@zeyos/zx 2.2.1 → 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 (117) hide show
  1. package/CHANGELOG.md +197 -0
  2. package/DESIGN-SYSTEM.md +136 -0
  3. package/MIGRATION.md +155 -4
  4. package/README.md +51 -14
  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 +74 -9
  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/select/select.d.ts +36 -1
  27. package/dist/types/components/sheet/sheet-stack.d.ts +167 -0
  28. package/dist/types/components/sheet/sheet.d.ts +294 -0
  29. package/dist/types/components/split-view/split-view.d.ts +2 -21
  30. package/dist/types/components/tabbox/tabbox.d.ts +12 -3
  31. package/dist/types/components/table/table.d.ts +219 -12
  32. package/dist/types/components/tooltip/tooltip.d.ts +2 -2
  33. package/dist/types/components/value-list/value-list.d.ts +24 -3
  34. package/dist/types/core/dom.d.ts +114 -0
  35. package/dist/types/core/drag-axis.d.ts +111 -0
  36. package/dist/types/core/position.d.ts +4 -2
  37. package/dist/types/index.d.ts +12 -2
  38. package/dist/zx-compat.esm.js +943 -311
  39. package/dist/zx-compat.esm.min.js +1 -1
  40. package/dist/zx-compat.global.js +7893 -2252
  41. package/dist/zx-compat.global.min.js +3 -3
  42. package/dist/zx-zeyos.esm.js +826 -114
  43. package/dist/zx-zeyos.esm.min.js +1 -1
  44. package/dist/zx.css +1720 -243
  45. package/dist/zx.esm.js +8227 -2599
  46. package/dist/zx.esm.min.js +3 -3
  47. package/dist/zx.global.js +8227 -2599
  48. package/dist/zx.global.min.js +3 -3
  49. package/dist/zx.min.css +1 -1
  50. package/docs/api.json +2597 -255
  51. package/docs/llms.md +475 -37
  52. package/docs/llms.txt +21 -9
  53. package/package.json +4 -2
  54. package/src/compat/globals.js +3 -1
  55. package/src/compat/map/data.js +31 -9
  56. package/src/components/account-menu/account-menu.css +70 -0
  57. package/src/components/account-menu/account-menu.js +208 -0
  58. package/src/components/app-rail/app-rail.css +107 -0
  59. package/src/components/app-rail/app-rail.js +668 -0
  60. package/src/components/app-sidebar/app-sidebar.css +68 -0
  61. package/src/components/app-sidebar/app-sidebar.js +388 -0
  62. package/src/components/avatar/avatar.css +61 -0
  63. package/src/components/avatar/avatar.js +222 -0
  64. package/src/components/button/button.css +0 -1
  65. package/src/components/chart/chart.css +61 -0
  66. package/src/components/chart/chart.js +518 -0
  67. package/src/components/date-picker/date-range-picker.css +7 -0
  68. package/src/components/date-picker/month-picker.js +9 -0
  69. package/src/components/dialog/dialog.js +11 -4
  70. package/src/components/dock/dock.css +228 -0
  71. package/src/components/dock/dock.js +977 -0
  72. package/src/components/dropdown/dropdown.js +1 -1
  73. package/src/components/field/field.js +2 -0
  74. package/src/components/field-upload/field-upload.js +9 -4
  75. package/src/components/fieldset/fieldset.css +7 -0
  76. package/src/components/form/form.css +7 -0
  77. package/src/components/form/form.js +6 -3
  78. package/src/components/grid/grid.css +6 -0
  79. package/src/components/grid/grid.js +213 -0
  80. package/src/components/launcher/launcher.css +100 -0
  81. package/src/components/launcher/launcher.js +557 -0
  82. package/src/components/layout/layout.js +2 -2
  83. package/src/components/menu-button/menu-button.js +27 -2
  84. package/src/components/modal/modal.css +5 -1
  85. package/src/components/modal/modal.js +37 -2
  86. package/src/components/multi-value-editor/multi-value-editor.css +99 -15
  87. package/src/components/multi-value-editor/multi-value-editor.js +237 -19
  88. package/src/components/navigation-bar/navigation-bar.css +7 -0
  89. package/src/components/questionnaire/items.js +370 -0
  90. package/src/components/questionnaire/questionnaire.css +387 -0
  91. package/src/components/questionnaire/questionnaire.js +1033 -0
  92. package/src/components/search/search.css +10 -2
  93. package/src/components/select/select.css +6 -1
  94. package/src/components/select/select.js +99 -11
  95. package/src/components/sheet/sheet-stack.js +304 -0
  96. package/src/components/sheet/sheet.css +351 -0
  97. package/src/components/sheet/sheet.js +551 -0
  98. package/src/components/split-view/split-view.js +76 -161
  99. package/src/components/stepper/stepper.css +12 -2
  100. package/src/components/tabbox/tabbox.css +13 -3
  101. package/src/components/tabbox/tabbox.js +34 -10
  102. package/src/components/table/table.css +43 -0
  103. package/src/components/table/table.js +523 -45
  104. package/src/components/tooltip/tooltip.js +5 -2
  105. package/src/components/value-list/value-list.js +6 -3
  106. package/src/core/dom.js +302 -0
  107. package/src/core/drag-axis.js +203 -0
  108. package/src/core/position.js +68 -22
  109. package/src/index.js +19 -2
  110. package/styles/tokens/dark.css +15 -13
  111. package/styles/tokens/global.css +17 -5
  112. package/styles/tokens/semantic.css +14 -8
  113. package/styles/tokens/themes.css +72 -0
  114. package/styles/zx.css +11 -1
  115. package/dist/types/components/permission/permission.d.ts +0 -93
  116. package/src/components/permission/permission.css +0 -47
  117. package/src/components/permission/permission.js +0 -198
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. |
@@ -217,8 +227,34 @@ the document. Select a built-in theme and density on any ancestor (normally `<ht
217
227
  ```
218
228
 
219
229
  Theme values are `light`, `dark`, and `auto`; density values are `cozy` and `compact`. `auto`
220
- follows the operating-system color preference. A product theme can override semantic tokens
221
- without reaching into component CSS:
230
+ follows the operating-system color preference.
231
+
232
+ A third attribute picks the **accent**, orthogonally to the other two:
233
+
234
+ ```html
235
+ <html data-zx-theme="dark" data-zx-preset="ocean">
236
+ ```
237
+
238
+ Six presets ship — `zx` (the ZeyOS green, and the default), `zeyos`, `ocean`, `violet`, `rose`,
239
+ `slate`. Each is five declarations of the tier-1 accent ramp that the semantic tier resolves
240
+ through, so a preset rethemes light, dark, and auto at once:
241
+
242
+ ```css
243
+ [data-zx-preset="acme"] {
244
+ --zx-accent-300: #c4b4ff;
245
+ --zx-accent-400: #a684ff;
246
+ --zx-accent-500: #8e51ff;
247
+ --zx-accent-600: #7f22fe;
248
+ --zx-accent-700: #7008e7;
249
+ }
250
+ ```
251
+
252
+ Light surfaces take the 600 and 700 stops, dark ones take 300, 400, and 500 — so keep 600 legible
253
+ against white and 400 against near-black, and `--zx-color-on-accent` stays correct in both. The
254
+ [theme studio](https://zx.zeyos.com/theme.html) renders every component family under a live theme and
255
+ exports the result.
256
+
257
+ Anything beyond the accent is a semantic token override, without reaching into component CSS:
222
258
 
223
259
  ```css
224
260
  :root[data-zx-theme="acme"] {
@@ -247,7 +283,7 @@ JavaScript positioning fallback.
247
283
 
248
284
  ## Development
249
285
 
250
- Install the single development dependency and start the no-build demo server:
286
+ Install the development toolchain and start the no-build demo server:
251
287
 
252
288
  ```sh
253
289
  npm install
@@ -292,12 +328,13 @@ During an incremental migration, load the global API before the compatibility bu
292
328
  <script src="/assets/zx.global.js"></script>
293
329
  <script src="/assets/zx-compat.global.js"></script>
294
330
  <script>
295
- // Only when old code relies on __(), _(), or prototype conveniences:
331
+ // Only for gx-era free functions; an existing ZeyOS __() is preserved:
296
332
  gx.compat.installGlobals();
297
333
  </script>
298
334
  ```
299
335
 
300
336
  The compatibility bundle always exposes `window.gx` and installs only the element
301
337
  `store`/`retrieve`/`eliminate` shim automatically. Legacy globals and prototype conveniences are
302
- 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
303
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 {
@@ -0,0 +1,144 @@
1
+ import { Component } from '../../core/component.js';
2
+ import { Avatar } from '../avatar/avatar.js';
3
+ import { MenuButton } from '../menu-button/menu-button.js';
4
+ export type MenuButtonItem = import('../menu-button/menu-button.js').MenuButtonItem;
5
+ export type AccountIdentity = {
6
+ /**
7
+ * Primary identity.
8
+ */
9
+ name?: string;
10
+ /**
11
+ * Email, company, or other secondary identity.
12
+ */
13
+ secondary?: string;
14
+ /**
15
+ * Avatar image URL.
16
+ */
17
+ src?: string | null;
18
+ /**
19
+ * Explicit avatar initials.
20
+ */
21
+ initials?: string | null;
22
+ /**
23
+ * Presence state.
24
+ */
25
+ status?: 'online' | 'away' | 'busy' | 'offline' | null;
26
+ /**
27
+ * Presence text alternative.
28
+ */
29
+ statusLabel?: string | null;
30
+ };
31
+ export type AccountMenuOptions = {
32
+ /**
33
+ * Account presentation supplied by the application.
34
+ */
35
+ account?: AccountIdentity;
36
+ /**
37
+ * Account actions and `'-'` separators.
38
+ */
39
+ items?: MenuButtonItem[];
40
+ /**
41
+ * Whether only the avatar is visually shown in the trigger.
42
+ */
43
+ compact?: boolean;
44
+ /**
45
+ * Trigger label; defaults to `Account menu for <name>`.
46
+ */
47
+ label?: string | null;
48
+ /**
49
+ * Popup placement.
50
+ */
51
+ placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'bottom' | 'top' | 'right-start' | 'right-end' | 'left-start' | 'left-end' | 'right' | 'left';
52
+ /**
53
+ * Preventable action listener.
54
+ */
55
+ onselect?: (event: CustomEvent<{
56
+ value: unknown;
57
+ item: object;
58
+ }>) => void;
59
+ /**
60
+ * Open listener.
61
+ */
62
+ onopen?: (event: CustomEvent<Record<string, never>>) => void;
63
+ /**
64
+ * Close listener.
65
+ */
66
+ onclose?: (event: CustomEvent<Record<string, never>>) => void;
67
+ };
68
+ /** @typedef {import('../menu-button/menu-button.js').MenuButtonItem} MenuButtonItem */
69
+ /**
70
+ * @typedef {Object} AccountIdentity
71
+ * @property {string} [name=''] Primary identity.
72
+ * @property {string} [secondary=''] Email, company, or other secondary identity.
73
+ * @property {string|null} [src=null] Avatar image URL.
74
+ * @property {string|null} [initials=null] Explicit avatar initials.
75
+ * @property {'online'|'away'|'busy'|'offline'|null} [status=null] Presence state.
76
+ * @property {string|null} [statusLabel=null] Presence text alternative.
77
+ */
78
+ /**
79
+ * @typedef {Object} AccountMenuOptions
80
+ * @property {AccountIdentity} [account={}] Account presentation supplied by the application.
81
+ * @property {MenuButtonItem[]} [items=[]] Account actions and `'-'` separators.
82
+ * @property {boolean} [compact=false] Whether only the avatar is visually shown in the trigger.
83
+ * @property {string|null} [label=null] Trigger label; defaults to `Account menu for <name>`.
84
+ * @property {'bottom-start'|'bottom-end'|'top-start'|'top-end'|'bottom'|'top'|'right-start'|'right-end'|'left-start'|'left-end'|'right'|'left'} [placement='top-start'] Popup placement.
85
+ * @property {(event: CustomEvent<{value: unknown, item: object}>) => void} [onselect] Preventable action listener.
86
+ * @property {(event: CustomEvent<Record<string, never>>) => void} [onopen] Open listener.
87
+ * @property {(event: CustomEvent<Record<string, never>>) => void} [onclose] Close listener.
88
+ */
89
+ /**
90
+ * Avatar-backed APG account action menu; session/authentication behavior remains application-owned.
91
+ * @fires AccountMenu#select
92
+ * @fires AccountMenu#open
93
+ * @fires AccountMenu#close
94
+ * @extends {Component<AccountMenuOptions>}
95
+ */
96
+ export declare class AccountMenu extends Component<AccountMenuOptions> {
97
+ _avatar: Avatar;
98
+ _menu: MenuButton;
99
+ _createdRoot: boolean;
100
+ _original: {
101
+ attributes: string[][];
102
+ children: ChildNode[];
103
+ };
104
+ _account: AccountIdentity & {
105
+ name: string;
106
+ secondary: string;
107
+ };
108
+ static cssName: string;
109
+ /** @type {Readonly<AccountMenuOptions>} */
110
+ static defaults: Readonly<AccountMenuOptions>;
111
+ /**
112
+ * Creates or enhances an account-menu host.
113
+ * @param {Element|string|null} target Host target.
114
+ * @param {AccountMenuOptions} [options={}] Account-menu options.
115
+ */
116
+ constructor(target?: Element | string | null, options?: AccountMenuOptions);
117
+ /** @returns {HTMLElement} */
118
+ render(): HTMLElement;
119
+ /** Opens the account menu. @returns {this} */
120
+ open(): this;
121
+ /** Closes the account menu. @returns {this} */
122
+ close(): this;
123
+ /** Toggles the account menu. @returns {this} */
124
+ toggle(): this;
125
+ /** Reports whether the menu is open. @returns {boolean} */
126
+ isOpen(): boolean;
127
+ /** Replaces account presentation without touching session state. @param {AccountIdentity} account @returns {this} */
128
+ setAccount(account: AccountIdentity): this;
129
+ /** Replaces account actions. @param {MenuButtonItem[]} items @returns {this} */
130
+ setItems(items: MenuButtonItem[]): this;
131
+ /** Focuses the account trigger. @returns {this} */
132
+ focus(): this;
133
+ /** Returns the underlying menu panel for shell hover/focus coordination. @returns {HTMLElement} */
134
+ getPanel(): HTMLElement;
135
+ /** Destroys child components and restores/removes the host. @returns {void} */
136
+ destroy(): void;
137
+ /** @returns {void} */
138
+ _renderIdentity(): void;
139
+ /** @returns {void} */
140
+ _renderPanelHeader(): void;
141
+ }
142
+ /** Fired when an action is activated. @event AccountMenu#select @type {CustomEvent<{value: unknown, item: object}>} */
143
+ /** Fired after the popup opens. @event AccountMenu#open @type {CustomEvent<Record<string, never>>} */
144
+ /** Fired after the popup closes. @event AccountMenu#close @type {CustomEvent<Record<string, never>>} */
@@ -0,0 +1,250 @@
1
+ import { Component } from '../../core/component.js';
2
+ import { Dropdown } from '../dropdown/dropdown.js';
3
+ export type AppNavItem = {
4
+ /**
5
+ * Stable item identifier.
6
+ */
7
+ id: string | number;
8
+ /**
9
+ * Visible/accessibility label.
10
+ */
11
+ label: string;
12
+ /**
13
+ * Kernel icon name.
14
+ */
15
+ icon?: string;
16
+ /**
17
+ * Count or status badge.
18
+ */
19
+ badge?: string | number;
20
+ /**
21
+ * Emitted value; defaults to `id`.
22
+ */
23
+ value?: unknown;
24
+ /**
25
+ * Native navigation target.
26
+ */
27
+ href?: string;
28
+ /**
29
+ * Native link browsing context.
30
+ */
31
+ target?: string;
32
+ /**
33
+ * Application-owned non-link action.
34
+ */
35
+ invoke?: () => void;
36
+ /**
37
+ * Whether activation is unavailable.
38
+ */
39
+ disabled?: boolean;
40
+ /**
41
+ * Child destinations/actions.
42
+ */
43
+ children?: AppNavItem[];
44
+ };
45
+ export type AppRailOptions = {
46
+ /**
47
+ * Application navigation tree.
48
+ */
49
+ items?: AppNavItem[];
50
+ /**
51
+ * Active item id.
52
+ */
53
+ active?: string | number | null;
54
+ /**
55
+ * Rail flow.
56
+ */
57
+ orientation?: 'vertical' | 'horizontal';
58
+ /**
59
+ * Workspace edge occupied by the rail.
60
+ */
61
+ side?: 'left' | 'right' | 'top' | 'bottom';
62
+ /**
63
+ * Navigation accessible label.
64
+ */
65
+ label?: string;
66
+ /**
67
+ * Leading rail content.
68
+ */
69
+ header?: Node | string | number | {
70
+ toElement: () => Node | null;
71
+ } | null;
72
+ /**
73
+ * Trailing rail content.
74
+ */
75
+ footer?: Node | string | number | {
76
+ toElement: () => Node | null;
77
+ } | null;
78
+ /**
79
+ * Hover-open delay in milliseconds.
80
+ */
81
+ openDelay?: number;
82
+ /**
83
+ * Pointer/focus crossing grace in milliseconds.
84
+ */
85
+ closeDelay?: number;
86
+ /**
87
+ * Preventable action listener.
88
+ */
89
+ onselect?: (event: CustomEvent<AppNavSelectDetail>) => void;
90
+ /**
91
+ * Flyout-state listener.
92
+ */
93
+ onflyoutchange?: (event: CustomEvent<{
94
+ item: AppNavItem;
95
+ id: string | number;
96
+ open: boolean;
97
+ }>) => void;
98
+ };
99
+ export type AppNavSelectDetail = {
100
+ item: AppNavItem;
101
+ id: string | number;
102
+ value: unknown;
103
+ href: string | null;
104
+ event: Event;
105
+ };
106
+ export type RailFlyout = {
107
+ key: string;
108
+ parentKey: string | null;
109
+ item: AppNavItem;
110
+ trigger: HTMLElement;
111
+ panel: HTMLElement;
112
+ dropdown: Dropdown;
113
+ };
114
+ /**
115
+ * @typedef {Object} AppNavItem
116
+ * @property {string|number} id Stable item identifier.
117
+ * @property {string} label Visible/accessibility label.
118
+ * @property {string} [icon] Kernel icon name.
119
+ * @property {string|number} [badge] Count or status badge.
120
+ * @property {unknown} [value] Emitted value; defaults to `id`.
121
+ * @property {string} [href] Native navigation target.
122
+ * @property {string} [target] Native link browsing context.
123
+ * @property {() => void} [invoke] Application-owned non-link action.
124
+ * @property {boolean} [disabled] Whether activation is unavailable.
125
+ * @property {AppNavItem[]} [children] Child destinations/actions.
126
+ */
127
+ /**
128
+ * @typedef {Object} AppRailOptions
129
+ * @property {AppNavItem[]} [items=[]] Application navigation tree.
130
+ * @property {string|number|null} [active=null] Active item id.
131
+ * @property {'vertical'|'horizontal'} [orientation='vertical'] Rail flow.
132
+ * @property {'left'|'right'|'top'|'bottom'} [side='left'] Workspace edge occupied by the rail.
133
+ * @property {string} [label='Applications'] Navigation accessible label.
134
+ * @property {Node|string|number|{toElement: () => Node|null}|null} [header=null] Leading rail content.
135
+ * @property {Node|string|number|{toElement: () => Node|null}|null} [footer=null] Trailing rail content.
136
+ * @property {number} [openDelay=80] Hover-open delay in milliseconds.
137
+ * @property {number} [closeDelay=160] Pointer/focus crossing grace in milliseconds.
138
+ * @property {(event: CustomEvent<AppNavSelectDetail>) => void} [onselect] Preventable action listener.
139
+ * @property {(event: CustomEvent<{item: AppNavItem, id: string|number, open: boolean}>) => void} [onflyoutchange] Flyout-state listener.
140
+ */
141
+ /** @typedef {{item: AppNavItem, id: string|number, value: unknown, href: string|null, event: Event}} AppNavSelectDetail */
142
+ /** @typedef {{key: string, parentKey: string|null, item: AppNavItem, trigger: HTMLElement, panel: HTMLElement, dropdown: Dropdown}} RailFlyout */
143
+ /**
144
+ * Minimized application navigation; descendants always open in hover/focus flyouts, never inline.
145
+ * @fires AppRail#select
146
+ * @fires AppRail#flyoutchange
147
+ * @extends {Component<AppRailOptions>}
148
+ */
149
+ export declare class AppRail extends Component<AppRailOptions> {
150
+ _createdRoot: boolean;
151
+ _original: {
152
+ attributes: string[][];
153
+ children: ChildNode[];
154
+ };
155
+ _items: AppNavItem[];
156
+ _active: string | number;
157
+ _flyouts: Map<any, any>;
158
+ _tooltips: any[];
159
+ _tooltipById: Map<any, any>;
160
+ _interaction: RailListenerScope;
161
+ _openTimers: Map<any, any>;
162
+ _closeTimers: Map<any, any>;
163
+ _pointerFocus: WeakSet<object>;
164
+ _silenceFlyoutEvents: boolean;
165
+ static cssName: string;
166
+ /** @type {Readonly<AppRailOptions>} */
167
+ static defaults: Readonly<AppRailOptions>;
168
+ /**
169
+ * Creates or enhances a rail host.
170
+ * @param {Element|string|null} target Rail target.
171
+ * @param {AppRailOptions} [options={}] Rail options.
172
+ */
173
+ constructor(target?: Element | string | null, options?: AppRailOptions);
174
+ /** @returns {HTMLElement} */
175
+ render(): HTMLElement;
176
+ /** Replaces navigation items and closes removed flyouts. @param {AppNavItem[]} items @returns {this} */
177
+ setItems(items: AppNavItem[]): this;
178
+ /** Sets the active item without routing. @param {string|number|null} id @returns {this} */
179
+ setActive(id: string | number | null): this;
180
+ /** Returns a shallow copy of normalized items. @returns {AppNavItem[]} */
181
+ getItems(): AppNavItem[];
182
+ /** Opens one item's flyout, optionally focusing its first action. @param {string|number} id @param {{focus?: boolean}} [options={}] @returns {this} */
183
+ openFlyout(id: string | number, { focus }?: {
184
+ focus?: boolean;
185
+ }): this;
186
+ /** Closes one flyout. @param {string|number} id @returns {this} */
187
+ closeFlyout(id: string | number): this;
188
+ /** Closes every flyout and cancels pending hover/focus transitions. @returns {this} */
189
+ closeAllFlyouts(): this;
190
+ /** Reports whether an item's flyout is open. @param {string|number} id @returns {boolean} */
191
+ isFlyoutOpen(id: string | number): boolean;
192
+ /** Focuses the first top-level rail item. @returns {this} */
193
+ focus(): this;
194
+ /** Reports whether a node belongs to this rail, including detached flyout panels. @param {Node|null} node @returns {boolean} @private */
195
+ private _containsNode;
196
+ /** Destroys body popovers/tooltips and restores or removes the root. @returns {void} */
197
+ destroy(): void;
198
+ /** @returns {void} */
199
+ _rebuild(): void;
200
+ /** @param {AppNavItem} item @param {HTMLElement} trigger @param {string} key @param {string|null} parentKey @returns {void} */
201
+ _buildFlyout(item: AppNavItem, trigger: HTMLElement, key: string, parentKey: string | null): void;
202
+ /** @param {AppNavItem} item @param {Event} event @returns {Event} */
203
+ _select(item: AppNavItem, event: Event): Event;
204
+ /** @param {KeyboardEvent} event @returns {void} */
205
+ _onRailKeydown(event: KeyboardEvent): void;
206
+ /** @param {KeyboardEvent} event @param {RailFlyout} flyout @returns {void} */
207
+ _onFlyoutKeydown(event: KeyboardEvent, flyout: RailFlyout): void;
208
+ /** @param {string|number} id @returns {void} */
209
+ _scheduleOpen(id: string | number): void;
210
+ /** @param {string|number} id @returns {void} */
211
+ _scheduleClose(id: string | number): void;
212
+ /** Schedules a flyout and, when leaving a detached panel, each owning flyout for re-evaluation. @param {RailFlyout} flyout @param {boolean} ancestors @returns {void} */
213
+ _scheduleFlyoutClose(flyout: RailFlyout, ancestors: boolean): void;
214
+ /** Resolves a public id or internal descendant path. @param {string|number} id @returns {RailFlyout|null} */
215
+ _resolveFlyout(id: string | number): RailFlyout | null;
216
+ /** Closes the root flyout that owns a selected descendant. @param {string} key @returns {void} */
217
+ _closeFlyoutChain(key: string): void;
218
+ /** Reports whether one flyout owns another through its parent chain. @param {RailFlyout} ancestor @param {RailFlyout} descendant @returns {boolean} */
219
+ _isAncestor(ancestor: RailFlyout, descendant: RailFlyout): boolean;
220
+ /** Cancels crossing timers for a flyout and optionally every owning flyout. @param {RailFlyout} flyout @param {boolean} ancestors @returns {void} */
221
+ _cancelFlyoutTimers(flyout: RailFlyout, ancestors: boolean): void;
222
+ /** Reports pointer/focus presence in a flyout branch, including detached descendant panels. @param {RailFlyout} flyout @returns {boolean} */
223
+ _branchInteracting(flyout: RailFlyout): boolean;
224
+ /** Restores trigger focus without immediately reopening the flyout through its focus handler. @param {HTMLElement} trigger @returns {void} */
225
+ _restoreFocus(trigger: HTMLElement): void;
226
+ /** @param {string} key @returns {void} */
227
+ _cancelTimers(key: string): void;
228
+ /** @param {Map<string, ReturnType<typeof setTimeout>>} timers @param {string} key @returns {void} */
229
+ _cancelTimer(timers: Map<string, ReturnType<typeof setTimeout>>, key: string): void;
230
+ /** @returns {void} */
231
+ _syncActive(): void;
232
+ /** @returns {void} */
233
+ _clearArtifacts(): void;
234
+ }
235
+ /** Owns listeners attached to one dynamic rail render so `setItems()` can release them immediately. */
236
+ declare class RailListenerScope extends Component {
237
+ /** @param {HTMLElement} host Rail host. */
238
+ constructor(host: HTMLElement);
239
+ /** @returns {HTMLElement} */
240
+ render(): HTMLElement;
241
+ }
242
+ /**
243
+ * Normalizes an application navigation tree without mutating caller data.
244
+ * @param {unknown} items Candidate tree.
245
+ * @returns {AppNavItem[]}
246
+ */
247
+ export declare function normalizeAppItems(items: unknown): AppNavItem[];
248
+ export {};
249
+ /** Fired when a destination/action is activated. @event AppRail#select @type {CustomEvent<AppNavSelectDetail>} */
250
+ /** Fired when a flyout opens or closes. @event AppRail#flyoutchange @type {CustomEvent<{item: AppNavItem, id: string|number, open: boolean}>} */