Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The modernization roadmap (React 17/18 upgrade, `semantic-ui-react` exit, projec

### Dual build targets

1. **Library** (`src/library/`) — Entry point `src/library/index.ts`, built via `webpack.library.config.mjs` to `dist/`. Exports the `UIRender` component as UMD. `react`, `react-dom`, and `moment` are externalized (peer dependencies — the host app provides them), and so is `react/jsx-runtime`: JSX compiles to it (`babel.config.js` uses the automatic runtime), and a bundled copy would create elements through a different React than the host's. CSS is compiled from LESS and the real stylesheets, fonts and images ship **once** in the root `static/` folder — that is the payload hosts copy to their web root, because a name-only `Image` loads from `/static/images/<name>` (`FILE.PATH_IMAGES`; the library build bakes `process.env` to `{NODE_ENV: 'production'}` on purpose, so no homepage reaches it — `src/core/common/variables/index.js` applies the homepage prefix only when one is set). `dist/static/all.css` and `font.css` are one-line `@import` re-exports of it, so bundler imports of the dist path keep working; `semantic.css` is a 0-byte stub in both places. Packaging is gated by `npm run test:pack` (budgets + a packed-tarball server-render smoke) — never re-add an asset copy under `dist/static/`, the duplicate guard fails the build.
1. **Library** (`src/library/`) — Entry point `src/library/index.ts`, built via `webpack.library.config.mjs` to `dist/`. Exports the `UIRender` component as UMD. `react`, `react-dom`, and `moment` are externalized (peer dependencies — the host app provides them), and so is `react/jsx-runtime`: JSX compiles to it (`babel.config.js` uses the automatic runtime), and a bundled copy would create elements through a different React than the host's. CSS is compiled from LESS and the real stylesheets and fonts ship **once** in the root `static/` folder — that is the payload hosts copy to their web root. No images ship: `static/images/flags/` stopped on 2026-10-01 (`docs/UPGRADE-PLAN.md` §10), and `npm run test:pack:budget` fails a tarball that carries it again. A name-only `Image` loads the HOST's `/static/images/<name>` (`FILE.PATH_IMAGES`; the library build bakes `process.env` to `{NODE_ENV: 'production'}` on purpose, so no homepage reaches it — `src/core/common/variables/index.ts` applies the homepage prefix only when one is set). `dist/static/all.css` and `font.css` are one-line `@import` re-exports of it, so bundler imports of the dist path keep working; `semantic.css` is a 0-byte stub in both places. Packaging is gated by `npm run test:pack` (budgets + a packed-tarball server-render smoke) — never re-add an asset copy under `dist/static/`, the duplicate guard fails the build.
2. **Demo app** (`src/demo/`) — Entry chain `src/demo/index.js` → `src/demo/main.jsx` (`createRoot`) → `src/demo/App.jsx`, built via `webpack.demo.config.mjs`. Used for development and GitHub Pages demo. The three entry files moved out of the `src/` root at §9.9-H3 so the top level reads `core/ | demo/ | library/ | style/` and the library/demo boundary is visible from the directory listing alone. Note it says `createRoot`, not `ReactDOM.render` — the demo mounts through the React 18 root API. It renders under `<StrictMode>` since §9.3 step 7; `src/demo/examples/__tests__/examples.strict-mode.test.js` pins that every example renders and behaves the same with it and without it.

### Core rendering engine (`src/core/engine/`)
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,18 @@ import 'eis-ui-render/static/all.css' // or 'eis-ui-render/dist/static/all.css
import 'eis-ui-render/static/font.css' // icon font — only if the host does not provide its own
```

An `Image` given only a `name` loads it from `/static/images/<name>`, relative to the host's web
root, so those files must be reachable there. Copy the package's `static/` folder into the web root
as part of the build; it is self-contained:
Copy the package's `static/` folder into the web root as part of the build. It holds the
stylesheets and the icon font, and is self-contained:

```bash
cp -R node_modules/eis-ui-render/static ./public/
```

An `Image` given only a `name` loads it from `/static/images/<name>`, relative to the host's web
root. The package ships no images, so those files are the host's own. Earlier releases also
carried `static/images/flags/`, 266 country-flag SVGs that nothing in the library used; a host that
links them now ships its own copy.

A host that serves `static/` under a sub-path or a CDN sets `path` (or `src`) on the `Image` in its
meta; the library build fixes its environment at build time, so no host environment variable reaches
it. Releases 0.32.4 to 0.34.3 resolved a name-only `Image` to a page-relative
Expand Down
2 changes: 1 addition & 1 deletion docs/SUPPORTED-PROPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ THE ARITHMETIC, derived from the installed `semantic-ui-react` rather than estim

### `Dropdown` — in-house, no semantic-ui-react

`src/core/components/Dropdown.tsx`, 364 lines. Replaced the wrapper in §9.7-F1 step 3 part 2.
`src/core/components/Dropdown.tsx`, 369 lines. Replaced the wrapper in §9.7-F1 step 3 part 2.

The wrapper already owned the external API: the `onChange(value, name, event)` signature, option sanitisation, case-insensitive dedup on addition, and the cascading reset are all wrapper code, and none of it moved. Only the `<DropDown/>` element at the bottom changed — it is now the in-house `Listbox`, under the same import alias. Two entry points, and they differ: `mapper.tsx` imports the memoised default export for `view: "Dropdown"`, while `modules/form/inputs/DropdownField.ts` imports the NAMED export for `view: "Select"` — which is the majority path.

Expand Down
4 changes: 2 additions & 2 deletions docs/SUPPORTED-VIEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Two consequences worth knowing before authoring meta:
| `Label` | `FIELD.TYPE.LABEL` | `Label` | `mapper.tsx` switch | A `<label>` element wrapping `items` as its children. |
| `List` | `FIELD.TYPE.LIST` | `List` | `mapper.tsx` switch | Renders the node data array through `renderItem` inside a vertical container. Aliases: `ColList`, `VerticalList`. `RowList` and `HorizontalList` are the horizontal form. |
| `PieChart` | `FIELD.TYPE.PIE_CHART` | `PieChart` | `mapper.tsx` switch | Pie or donut chart drawn as inline SVG from the node data. `mapItems` maps each datum onto the chart shape; `legends`, `pointers` and `sort` control labelling and order. |
| `Popup` | `FIELD.TYPE.POPUP` | `PopupContent` | `mapper.tsx` switch | Registers its `items` on the render instance under `id` and renders nothing in place; the content is mounted only when the `popupOpen` action opens it. An `id` containing `{...}` is kept as a template and interpolated at open time, so one declaration can serve many rows. |
| `Popup` | `FIELD.TYPE.POPUP` | `PopupContent` | `mapper.tsx` switch | Registers its `items` on the render instance under `id` and renders nothing in place; the content is mounted only when the `popupOpen` action opens it. An `id` containing `{...}` is kept as a template and interpolated at open time, so one declaration can serve many rows. The popup shows the node's `title` above its `items`; no other key of the node has an effect. |
| `ProgressSteps` | `FIELD.TYPE.PROGRESS_STEPS` | `ProgressSteps` | `mapper.tsx` switch | Step indicator whose items each carry `step`, `label` and `content`, any of which may itself be a view declaration. |
| `Row` | `FIELD.TYPE.ROW` | `Row` | `mapper.tsx` switch | Horizontal flex container that renders `items` as its children. Alias: `HorizontalLayout`. |
| `RowList` | `FIELD.TYPE.ROW_LIST` | `List` | `mapper.tsx` switch | Renders the node data array through `renderItem` inside a horizontal container. Alias: `HorizontalList`. Same component as `List`, with the `row` flag set. |
Expand Down Expand Up @@ -117,7 +117,7 @@ A name that is not below stays an unresolved string rather than raising.
| `fetch` | `FIELD.ACTION.FETCH` | `engine/rules.tsx` | The global `fetch`. |
| `onApplyPeriods` | `FIELD.ACTION.ON_APPLY_PERIODS` | `engine/rules.tsx` | Sends all form data to the host `updateExperienceData` API call and restarts the form with the normalized response. Does nothing when the host supplies no `updateExperienceData`; failures open an error popup. |
| `popup` | `FIELD.ACTION.POPUP` | `engine/rules.tsx` | Opens an alert popup with the given title and content. |
| `popupOpen` | `FIELD.ACTION.POPUP_OPEN` | `engine/rules.tsx` | Opens the content registered by a `Popup` node with the given `id`. Event arguments are filtered out, and the row index is forwarded so fields inside the popup address the row that opened it. |
| `popupOpen` | `FIELD.ACTION.POPUP_OPEN` | `engine/rules.tsx` | Opens the content registered by a `Popup` node with the given `id`. Event arguments are filtered out, and the row index is forwarded so fields inside the popup address the row that opened it. Of an options object after the `id`, only `relativeIndex` and `relativePath` are read, for a template popup's row. |
| `removeData` | `FIELD.ACTION.REMOVE_DATA` | `engine/rules.tsx` | Removes the current row from the parent instance `dataKind` array through the parent form array mutator. Warns and does nothing when the node has no parent instance and form. |
| `reset` | `FIELD.ACTION.RESET` | `engine/rules.tsx` | Resets the form to its initial values. |
| `setState` | `FIELD.ACTION.SET_STATE` | `engine/rules.tsx` | Writes the incoming value into the render instance state at the path given as the argument, for example `setState,active.tab`. This is the channel `{state.…}` templates and `showIf` read; a `Dropdown` or `Select` with a `name` and no `onChange` gets `setState,<name>` installed automatically. |
Expand Down
Loading
Loading