@zeyos/zx 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/DESIGN-SYSTEM.md +136 -0
  3. package/MIGRATION.md +155 -4
  4. package/README.md +24 -13
  5. package/dist/types/compat/map/data.d.ts +3 -2
  6. package/dist/types/components/account-menu/account-menu.d.ts +144 -0
  7. package/dist/types/components/app-rail/app-rail.d.ts +250 -0
  8. package/dist/types/components/app-sidebar/app-sidebar.d.ts +169 -0
  9. package/dist/types/components/avatar/avatar.d.ts +100 -0
  10. package/dist/types/components/chart/chart.d.ts +321 -0
  11. package/dist/types/components/date-picker/month-picker.d.ts +6 -0
  12. package/dist/types/components/dialog/dialog.d.ts +9 -0
  13. package/dist/types/components/dock/dock.d.ts +495 -0
  14. package/dist/types/components/dropdown/dropdown.d.ts +2 -2
  15. package/dist/types/components/field/field.d.ts +14 -0
  16. package/dist/types/components/field-upload/field-upload.d.ts +37 -4
  17. package/dist/types/components/form/form.d.ts +25 -3
  18. package/dist/types/components/grid/grid.d.ts +172 -0
  19. package/dist/types/components/launcher/launcher.d.ts +300 -0
  20. package/dist/types/components/layout/layout.d.ts +4 -4
  21. package/dist/types/components/menu-button/menu-button.d.ts +10 -2
  22. package/dist/types/components/modal/modal.d.ts +25 -0
  23. package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +7 -1
  24. package/dist/types/components/questionnaire/items.d.ts +327 -0
  25. package/dist/types/components/questionnaire/questionnaire.d.ts +449 -0
  26. package/dist/types/components/sheet/sheet-stack.d.ts +167 -0
  27. package/dist/types/components/sheet/sheet.d.ts +294 -0
  28. package/dist/types/components/split-view/split-view.d.ts +2 -21
  29. package/dist/types/components/table/table.d.ts +219 -12
  30. package/dist/types/components/tooltip/tooltip.d.ts +2 -2
  31. package/dist/types/components/value-list/value-list.d.ts +24 -3
  32. package/dist/types/core/dom.d.ts +114 -0
  33. package/dist/types/core/drag-axis.d.ts +111 -0
  34. package/dist/types/core/position.d.ts +4 -2
  35. package/dist/types/index.d.ts +12 -2
  36. package/dist/zx-compat.esm.js +641 -277
  37. package/dist/zx-compat.esm.min.js +1 -1
  38. package/dist/zx-compat.global.js +7609 -2236
  39. package/dist/zx-compat.global.min.js +3 -3
  40. package/dist/zx-zeyos.esm.js +546 -87
  41. package/dist/zx-zeyos.esm.min.js +1 -1
  42. package/dist/zx.css +1452 -101
  43. package/dist/zx.esm.js +7952 -2592
  44. package/dist/zx.esm.min.js +3 -3
  45. package/dist/zx.global.js +7952 -2592
  46. package/dist/zx.global.min.js +3 -3
  47. package/dist/zx.min.css +1 -1
  48. package/docs/api.json +2276 -337
  49. package/docs/llms.md +426 -30
  50. package/docs/llms.txt +21 -9
  51. package/package.json +4 -2
  52. package/src/compat/globals.js +3 -1
  53. package/src/compat/map/data.js +31 -9
  54. package/src/components/account-menu/account-menu.css +70 -0
  55. package/src/components/account-menu/account-menu.js +208 -0
  56. package/src/components/app-rail/app-rail.css +107 -0
  57. package/src/components/app-rail/app-rail.js +668 -0
  58. package/src/components/app-sidebar/app-sidebar.css +68 -0
  59. package/src/components/app-sidebar/app-sidebar.js +388 -0
  60. package/src/components/avatar/avatar.css +61 -0
  61. package/src/components/avatar/avatar.js +222 -0
  62. package/src/components/button/button.css +0 -1
  63. package/src/components/chart/chart.css +61 -0
  64. package/src/components/chart/chart.js +518 -0
  65. package/src/components/date-picker/month-picker.js +9 -0
  66. package/src/components/dialog/dialog.js +11 -4
  67. package/src/components/dock/dock.css +228 -0
  68. package/src/components/dock/dock.js +977 -0
  69. package/src/components/dropdown/dropdown.js +1 -1
  70. package/src/components/field/field.js +2 -0
  71. package/src/components/field-upload/field-upload.js +9 -4
  72. package/src/components/form/form.js +6 -3
  73. package/src/components/grid/grid.css +6 -0
  74. package/src/components/grid/grid.js +213 -0
  75. package/src/components/launcher/launcher.css +100 -0
  76. package/src/components/launcher/launcher.js +557 -0
  77. package/src/components/layout/layout.js +2 -2
  78. package/src/components/menu-button/menu-button.js +27 -2
  79. package/src/components/modal/modal.css +5 -1
  80. package/src/components/modal/modal.js +37 -2
  81. package/src/components/multi-value-editor/multi-value-editor.js +2 -1
  82. package/src/components/questionnaire/items.js +370 -0
  83. package/src/components/questionnaire/questionnaire.css +387 -0
  84. package/src/components/questionnaire/questionnaire.js +1033 -0
  85. package/src/components/select/select.css +0 -1
  86. package/src/components/sheet/sheet-stack.js +304 -0
  87. package/src/components/sheet/sheet.css +351 -0
  88. package/src/components/sheet/sheet.js +551 -0
  89. package/src/components/split-view/split-view.js +76 -161
  90. package/src/components/table/table.css +43 -0
  91. package/src/components/table/table.js +523 -45
  92. package/src/components/tooltip/tooltip.js +5 -2
  93. package/src/components/value-list/value-list.js +6 -3
  94. package/src/core/dom.js +302 -0
  95. package/src/core/drag-axis.js +203 -0
  96. package/src/core/position.js +68 -22
  97. package/src/index.js +19 -2
  98. package/styles/tokens/dark.css +2 -3
  99. package/styles/tokens/global.css +5 -5
  100. package/styles/tokens/semantic.css +5 -3
  101. package/styles/tokens/themes.css +1 -1
  102. package/styles/zx.css +10 -1
  103. package/dist/types/components/permission/permission.d.ts +0 -96
  104. package/src/components/permission/permission.css +0 -47
  105. package/src/components/permission/permission.js +0 -201
package/CHANGELOG.md CHANGED
@@ -8,6 +8,93 @@ and friends remain the complete record.
8
8
 
9
9
  ## Unreleased
10
10
 
11
+ ## 3.0.0 — 2026-08-24
12
+
13
+ ### Added
14
+
15
+ - **Xenon application shell components.** `Launcher` combines deterministic local ranking with
16
+ abortable grouped sources and a Cmd/Ctrl+K dialog; `Avatar` provides a stable initials fallback;
17
+ `AccountMenu` composes identity with an APG menu; `AppSidebar` is expanded vertical navigation;
18
+ and minimized `AppRail` keeps descendants in pointer-, focus-, and keyboard-accessible flyouts
19
+ for both vertical and horizontal placement. All route, permission, session, and persistence work
20
+ remains application-owned behind cancelable events.
21
+ - **`Grid` and `Grid.BillingItems()`.** The public Table specialization keeps every Table feature
22
+ while providing a conventional editable billing schema for currencies, units, line totals, and
23
+ flat parent rows. The default line formula is quantity × unit price; tax, discount, rounding,
24
+ subtotal, validation, and persistence policy remain caller-owned.
25
+ - **Engine-neutral `Chart` and injected `ChartJsAdapter`.** Chart owns responsive canvas lifecycle,
26
+ loading/empty/error states, Xenon theme defaults, point-selection events, and a synchronized
27
+ semantic data table. Chart.js 4.5.1 is pinned only as a development/documentation asset; the Zx
28
+ runtime has no chart import and no runtime dependency.
29
+ - **Lateral anchored-overlay placement.** `position()`, `Dropdown`, `MenuButton`, and `Tooltip` now
30
+ accept left/right start/end variants for rail and account surfaces.
31
+
32
+ - **`Questionnaire`** — a guided, one-question-at-a-time flow for onboarding intake, service
33
+ checklists, audits and surveys, where a `Form` full of fieldsets is the wrong shape. The root is
34
+ a real `<form>` and the choices are native radios and checkboxes carrying the item name, so
35
+ `new FormData(questionnaire.toElement())` reads the answers and the keyboard contract inside a
36
+ choice group is the browser's. Three things go beyond a stack of fieldsets: an item carries a
37
+ `when` predicate and a `next` target, so the flow **branches** — conditions cascade, an
38
+ abandoned branch's answers drop out of `getAnswers()`, progress counts the questions actually
39
+ reachable, and Back retraces the path walked rather than an array index; an item's answer control
40
+ can be **any registered `Field` type** (`field: {type: 'date'}`), which is what lets a question
41
+ ask for a date, a number, a rating or an upload; and `validate` may return a **promise**, so a
42
+ question can be gated on a server check. `review: true` adds a summary screen with jump-back-to-
43
+ edit, `advance: 'auto'` moves on by itself after a single choice, and `1`–`9`/`a`–`z` shortcuts
44
+ are assigned and shown on each answer.
45
+
46
+ - **`Sheet`** — an edge-anchored `Dialog` covering both side-sheet and mobile-drawer patterns;
47
+ the two differ only in which edge they take, so `side` (`'start' | 'end' | 'top' | 'bottom'`,
48
+ logical) replaces a second component. `modal` is three-way rather than a boolean because the
49
+ three real behaviours do not collapse into two: `true` hands focus containment, page inertness,
50
+ Escape and the backdrop to the browser via `showModal()`, while `'trap-focus'` and `false` open
51
+ non-modally and re-implement only what they still want. `backdrop: 'dim'|'blur'|'none'` applies
52
+ to modal sheets alone — `::backdrop` does not render for a non-modal dialog, and a painted
53
+ stand-in would make a non-blocking sheet look blocking. Entry **and exit** animate, which a
54
+ `<dialog>` normally cannot do, via `@starting-style` and `transition-behavior: allow-discrete`
55
+ on `display`/`overlay`. `resizable`, `snap` detents and swipe-to-dismiss are deliberately one
56
+ gesture whose meaning is decided when the pointer settles, so the sheet follows the pointer the
57
+ whole way instead of pinning at its minimum and then vanishing.
58
+ - **`SheetStack`** — several sheets as one drill-down. Small on purpose: nested dialogs already
59
+ stack in the top layer by open order and Escape already closes only the topmost, so no z-index
60
+ bookkeeping and no unwinding logic. `stack` slides covered sheets back, scales them down and
61
+ makes them `inert`; `cascade` shifts each clear of the ones in front by their **measured** size
62
+ so they sit side by side and all stay usable — usually the right one for an ERP screen, where
63
+ the parent record should stay readable while a line item is edited.
64
+ - **`Dock`** — a stack of collapsible, resizable panes: the docked inspector column of a design
65
+ tool, and the detail side of a master–detail screen. A pane is either titled or a **tab group**
66
+ whose strip replaces the title. Giving the dock a `content` turns it into a region with panes on
67
+ either `side` of it, and nesting one dock in another's pane gives a workbench. Sizes, collapsed
68
+ panes and active tabs persist through `storageKey`; content factories run on first reveal.
69
+ - **`Dock.adopt(sheet)`** — a dock can take over a `Sheet`'s positioning, so the sheet becomes a
70
+ track in the dock's flow instead of an overlay. A dock is a flex container by construction and
71
+ therefore always a valid host, which is why docking needs no arrangement from the application.
72
+ `dockAt` hands the sheet back to a free overlay below a breakpoint measured on the **dock's own
73
+ width**, so a dock inside a split pane behaves correctly where a viewport media query would not.
74
+ Nothing is rebuilt across the handoff: the element moves and reopens in place, so DOM state and
75
+ listeners survive and no `open`/`close` is emitted for what is only a change of address.
76
+ - **`--zx-overlay-blur`** — tier-2 semantic token behind `Sheet`'s `'blur'` backdrop, default `8px`.
77
+
78
+ ### Changed
79
+
80
+ - **`SplitView` now shares one axis-drag engine with `Sheet` and `Dock`**, extracted to
81
+ `core/drag-axis.js`: pointer capture, one write per frame, telling a click from a zero-distance
82
+ drag, and the WAI-ARIA keyboard map. Behaviour is unchanged. `resolveSize` moved to the kernel
83
+ and is re-exported from `split-view.js`, so every existing import keeps working.
84
+ - **`Modal` gained three protected seams** — `mountTarget()`, `_show()` and `_isRealClose()` — so a
85
+ subclass can live somewhere other than `document.body`, open non-modally, and re-host itself.
86
+ `Dialog`'s size application became the overridable `_applySize()`. No public behaviour changed.
87
+ - **The modal scroll lock keys off `:modal` rather than `[open]`**, so a non-modal dialog no longer
88
+ locks the page behind it. `Modal` and `Dialog` always open modally, so neither is affected.
89
+
90
+ ### Removed
91
+
92
+ - **`Permission` is removed**, not just deprecated. 2.3.0 kept the class around for
93
+ `gx.zeyos.Permission` while pointing new code at `Select.permission()`; there is no longer a
94
+ second implementation to keep in sync, and `gx.zeyos.Permission` now builds directly on
95
+ `Select.permission()` instead of wrapping the removed class. The legacy constructor, options,
96
+ `get()`/`set()`, and the `change` event are unchanged — only the `zx.Permission` export is gone.
97
+
11
98
  ## 2.3.0 — 2026-08-23
12
99
 
13
100
  ### Added
@@ -0,0 +1,136 @@
1
+ # Xenon design-system audit
2
+
3
+ Audit date: 2026-08-24. Xenon is the design system; Zx is its dependency-free JavaScript
4
+ implementation. This document records the current coverage against ZeyOS Classic and the work
5
+ needed for an incremental adoption that keeps the existing routing and business logic.
6
+
7
+ ## System boundary
8
+
9
+ Xenon has four layers:
10
+
11
+ 1. **Foundations** — semantic tokens, typography, spacing, density, themes, icons, motion, i18n,
12
+ accessibility rules, and the safe DOM kernel.
13
+ 2. **Components** — lifecycle-safe controls and containers with one options/events/destroy model.
14
+ 3. **Patterns** — repeatable business interactions such as global launch, account/preferences,
15
+ record detail, transaction entry, filtering, and empty/loading/error handling.
16
+ 4. **Application layouts** — rails, bars, workspaces, master/detail, dashboards, inboxes, wizards,
17
+ and responsive shell geometry.
18
+
19
+ This separation follows the enterprise-system intent described by the
20
+ [Carbon Design System](https://carbondesignsystem.com/all-about-carbon/what-is-carbon/) and
21
+ [SAP Fiori design principles](https://experience.sap.com/fiori-design-web/design-principles/),
22
+ without copying either system's code, assets, or component contracts.
23
+
24
+ Zx currently has more than 50 public component classes, 63 registered documentation/demo entries,
25
+ a generated API reference, bundled local icons, and no runtime dependency. The foundations,
26
+ component layer, and persistent application shell now cover the first ZeyOS adoption wave; domain
27
+ patterns remain intentionally application-owned until their business invariants are specified.
28
+
29
+ ## ZeyOS adoption boundary
30
+
31
+ ZeyOS Classic does not use `gx`. Across its 30 module files it has roughly 2,500 `UI.*` calls and
32
+ 2,600 `PG.*` calls. `PG` already owns navigation, transport, history, exit guards, and page
33
+ lifecycle and remains authoritative.
34
+
35
+ The existing compact DOM surface has 2,668 executable builder calls: 871 bare `__()` calls, 1,710
36
+ parent-returning `parent.__()` calls, and 87 child-returning `parent.$__()` calls. Zx now provides
37
+ the exact compact builder plus pure append/property/event helpers. Existing global and prototype
38
+ names remain application-owned delegation seams; Zx does not install or replace them.
39
+
40
+ Migration therefore replaces `UI.new*` implementations one family at a time, keeps their current
41
+ DOM/value contracts until call sites reach zero, and leaves `PG`, `MD`, routes, and server payloads
42
+ in place. See [MIGRATION.md](./MIGRATION.md) for the ordering and shell invariants.
43
+
44
+ ## Coverage ledger
45
+
46
+ | Capability in current ZeyOS | Xenon/Zx status | Decision |
47
+ | --- | --- | --- |
48
+ | Buttons, inputs, toggles, dates, selects, checklists, tags | Covered by public components | Replace `UI.new*` families incrementally and preserve value/event contracts. |
49
+ | Forms and fieldsets | Covered, including component-backed field adapters | Use for record editors; keep validation/business rules application-owned. |
50
+ | Dialogs, sheets, dropdowns, context menus, tooltips, messages | Covered | Consolidate duplicate menu behavior before building account/launcher surfaces. |
51
+ | Tabs, panels, toolbar, breadcrumbs, stepper, split view, dock | Covered | Compose layouts; do not let navigation components own routes. |
52
+ | Sorting, selection, filtering, pagination, trees/finder | Covered | Suitable for generic data screens. |
53
+ | Editable billing/transaction rows | Covered at generic-grid level | `Grid.BillingItems()` composes typed editable currency/unit columns and flat hierarchy over `Table`. Tax, subtotal, posting, rounding, and persistence stay domain code. |
54
+ | Global launcher/search | Covered | `Launcher` combines ranked local applications with abortable grouped sources. ZeyOS still filters the catalogue and resolves selection through `PG`. |
55
+ | Account/profile/preferences menu | Covered at presentation level | `Avatar` and `AccountMenu` provide identity and action UI. ZeyOS supplies role-filtered actions and owns preferences, authentication, and logout. |
56
+ | Persistent app rail / side navigation | Covered | `AppSidebar` is the expanded vertical tree; minimized `AppRail` uses flyouts in every orientation. Both are route- and persistence-agnostic. |
57
+ | Charts and analytical summaries | Covered through an adapter | `Chart` is engine-neutral and accessible; `ChartJsAdapter` accepts an injected Chart.js 4 engine. Chart.js is documentation/test tooling only. |
58
+ | Local product/module icons | Partial | Use bundled icons or registered local assets; do not require the optional remote Font Awesome kit. |
59
+ | Domain entity selectors/cards/links | Partial | Build patterns on `Select`, Table, Panel, and ContextMenu after the shell blockers. |
60
+ | Persistent notification/activity center | Missing, lower priority | `Message` covers ephemeral feedback, not read/unread activity history. |
61
+
62
+ ### Launcher contract
63
+
64
+ The current launcher searches applications, recent records, and grouped remote record types. A
65
+ replacement supplies pinned-order ranking, request cancellation, Cmd/Ctrl+K, listbox keyboard
66
+ behavior, native link metadata, and a cancelable action. Permission filtering, active-route state,
67
+ cache and recent-history policy remain inputs from ZeyOS, which resolves actions through `PG.go()`.
68
+ The component is deliberately not a second router.
69
+
70
+ ### Account contract
71
+
72
+ The current account surface includes identity, role-dependent links, language, authentication and
73
+ logout, theme and menu-position preferences, and About/version content. A shared `Menu` should
74
+ first centralize the keyboard/typeahead/selection behavior currently duplicated by `MenuButton`
75
+ and `ContextMenu`; `AccountMenu` then composes that primitive with `Avatar`/`Identity` and emits
76
+ actions without owning routes or session state. `AccountMenu` now provides that composition over
77
+ `MenuButton`; a future shared low-level `Menu` remains an internal consolidation opportunity, not
78
+ an adoption blocker.
79
+
80
+ ## Table and transaction follow-ups
81
+
82
+ The enhanced `Table` now keeps values numeric while formatting per-row locales, currencies, units,
83
+ and decimals; numeric types infer `NumberField` editors. Flat `parentId` data is projected into a
84
+ cycle-safe ARIA treegrid with local sibling sorting and expand/collapse APIs.
85
+
86
+ `Grid.BillingItems()` now packages the conventional description, quantity, unit, unit-price,
87
+ currency, line-total, and hierarchy schema while retaining Table's editing contract. Useful
88
+ follow-ups, deliberately separate from this generic preset:
89
+
90
+ - summary/footer rows and grouped subtotals;
91
+ - column reorder and user-persisted column state;
92
+ - product-specific invoice/transaction presets with tax, discount, rounding, and formula golden tests;
93
+ - server persistence, optimistic rejection, and undo owned by the application/controller layer.
94
+
95
+ ## Chart-engine candidates
96
+
97
+ Chart.js was selected for the first adapter. It is pinned at 4.5.1 as a development dependency for
98
+ tests and the documentation asset, but is never imported by Zx runtime source. Applications inject
99
+ their chosen engine into the adapter. Published browser artifact sizes below are approximate and
100
+ remain useful when choosing a different future adapter.
101
+
102
+ | Engine | Current state at audit | Approx. browser cost | Best fit | Main trade-off |
103
+ | --- | --- | ---: | --- | --- |
104
+ | [Chart.js](https://github.com/chartjs/Chart.js/releases) 4.5.1 | Mature, active, MIT | 209 kB / 71 kB gzip (UMD) | Broad default: bar, line, doughnut, mixed business charts | Larger than focused engines; canvas requires a separate accessible data summary. |
105
+ | [Frappe Charts](https://github.com/frappe/charts/releases) 1.6.x | Zero-dependency SVG, ERP-oriented, MIT | 69 kB / 18 kB gzip (UMD) | Lean dashboards with common chart types | GitHub release and npm publication were out of step; ecosystem and extension surface are smaller. |
106
+ | [uPlot](https://github.com/leeoniya/uPlot) 1.6.32 | Active, MIT, highly optimized | 51 kB JS + 2 kB CSS / about 23 kB gzip | Dense time-series and operational telemetry | Deliberately narrow; not a general categorical/stacked business-chart toolkit. |
107
+ | [Apache ECharts](https://echarts.apache.org/en/changelog.html) 6.1.0 | Very capable, active, Apache-2.0 | 1.12 MB / 369 kB gzip (full build) | Advanced analytical visualization | Too large as Xenon's default; only sensible as an opt-in advanced adapter or custom build. |
108
+
109
+ Implemented architecture: `Chart` accepts an injected engine adapter, maps Xenon semantic tokens,
110
+ owns loading/empty/error states, and mirrors its data in an accessible table. Chart.js is the broad
111
+ default adapter; Frappe Charts remains the lean ERP-oriented alternative, uPlot a specialized
112
+ time-series candidate, and ECharts an opt-in advanced adapter. Any additional package still
113
+ requires explicit dependency approval.
114
+
115
+ ## Review corrections completed
116
+
117
+ - Generated API records no longer let helper typedefs overwrite component options; inline JSDoc
118
+ tags are parsed, and audited runtime events are present in types and documentation.
119
+ - Form documentation exposes `Form`, `Fieldset`, and `Field`; `MonthPicker` has its own constructor
120
+ type.
121
+ - Theme Studio destroys registered component instances on every rebuild and describes its honest
122
+ family-level coverage.
123
+ - Documentation separates Presets from green-accent Examples and uses callable preset names.
124
+ - Current source and documentation no longer carry branding from the retired framework experiment.
125
+
126
+ ## Recommended sequence
127
+
128
+ 1. Ship the Zx runtime and delegate the current compact DOM/event seams; verify no navigation or
129
+ listener regressions.
130
+ 2. Mount `Launcher`, `Avatar`/`AccountMenu`, and `AppSidebar`/`AppRail` behind the current shell
131
+ fixtures, permission filters, and preference store.
132
+ 3. Replace high-volume `UI.new*` families, one discriminating fixture set at a time.
133
+ 4. Introduce `Grid.BillingItems()` where its generic schema fits; add domain presets only with
134
+ formula and rounding fixtures.
135
+ 5. Inject Chart.js into `ChartJsAdapter` only on analytical surfaces that need it; keep the engine
136
+ out of the base Zx runtime bundle.
package/MIGRATION.md CHANGED
@@ -4,6 +4,136 @@ Zx replaces the MooTools-era `gx` UI libraries with dependency-free ES2022 modul
4
4
  compatibility bundle lets mapped legacy code keep running while classes are migrated one at a
5
5
  time. Compatibility constructors warn once per legacy class so remaining call sites are visible.
6
6
 
7
+ Xenon is the ZeyOS design system; Zx is its browser implementation. A complete migration therefore
8
+ means more than swapping constructors: foundations, components, application patterns, and layout
9
+ contracts must move together while routing and business behavior stay authoritative.
10
+
11
+ ## Introducing Xenon into ZeyOS Classic
12
+
13
+ The current ZeyOS Classic application is **not** a `gx.*` application. Its modules call the global
14
+ `UI` factories, use `PG` for routing and page lifecycle, and rely on an extended DOM API including a
15
+ CSS-like `__()` element builder. Do not call `gx.compat.installGlobals()` there: that opt-in helper
16
+ preserves an existing `__()` but installs unrelated `gx` globals and prototype compatibility that
17
+ the current application does not need.
18
+
19
+ The migration does not need a separate application bridge. Zx now exports the established builder
20
+ directly, including its exact compact tag and property conventions:
21
+
22
+ ```js
23
+ const node = zx.__('button#save.primary', {
24
+ Daction: 'save',
25
+ onclick: () => save()
26
+ }, 'Save');
27
+ ```
28
+
29
+ Zx does not install globals or alter DOM prototypes. The current runtime keeps owning its global
30
+ `__`, `_`, `Node._`, `Node.__`, `Node.$__`, and `Element.be` seams during the migration and delegates
31
+ their bodies to `zx.compactElement()`, `zx.appendContent()`, `zx.appendCompact()`,
32
+ `zx.appendCompactChild()`, and `zx.applyCompactProperties()`. Its `DOM.on`, `DOM.remEvt`, and
33
+ `DOM.fireEvt` facade likewise delegates to Zx's shared compact-event helpers, so registration,
34
+ removal, and synthetic firing always see the same handlers. Replace the implementations of
35
+ `UI.new*` component families progressively with Zx components; do not insert a second routing or
36
+ application abstraction between those components and `PG`.
37
+
38
+ ### Keep these authorities in place
39
+
40
+ - `PG` remains responsible for URL construction, history, transport, exit guards, page dispatch,
41
+ and the `page:beforeUnmount` / `page:mounted` lifecycle.
42
+ - Existing `MD` handlers and business logic continue receiving the same page data.
43
+ - Existing `UI.new*` call sites keep their DOM return values and `getV` / `setV` / chaining
44
+ contracts while each factory implementation is replaced. New code uses the Zx component API
45
+ directly; the old factory is removed when its call-site count reaches zero.
46
+ - Zx owns only the mounted component subtree and tears that subtree down exactly once.
47
+ - New client/schema-driven screens may use `@zeyos/zx/zeyos`; adopting that optional layer is not a
48
+ prerequisite for converting current server-rendered screens.
49
+
50
+ Safe bootstrap order is the normal Zx bundle, the current Classic runtime delegating its compact
51
+ DOM seams to Zx, then the existing `Z(data)` application bootstrap. Component actions must call
52
+ `PG.go()` for internal routes; do not let a navigation component fall back to `location.assign()`.
53
+
54
+ ### Recommended adoption waves
55
+
56
+ 1. Mount persistent shell components behind current lifecycle events: launcher, account menu,
57
+ application rail, detail chrome, and overlays.
58
+ 2. Replace the highest-volume `UI.new*` implementations—inputs, Selects, tabs, menus, dialogs, and
59
+ tables—one family at a time while preserving their existing call-site contract.
60
+ 3. Move record and transaction patterns only after old/new behavior has discriminating fixtures.
61
+ 4. Use direct Zx and the ZeyOS schema binding for new surfaces; retire an old factory only after its
62
+ remaining call-site count reaches zero.
63
+
64
+ ### Shell components and ownership
65
+
66
+ `Search` remains a field-level input. `Launcher` is the shell-level application/record surface: it
67
+ ranks local items, debounces and aborts grouped sources, ignores stale responses, and supplies the
68
+ Cmd/Ctrl+K dialog/listbox interaction. ZeyOS filters permissions, supplies apps/recent records,
69
+ decides caching, and handles the cancelable selection through `PG`; Launcher never becomes a
70
+ router.
71
+
72
+ `Avatar` and `AccountMenu` provide the identity trigger, profile header, grouped actions, focus
73
+ return, and compact rail presentation. ZeyOS still decides permission-dependent routes, language
74
+ and theme choices, authentication/logout, and About/version data. A selection is a request to the
75
+ application, not a session mutation.
76
+
77
+ `AppSidebar` is the expanded vertical application tree and is the only presentation with inline
78
+ children. Its collapsed state renders `AppRail`. A standalone rail may be vertical or horizontal,
79
+ but every child collection remains a hover/focus/keyboard flyout. Both components accept native
80
+ links or cancelable actions and expose active/collapsed/expanded state without persisting it.
81
+
82
+ Use bundled Zx icons or explicitly registered local assets. The optional ZeyOS icon helper's
83
+ remote Font Awesome kit is not appropriate for a dependency-free production shell.
84
+
85
+ ### Persistent shell contract
86
+
87
+ These invariants were validated while prototyping the replacement shell and remain binding for a
88
+ Xenon implementation:
89
+
90
+ - Application-menu position is `top`, `bottom`, `left`, `right`, or `none`, defaulting to `left`.
91
+ Persist it under `zeyos.appMenu.position` (scope-suffixed where separate workspaces share an
92
+ origin) and publish the resolved value on `:root[data-app-menu-effective]`.
93
+ - Sidebar minimization is a user choice, never a hover side effect. Keep the existing
94
+ `zeyos.appRail.expanded` preference while migrating and map it to
95
+ `AppSidebar.setCollapsed(!expanded)`. `AppRail` itself never expands labels or inline children.
96
+ - The minimized rail is 48 px and the expanded sidebar 184 px. The application bar is 48 px; tiles
97
+ are 30 px, glyphs 22 px, and compact controls 31 px. Workspace tools in a side layout remain
98
+ inside the rail, and page insets derive from the effective rail/bar geometry.
99
+ - Theme preference is `auto`, `light`, or `dark`, persisted under `zeyos.theme` and applied before
100
+ paint. `auto` follows the system color-scheme media query.
101
+ - The dark neutral ramp is a coal surface rebased from Carbon Gray 100 toward `#0b0c0e`. Avoid a
102
+ cyan/slate cast that competes with ZeyOS module colors; module accents must retain clear contrast
103
+ on both shell and content surfaces.
104
+
105
+ ### Migration proof points
106
+
107
+ Before replacing any Classic surface, verify that internal navigation and browser history still use
108
+ `PG.go()` without a full reload; page-scoped instances are destroyed exactly once; persistent shell
109
+ listeners do not multiply across navigation or language changes; launcher output matches permission,
110
+ app, recent, and search fixtures; account content matches ordinary/admin/developer roles; and the
111
+ production shell loads no remote UI or icon dependency.
112
+
113
+ The shell wiring stays direct:
114
+
115
+ ```js
116
+ const launcher = new zx.Launcher(null, {
117
+ items: applicationCatalogue,
118
+ sources: recordSources,
119
+ onselect(event) {
120
+ event.preventDefault();
121
+ PG.go(resolveLauncherRoute(event.detail.item));
122
+ }
123
+ });
124
+
125
+ const sidebar = new zx.AppSidebar(shellHost, {
126
+ items: applicationTree,
127
+ active: currentRouteId,
128
+ collapsed: !savedAppRailExpanded,
129
+ footer: accountMenu,
130
+ onselect(event) {
131
+ event.preventDefault();
132
+ PG.go(event.detail.href);
133
+ }
134
+ });
135
+ ```
136
+
7
137
  ## Deployment script swap
8
138
 
9
139
  For deployments that serve the old libraries directly from
@@ -25,8 +155,9 @@ with this order:
25
155
  ```
26
156
 
27
157
  The compatibility entry exposes both `window.zx` and `window.gx`. Element
28
- `store`/`retrieve`/`eliminate` is installed automatically. If the application uses `__()`, `_()`,
29
- `String.prototype.htmlSpecialChars`, or `Array.prototype.findBy`, opt in after both scripts load:
158
+ `store`/`retrieve`/`eliminate` is installed automatically. If a genuine gx application uses its
159
+ free parser, `_()`, `String.prototype.htmlSpecialChars`, or `Array.prototype.findBy`, opt in after
160
+ both scripts load. An existing `__()` is deliberately never replaced:
30
161
 
31
162
  ```js
32
163
  gx.compat.installGlobals();
@@ -251,14 +382,14 @@ list.setValues([1, 2]);
251
382
 
252
383
  For remote data pass `load: () => Promise<items>` and listen for `loaded`.
253
384
 
254
- ### `gx.zeyos.Permission` → `zx.Permission`
385
+ ### `gx.zeyos.Permission` → `zx.Select.permission()`
255
386
 
256
387
  ```js
257
388
  // gx
258
389
  const permission = new gx.zeyos.Permission(host, { value: true, groups });
259
390
 
260
391
  // Zx
261
- const permission = new zx.Permission(host, { value: 'public', groups });
392
+ const permission = zx.Select.permission(host, { value: true, groups });
262
393
  permission.on('change', (event) => save(event.detail.value));
263
394
  ```
264
395
 
@@ -295,6 +426,26 @@ table.addData([{ ID: 1, name: 'Ada' }]);
295
426
 
296
427
  Use `setData`, `addData`, `updateRow`, `removeRow`, and `getData` for row operations.
297
428
 
429
+ ### Billing/transaction rows → `zx.Grid.BillingItems()`
430
+
431
+ Use the generic preset when the existing screen has description, quantity, unit, unit price,
432
+ currency, total, and optional parent rows:
433
+
434
+ ```js
435
+ const items = zx.Grid.BillingItems(host, {
436
+ data: rows,
437
+ units: unitChoices,
438
+ currencies: currencyChoices,
439
+ oneditcommit(event) {
440
+ if (!controller.accept(event.detail.changes)) event.preventDefault();
441
+ }
442
+ });
443
+ ```
444
+
445
+ The default line total is quantity × unit price. Keep taxes, discounts, subtotal/group updates,
446
+ rounding policy, posting, server persistence, and undo in the existing controller. Override
447
+ `lineTotal` only when that calculation is a stable screen-level rule.
448
+
298
449
  ### `gx.zeyos.Tabbox` and `gx.bootstrap.Tabbox` → `zx.Tabbox`
299
450
 
300
451
  ```js
package/README.md CHANGED
@@ -1,10 +1,13 @@
1
- # Zx
1
+ # Xenon Design System (Zx)
2
2
 
3
- Zx is the dependency-free, vanilla-JavaScript component library for ZeyOS business applications:
4
- ES2022 modules, accessible native controls, semantic design tokens, and lifecycle-safe components.
5
- Source modules run directly in a browser; the distribution also provides ESM and classic-script
6
- bundles. An opt-in compatibility layer keeps existing MooTools-era `gx` code running while it is
7
- modernised.
3
+ Xenon is the dependency-free design system for ZeyOS business applications; Zx is its
4
+ vanilla-JavaScript implementation. It combines foundations, accessible components, repeatable
5
+ workflow patterns, and application layouts in plain ES2022 modules. Source modules run directly in
6
+ a browser; the distribution also provides ESM and classic-script bundles. An opt-in compatibility
7
+ layer remains available for genuine MooTools-era `gx` applications while they are modernised.
8
+
9
+ The [design-system audit](./DESIGN-SYSTEM.md) records current ZeyOS coverage, missing shell
10
+ patterns, the adoption boundary, transaction-grid follow-ups, and chart-engine candidates.
8
11
 
9
12
  ## Quick start
10
13
 
@@ -95,7 +98,8 @@ ZeyOS binding — see `src/zeyos/modules.js`.
95
98
  | `CheckButton` | Two-state pressed button with optional state-specific labels. |
96
99
  | `Toggle` | Native-button switch with a separate submitted value. |
97
100
  | `Search` | Search input with debounced input, submit, and clear events. |
98
- | `Select` | APG combobox with local or async filtering and a priority preset. |
101
+ | `Launcher` | Cmd/Ctrl+K application and record launcher with ranked local items and abortable grouped sources. |
102
+ | `Select` | APG combobox with local or async filtering, pinned fixed items, and priority/permission presets. |
99
103
  | `Checklist` | Searchable checkbox group with optional async loading. |
100
104
  | `TagPicker` | Multi-select combobox that keeps its selection as removable tags. |
101
105
  | `NumberField` | APG spinbutton with step buttons, ranges, units, and wrapping. |
@@ -122,12 +126,16 @@ ZeyOS binding — see `src/zeyos/modules.js`.
122
126
  | `MenuButton` | APG menu button built on `Dropdown`. |
123
127
  | `ContextMenu` | APG right-click menu for a region or, via `selector`, per row. |
124
128
  | `Tooltip`, `tooltip()`, `describe()` | Hover/focus description bubble anchored with `position()`. |
129
+ | `Avatar` | Fixed-size user image with initials fallback and optional presence. |
130
+ | `AccountMenu` | Identity trigger and grouped account actions over `MenuButton`. |
125
131
 
126
132
  ### Data
127
133
 
128
134
  | API | Description |
129
135
  | --- | --- |
130
- | `Table` | Semantic sortable table with local/server sorting, row selection, and opt-in inline cell/row editing. |
136
+ | `Table` | Sortable/selectable table with typed transaction columns, flat-data hierarchy/treegrid projection, and opt-in cell/row editing. |
137
+ | `Grid`, `Grid.BillingItems()` | Table-compatible preset surface with editable currencies, units, totals, and sub-items. |
138
+ | `Chart`, `ChartJsAdapter` | Accessible engine-neutral chart host and explicitly injected Chart.js adapter. |
131
139
  | `DataFilter` | Declarative select, text, and custom filters for client-side row sets. |
132
140
  | `TreeView` | APG tree with lazy children, filtering, and tri-state checkboxes. |
133
141
  | `Finder` | Miller-columns hierarchy browser with an optional preview pane. |
@@ -137,10 +145,10 @@ ZeyOS binding — see `src/zeyos/modules.js`.
137
145
 
138
146
  | API | Description |
139
147
  | --- | --- |
140
- | `Permission` | Private, public, or group-level permission selector. |
141
148
  | `Field` | Label, description, validation state, and adapter-backed form control. |
142
149
  | `Fieldset` | Native fieldset that owns and coordinates fields. |
143
150
  | `Form` | Form composition, values, validation, highlighting, and actions. |
151
+ | `Questionnaire` | Guided one-question-at-a-time flow: branching, path-aware progress, review. |
144
152
  | `ValueList` | Validated, sortable tag/chip editor. |
145
153
  | `MultiValueEditor` | Ordered editable rows with add, remove, and move controls. |
146
154
  | `FieldUpload` | Click/drop file upload with progress, abort, validation, and preview. |
@@ -154,6 +162,8 @@ ZeyOS binding — see `src/zeyos/modules.js`.
154
162
  | `MasterPanel` | Full-height application panel with fixed header actions and footer. |
155
163
  | `Tabbox` | APG tabs in four appearances, with lazy content, closing, badges, and disabled states. |
156
164
  | `NavigationBar` | Responsive application navigation with optional tab panels and overflow. |
165
+ | `AppSidebar` | Expanded vertical application navigation with inline disclosure children. |
166
+ | `AppRail` | Minimized vertical/horizontal application navigation with flyout-only descendants. |
157
167
  | `Toolbar` | APG toolbar: one tab stop, arrow-key movement, and overflow into a menu. |
158
168
  | `SplitView` | Resizable two-pane split with a keyboard-operable separator. |
159
169
  | `Stepper` | Linear multi-step progress with completed, active, and error states. |
@@ -241,7 +251,7 @@ through, so a preset rethemes light, dark, and auto at once:
241
251
 
242
252
  Light surfaces take the 600 and 700 stops, dark ones take 300, 400, and 500 — so keep 600 legible
243
253
  against white and 400 against near-black, and `--zx-color-on-accent` stays correct in both. The
244
- [theme studio](https://zx.zeyos.com/theme.html) renders every component under a live theme and
254
+ [theme studio](https://zx.zeyos.com/theme.html) renders every component family under a live theme and
245
255
  exports the result.
246
256
 
247
257
  Anything beyond the accent is a semantic token override, without reaching into component CSS:
@@ -273,7 +283,7 @@ JavaScript positioning fallback.
273
283
 
274
284
  ## Development
275
285
 
276
- Install the single development dependency and start the no-build demo server:
286
+ Install the development toolchain and start the no-build demo server:
277
287
 
278
288
  ```sh
279
289
  npm install
@@ -318,12 +328,13 @@ During an incremental migration, load the global API before the compatibility bu
318
328
  <script src="/assets/zx.global.js"></script>
319
329
  <script src="/assets/zx-compat.global.js"></script>
320
330
  <script>
321
- // Only when old code relies on __(), _(), or prototype conveniences:
331
+ // Only for gx-era free functions; an existing ZeyOS __() is preserved:
322
332
  gx.compat.installGlobals();
323
333
  </script>
324
334
  ```
325
335
 
326
336
  The compatibility bundle always exposes `window.gx` and installs only the element
327
337
  `store`/`retrieve`/`eliminate` shim automatically. Legacy globals and prototype conveniences are
328
- an explicit opt-in through `gx.compat.installGlobals()`. See [MIGRATION.md](./MIGRATION.md) for
338
+ an explicit opt-in through `gx.compat.installGlobals()`; it never replaces an existing `__`.
339
+ See [MIGRATION.md](./MIGRATION.md) for
329
340
  class mappings, script replacement, deliberate behavior changes, and unsupported legacy APIs.
@@ -30,13 +30,14 @@ export declare class Checklist extends ChecklistBase {
30
30
  export declare class BootstrapChecklist extends ChecklistBase {
31
31
  static legacyName: string;
32
32
  }
33
- /** Legacy permission selector. */
33
+ /** Legacy permission selector, backed by the `Select.permission()` preset. */
34
34
  export declare class Permission extends GxWrapper {
35
35
  static legacyName: string;
36
36
  /** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
37
37
  constructor(display: Element | string | null, options?: Record<string, any>);
38
38
  /** @returns {unknown} */ get(): unknown;
39
- /** @param {unknown} value @param {boolean} [silent=false] @returns {this} */ set(value: unknown, silent?: boolean): this;
39
+ /** @param {unknown} value @param {boolean} [silent=false] @returns {this} */
40
+ set(value: unknown, silent?: boolean): this;
40
41
  }
41
42
  /** Shared full Table wrapper. */
42
43
  declare class TableBase extends GxWrapper {