@zeyos/zx 5.0.0 → 5.2.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 (154) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/README.md +2 -1
  3. package/dist/types/components/account-menu/account-menu.d.ts +8 -0
  4. package/dist/types/components/activity-list/activity-list.d.ts +9 -1
  5. package/dist/types/components/app-icon/app-icon.d.ts +14 -2
  6. package/dist/types/components/app-sidebar/app-sidebar.d.ts +288 -14
  7. package/dist/types/components/calendar/calendar.d.ts +67 -5
  8. package/dist/types/components/card-view/card-view.d.ts +7 -4
  9. package/dist/types/components/card-view/record-card.d.ts +11 -0
  10. package/dist/types/components/context-menu/context-menu.d.ts +6 -2
  11. package/dist/types/components/data-filter/data-filter.d.ts +4 -4
  12. package/dist/types/components/dropdown/dropdown.d.ts +22 -7
  13. package/dist/types/components/field/field.d.ts +30 -0
  14. package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
  15. package/dist/types/components/fieldset/fieldset.d.ts +7 -0
  16. package/dist/types/components/file-list/file-list.d.ts +35 -3
  17. package/dist/types/components/filter/filter.d.ts +127 -3
  18. package/dist/types/components/filter-panel/filter-panel.d.ts +36 -7
  19. package/dist/types/components/launcher/launcher.d.ts +8 -0
  20. package/dist/types/components/list-toolbar/list-toolbar.d.ts +15 -6
  21. package/dist/types/components/menu-button/menu-button.d.ts +6 -0
  22. package/dist/types/components/message/message.d.ts +14 -1
  23. package/dist/types/components/modal/modal.d.ts +30 -0
  24. package/dist/types/components/module-bar/module-bar.d.ts +395 -0
  25. package/dist/types/components/pagination/pagination.d.ts +17 -3
  26. package/dist/types/components/select/select.d.ts +6 -0
  27. package/dist/types/components/sheet/sheet.d.ts +15 -0
  28. package/dist/types/components/table/table.d.ts +265 -17
  29. package/dist/types/components/view/record-view.d.ts +59 -2
  30. package/dist/types/components/view-settings/view-settings.d.ts +879 -0
  31. package/dist/types/components/workspace-switcher/workspace-switcher.d.ts +327 -0
  32. package/dist/types/core/component.d.ts +12 -2
  33. package/dist/types/core/i18n.d.ts +27 -3
  34. package/dist/types/core/keyboard.d.ts +98 -1
  35. package/dist/types/core/messages.d.ts +382 -0
  36. package/dist/types/core/overlay-host.d.ts +28 -1
  37. package/dist/types/core/overlay-stack.d.ts +260 -0
  38. package/dist/types/index.d.ts +5 -2
  39. package/dist/types/internal/app-rail.d.ts +38 -0
  40. package/dist/types/internal/menu-items.d.ts +71 -3
  41. package/dist/types/zeyos/index.d.ts +1 -0
  42. package/dist/types/zeyos/launcher.d.ts +9 -0
  43. package/dist/types/zeyos/module-bar.d.ts +176 -0
  44. package/dist/types/zeyos/query.d.ts +31 -5
  45. package/dist/types/zeyos/table.d.ts +245 -8
  46. package/dist/types/zeyos/view.d.ts +16 -2
  47. package/dist/zx-zeyos.esm.js +4422 -430
  48. package/dist/zx-zeyos.esm.min.js +5 -5
  49. package/dist/zx.css +1417 -134
  50. package/dist/zx.esm.js +6986 -830
  51. package/dist/zx.esm.min.js +8 -8
  52. package/dist/zx.global.js +6986 -830
  53. package/dist/zx.global.min.js +8 -8
  54. package/dist/zx.min.css +1 -1
  55. package/docs/api.json +794 -17
  56. package/docs/llms.md +503 -63
  57. package/docs/llms.txt +6 -2
  58. package/package.json +1 -1
  59. package/src/components/account-menu/account-menu.js +12 -0
  60. package/src/components/activity-list/activity-list.js +27 -1
  61. package/src/components/app-icon/app-icon.css +13 -2
  62. package/src/components/app-icon/app-icon.js +11 -1
  63. package/src/components/app-rail/app-rail.css +19 -0
  64. package/src/components/app-sidebar/app-sidebar.css +204 -3
  65. package/src/components/app-sidebar/app-sidebar.js +646 -40
  66. package/src/components/breadcrumb/breadcrumb.css +1 -1
  67. package/src/components/calendar/calendar.css +1 -1
  68. package/src/components/calendar/calendar.js +26 -52
  69. package/src/components/card/card.css +2 -2
  70. package/src/components/card-view/card-view.css +5 -5
  71. package/src/components/card-view/card-view.js +13 -9
  72. package/src/components/card-view/record-card.js +14 -3
  73. package/src/components/code-editor/code-editor.css +1 -1
  74. package/src/components/code-editor/field-adapter.js +9 -2
  75. package/src/components/context-menu/context-menu.js +8 -2
  76. package/src/components/copy/copy-input.css +1 -1
  77. package/src/components/data-filter/data-filter.js +2 -2
  78. package/src/components/date-picker/time-picker.css +2 -2
  79. package/src/components/dock/dock.css +5 -4
  80. package/src/components/dropdown/dropdown.js +157 -72
  81. package/src/components/field/field.js +33 -3
  82. package/src/components/fieldset/external-adapter.js +363 -0
  83. package/src/components/fieldset/fieldset.js +10 -59
  84. package/src/components/file-list/file-list.js +144 -21
  85. package/src/components/filter/filter.css +86 -2
  86. package/src/components/filter/filter.js +300 -8
  87. package/src/components/filter-panel/filter-panel.js +149 -32
  88. package/src/components/finder/finder.css +1 -1
  89. package/src/components/kanban-view/kanban-view.css +3 -3
  90. package/src/components/kanban-view/kanban-view.js +5 -2
  91. package/src/components/launcher/launcher.css +1 -1
  92. package/src/components/launcher/launcher.js +29 -3
  93. package/src/components/list-toolbar/list-toolbar.js +39 -13
  94. package/src/components/master-panel/master-panel.js +0 -1
  95. package/src/components/menu-button/menu-button.css +63 -0
  96. package/src/components/menu-button/menu-button.js +97 -11
  97. package/src/components/message/message.js +60 -20
  98. package/src/components/modal/modal.css +1 -1
  99. package/src/components/modal/modal.js +66 -13
  100. package/src/components/module-bar/module-bar.css +486 -0
  101. package/src/components/module-bar/module-bar.js +1074 -0
  102. package/src/components/multi-value-editor/multi-value-editor.css +1 -1
  103. package/src/components/number-field/field-adapter.js +2 -1
  104. package/src/components/pagination/pagination.css +5 -5
  105. package/src/components/pagination/pagination.js +20 -4
  106. package/src/components/panel/panel.css +3 -2
  107. package/src/components/questionnaire/questionnaire.css +4 -4
  108. package/src/components/rating/field-adapter.js +2 -1
  109. package/src/components/rating/rating.css +1 -1
  110. package/src/components/search/search.css +4 -1
  111. package/src/components/select/select.js +9 -0
  112. package/src/components/sheet/sheet.css +1 -1
  113. package/src/components/sheet/sheet.js +74 -32
  114. package/src/components/slider/field-adapter.js +6 -1
  115. package/src/components/slider/slider.css +2 -2
  116. package/src/components/split-view/split-view.css +1 -1
  117. package/src/components/stat-tile/stat-tile.css +1 -1
  118. package/src/components/stepper/stepper.css +1 -1
  119. package/src/components/tabbox/tabbox.css +9 -5
  120. package/src/components/table/table.css +86 -11
  121. package/src/components/table/table.js +628 -57
  122. package/src/components/tag-picker/field-adapter.js +2 -1
  123. package/src/components/tooltip/tooltip.js +35 -17
  124. package/src/components/tree/tree.css +1 -1
  125. package/src/components/view/record-view.css +1 -1
  126. package/src/components/view/record-view.js +178 -18
  127. package/src/components/view-settings/view-settings.css +285 -0
  128. package/src/components/view-settings/view-settings.js +1830 -0
  129. package/src/components/workspace-switcher/workspace-switcher.css +188 -0
  130. package/src/components/workspace-switcher/workspace-switcher.js +463 -0
  131. package/src/core/component.js +88 -17
  132. package/src/core/fontawesome.js +5 -1
  133. package/src/core/i18n.js +47 -4
  134. package/src/core/icons.js +12 -2
  135. package/src/core/keyboard.js +206 -11
  136. package/src/core/messages.js +427 -0
  137. package/src/core/overlay-host.js +64 -9
  138. package/src/core/overlay-stack.js +487 -0
  139. package/src/core/position.js +22 -3
  140. package/src/index.js +5 -2
  141. package/src/internal/app-rail.js +134 -53
  142. package/src/internal/menu-items.js +61 -3
  143. package/src/zeyos/form.js +5 -3
  144. package/src/zeyos/index.js +3 -0
  145. package/src/zeyos/launcher.js +8 -3
  146. package/src/zeyos/module-bar.js +181 -0
  147. package/src/zeyos/query.js +44 -13
  148. package/src/zeyos/table.js +220 -80
  149. package/src/zeyos/view.js +43 -93
  150. package/styles/base.css +16 -1
  151. package/styles/print.css +1 -1
  152. package/styles/tokens/dark.css +4 -0
  153. package/styles/tokens/semantic.css +56 -28
  154. package/styles/zx.css +3 -0
@@ -1,6 +1,4 @@
1
1
  import { Component } from '../../core/component.js';
2
- declare const HANDLE_POINTER_DISMISS: unique symbol;
3
- declare const HANDLE_ESCAPE_DISMISS: unique symbol;
4
2
  export type DropdownOptions = {
5
3
  /**
6
4
  * Panel content.
@@ -55,6 +53,16 @@ export type DropdownOptions = {
55
53
  */
56
54
  /**
57
55
  * Generic anchored floating panel using the browser popover top layer.
56
+ *
57
+ * Open, the panel is one entry on the overlay stack (`core/overlay-stack.js`): Escape closes it
58
+ * only while it is the topmost layer that takes Escape, a press outside it and every overlay opened
59
+ * from it closes it, and it closes with the overlay its anchor sits in. Inside an open dialog the
60
+ * panel is hosted by that dialog, so `showModal()` does not make it inert.
61
+ *
62
+ * The panel follows its trigger in the Tab order: Tab on the anchor of an open panel moves into
63
+ * the panel's first focusable control (or onto the panel itself when it carries a `tabindex`),
64
+ * Tab past the panel's last control continues after the anchor, and Shift+Tab from the first goes
65
+ * back to the anchor. Closing while focus is inside returns it to the anchor.
58
66
  * @fires Dropdown#open
59
67
  * @fires Dropdown#close
60
68
  * @extends {Component<DropdownOptions>}
@@ -115,9 +123,16 @@ export declare class Dropdown extends Component<DropdownOptions> {
115
123
  * @returns {void}
116
124
  */
117
125
  destroy(): void;
118
- /** @param {PointerEvent} event @returns {void} */
119
- [HANDLE_POINTER_DISMISS](event: PointerEvent): void;
120
- /** @param {KeyboardEvent} event @returns {void} */
121
- [HANDLE_ESCAPE_DISMISS](event: KeyboardEvent): void;
126
+ /**
127
+ * Internal seam for components built on a Dropdown (MenuButton, ContextMenu, the app rail):
128
+ * replaces what Escape does when the overlay stack routes it to this panel, and takes the panel
129
+ * out of the anchor's Tab order — a menu is reached with the arrow keys, not Tab.
130
+ * @param {{onEscape?: ((event: KeyboardEvent) => void)|null, tabReach?: boolean}} settings
131
+ * @returns {this}
132
+ * @internal
133
+ */
134
+ _configure(settings: {
135
+ onEscape?: ((event: KeyboardEvent) => void) | null;
136
+ tabReach?: boolean;
137
+ }): this;
122
138
  }
123
- export {};
@@ -38,6 +38,12 @@ export type FieldOptions = {
38
38
  * Whether the control is disabled.
39
39
  */
40
40
  disabled?: boolean;
41
+ /**
42
+ * Whether the value is read-only: shown and focusable, not
43
+ * editable. Types whose control has no read-only state (`checkbox`, `select`, `optionlist`,
44
+ * `zxselect`, `date`, `time`, …) ignore it.
45
+ */
46
+ readonly?: boolean;
41
47
  /**
42
48
  * Select or option-list values.
43
49
  */
@@ -90,6 +96,11 @@ export type FieldAdapter = {
90
96
  * Set disabled state.
91
97
  */
92
98
  setDisabled: (disabled: boolean) => void;
99
+ /**
100
+ * Set read-only state; left out when the
101
+ * control has none.
102
+ */
103
+ setReadonly?: (readonly: boolean) => void;
93
104
  /**
94
105
  * Release adapter-owned resources.
95
106
  */
@@ -119,6 +130,9 @@ export type NumericCoercion = {
119
130
  * @property {string} [placeholder=''] Control placeholder.
120
131
  * @property {boolean} [required=false] Whether a value is required.
121
132
  * @property {boolean} [disabled=false] Whether the control is disabled.
133
+ * @property {boolean} [readonly=false] Whether the value is read-only: shown and focusable, not
134
+ * editable. Types whose control has no read-only state (`checkbox`, `select`, `optionlist`,
135
+ * `zxselect`, `date`, `time`, …) ignore it.
122
136
  * @property {string[]|Record<string, string>|null} [options=null] Select or option-list values.
123
137
  * @property {'stack'|'inline'} [layout='stack'] Label/control layout.
124
138
  * @property {Record<string, unknown>} [props={}] Adapter-specific control properties.
@@ -133,6 +147,8 @@ export type NumericCoercion = {
133
147
  * @property {(value: unknown, options?: {silent?: boolean}) => void} set Set the current value.
134
148
  * @property {() => void} focus Focus the control.
135
149
  * @property {(disabled: boolean) => void} setDisabled Set disabled state.
150
+ * @property {(readonly: boolean) => void} [setReadonly] Set read-only state; left out when the
151
+ * control has none.
136
152
  * @property {() => void} [destroy] Release adapter-owned resources.
137
153
  * @property {Element} [labelTarget] The element the field's label, description, and validity
138
154
  * belong to when it is not `el` — the text input inside a composite control. Left out, a
@@ -143,6 +159,7 @@ export type NumericCoercion = {
143
159
  /**
144
160
  * One labelled form control backed by a registered adapter.
145
161
  * @fires Field#change
162
+ * @fires Field#input
146
163
  * @fires Field#invalid
147
164
  * @extends {Component<FieldOptions>}
148
165
  */
@@ -213,6 +230,13 @@ export declare class Field extends Component<FieldOptions> {
213
230
  * @returns {this}
214
231
  */
215
232
  setDisabled(disabled: boolean): this;
233
+ /**
234
+ * Makes the value read-only or editable again, where the control has a read-only state (see
235
+ * the `readonly` option); reflected as `data-readonly` on the root either way.
236
+ * @param {boolean} readonly Read-only state.
237
+ * @returns {this}
238
+ */
239
+ setReadonly(readonly: boolean): this;
216
240
  /**
217
241
  * Displays a validation or status message.
218
242
  * @param {string} message Message text.
@@ -260,6 +284,12 @@ export declare function coerceFloat(input: unknown): NumericCoercion;
260
284
  * @event Field#change
261
285
  * @type {CustomEvent<{value: unknown}>}
262
286
  */
287
+ /**
288
+ * Live edit before it is committed, from the types whose widget tells the two apart (`code`,
289
+ * `slider`): every keystroke or drag step, where `change` follows only on commit.
290
+ * @event Field#input
291
+ * @type {CustomEvent<{value: unknown}>}
292
+ */
263
293
  /**
264
294
  * Field validation failure event.
265
295
  * @event Field#invalid
@@ -0,0 +1,83 @@
1
+ export type Field = import('../field/field.js').Field;
2
+ export type FieldAdapter = import('../field/field.js').FieldAdapter;
3
+ export type ExternalSource = Element | {
4
+ el?: Element;
5
+ toElement?: () => Element;
6
+ };
7
+ /** @typedef {import('../field/field.js').Field} Field */
8
+ /** @typedef {import('../field/field.js').FieldAdapter} FieldAdapter */
9
+ /**
10
+ * An element or component a Fieldset adopts with `addField(id, source)`: anything that renders
11
+ * into an element. Components are read through the methods they have, elements through their
12
+ * native properties.
13
+ * @typedef {Element|{el?: Element, toElement?: () => Element}} ExternalSource
14
+ */
15
+ /**
16
+ * The value accessor pairs the library's components use, in the order they are tried. A reader
17
+ * counts only when it takes no required argument (`Fieldset.getValue(id)` is not a reader), a
18
+ * writer of another pair only when the value is its sole required argument.
19
+ * - `getValue/setValue`: Field, CodeEditor, Filter, SortControl, Toggle (`getValue()` is the
20
+ * configured on-value or `false`, the same as the `toggle` field type reads).
21
+ * - `get/set`: NumberField, Select, Slider, Rating, CheckButton, Datebox, Timebox, Search,
22
+ * CopyInput, DatePicker and the other pickers.
23
+ * - `getValues/setValues`: Checklist, TagPicker, ValueList, MultiValueEditor, Fieldset, Form.
24
+ * - `isChecked/setChecked`: boolean controls that name their state that way.
25
+ * @type {ReadonlyArray<readonly [string, string]>}
26
+ */
27
+ export declare const VALUE_METHODS: ReadonlyArray<readonly [string, string]>;
28
+ /**
29
+ * The element a source renders into.
30
+ * @param {ExternalSource} source Element or component.
31
+ * @returns {Element}
32
+ */
33
+ export declare function externalElement(source: ExternalSource): Element;
34
+ /**
35
+ * Reads the current value of an element or component through the first value dialect it
36
+ * supports (see {@link VALUE_METHODS}), then a `value`, `values`, or `checked` property, then the
37
+ * element itself: `checked` for a checkbox or radio, `value` for any other control. Null when
38
+ * the source has no value at all.
39
+ * @param {ExternalSource} source Element or component.
40
+ * @returns {unknown}
41
+ */
42
+ export declare function readExternalValue(source: ExternalSource): unknown;
43
+ /**
44
+ * Reports whether an element or component is disabled: its `isDisabled()`, a `disabled`
45
+ * property, the element's own `disabled`, an `aria-disabled="true"` or `data-disabled` root, or
46
+ * a wrapper whose every form control is disabled.
47
+ * @param {ExternalSource} source Element or component.
48
+ * @returns {boolean}
49
+ */
50
+ export declare function readExternalDisabled(source: ExternalSource): boolean;
51
+ /**
52
+ * Reports whether an element or component is read-only: a `readonly`/`readOnly` property, the
53
+ * element's own `readOnly`, or an `aria-readonly="true"` or `data-readonly` root.
54
+ * @param {ExternalSource} source Element or component.
55
+ * @returns {boolean}
56
+ */
57
+ export declare function readExternalReadonly(source: ExternalSource): boolean;
58
+ /**
59
+ * Builds the Field adapter for an element or component that is not a registered field type.
60
+ *
61
+ * Values go through the source's own accessors ({@link readExternalValue}); disabling through
62
+ * `setDisabled(bool)`, then `enable()`/`disable()`, then a `disabled` property, and only then the
63
+ * DOM — the element's `disabled`, or for a plain wrapper `aria-disabled` plus `disabled` on every
64
+ * form control inside it. Read-only goes through `setReadonly(bool)`/`setReadOnly(bool)`, a
65
+ * `readonly`/`readOnly` property, or the element's own `readOnly`.
66
+ *
67
+ * Writes pass the caller's options to the component: `Field.setValue(v)` or
68
+ * `Fieldset.setValues(values)` without `silent` lets the component emit its own `change` to its
69
+ * own listeners, while the field emits one `change` for the write; with `silent` neither does.
70
+ *
71
+ * Given the field, a component's own `change` event becomes the field's `change`, and the native
72
+ * `change` its inner controls bubble is dropped unless it carries a value the component did not
73
+ * already report — so one edit is one field `change`, whether the component reports it, its
74
+ * input does, or (Search, CopyInput) only its input does.
75
+ *
76
+ * `destroy()` puts the element back where it was found and undoes what the adapter changed:
77
+ * attributes, the native value, disabled and read-only state.
78
+ * @param {ExternalSource} source Element or component to adopt.
79
+ * @param {Field|null} [field=null] The field the adapter serves; needed to forward events. Its
80
+ * `listen()` owns every listener the adapter adds, so destroying the field removes them.
81
+ * @returns {FieldAdapter}
82
+ */
83
+ export declare function externalAdapter(source: ExternalSource, field?: Field | null): FieldAdapter;
@@ -53,6 +53,13 @@ export declare class Fieldset extends Component<FieldsetOptions> {
53
53
  * Adds a field from options, an existing field, an element, or a component. The key becomes the
54
54
  * field's `name` and its `data-field-id`; the control's DOM id is `<idPrefix>-<key>`, unless the
55
55
  * field options give an `id` of their own that differs from the key.
56
+ *
57
+ * An element or a component that is not a registered field type is wrapped in a `custom` field
58
+ * that reads and writes it through its own API — `getValue`/`setValue`, `get`/`set`,
59
+ * `getValues`/`setValues`, `isChecked`/`setChecked`, or a `value` property — disables it
60
+ * through `setDisabled(bool)` or `enable()`/`disable()`, and makes it read-only through
61
+ * `setReadonly(bool)`, falling back to the element's native properties only when the component
62
+ * has none of these. The component's own `change` becomes the field's `change`, once per edit.
56
63
  * @param {string} id Logical field identifier.
57
64
  * @param {FieldOptions|Field|Element|Component} field Field source.
58
65
  * @returns {Field}
@@ -75,6 +75,12 @@ export type FileListOptions = {
75
75
  /**
76
76
  * Accessible collection for durable and transient files. Ordering and mutation are local
77
77
  * presentation concerns only; transport, authorization, and persistence remain host-owned.
78
+ *
79
+ * Mutations are reconciled by file `id`: a file whose descriptor did not change keeps its row
80
+ * untouched, a changed one is updated in place through `FileItem.set()`, and only added or removed
81
+ * files create or drop rows. Upload progress can therefore tick through `updateItem()` while the
82
+ * reader's focus — on that file's Cancel button, say — and the list's scroll position stay put.
83
+ * Files without an `id` cannot be matched and are rebuilt on every mutation.
78
84
  * @fires FileList#activate
79
85
  * @fires FileList#action
80
86
  * @fires FileList#datachange
@@ -86,7 +92,16 @@ export declare class FileList extends Component<FileListOptions> {
86
92
  _destroyed: boolean;
87
93
  _items: import("../file-item/file-item.js").FileItemState[];
88
94
  _loading: any;
89
- _itemComponents: any[];
95
+ _itemComponents: any[] | FileItem[];
96
+ /** @type {Map<FileItem, {row: HTMLElement, state: FileItemState}>} */
97
+ _itemRecords: Map<FileItem, {
98
+ row: HTMLElement;
99
+ state: FileItemState;
100
+ }>;
101
+ _itemList: HTMLElement;
102
+ _emptyRegion: HTMLElement;
103
+ _loadingRegion: HTMLElement;
104
+ _loadingPlaceholders: boolean;
90
105
  static cssName: string;
91
106
  /** @type {Readonly<FileListOptions>} */
92
107
  static defaults: Readonly<FileListOptions>;
@@ -144,10 +159,27 @@ export declare class FileList extends Component<FileListOptions> {
144
159
  setLoading(loading: boolean): this;
145
160
  /** Restores an enhanced target exactly, or removes an owned collection. @returns {void} */
146
161
  destroy(): void;
147
- /** @returns {void} */
162
+ /**
163
+ * Brings the rendered rows in line with `_items`, keyed by file id, and keeps focus on the
164
+ * control that held it when that control's row was updated or removed.
165
+ * @returns {void}
166
+ */
148
167
  _renderList(): void;
149
- /** @param {boolean} placeholders @returns {HTMLElement} */
168
+ /**
169
+ * Keyed reconciliation of `FileItem` children. Rows are only moved when out of place, because
170
+ * detaching a row — even to re-insert it a moment later — takes focus out of it.
171
+ * @returns {void}
172
+ */
173
+ _reconcileItems(): void;
174
+ /**
175
+ * The loading region, kept across renders while its shape stays the same so that its live
176
+ * status is not re-announced by every mutation that happens during a load.
177
+ * @param {boolean} placeholders Whether skeleton rows stand in for an empty list.
178
+ * @returns {HTMLElement}
179
+ */
150
180
  _createLoading(placeholders: boolean): HTMLElement;
181
+ /** @param {boolean} placeholders @returns {HTMLElement} */
182
+ _buildLoading(placeholders: boolean): HTMLElement;
151
183
  /** @returns {void} */
152
184
  _destroyItems(): void;
153
185
  /** @param {CustomEvent} event @returns {void} */
@@ -22,7 +22,13 @@ export type FilterField = {
22
22
  */
23
23
  defaultOperator?: string;
24
24
  /**
25
- * Static choices.
25
+ * Glyph beside the field's name in a `searchable` field picker, an
26
+ * icon name or a node; a native `<select>` cannot show one.
27
+ */
28
+ icon?: string | Node;
29
+ /**
30
+ * Static choices; a
31
+ * choice's `icon` shows beside it in a `searchable` value picker.
26
32
  */
27
33
  choices?: Array<{
28
34
  value: string | number | boolean;
@@ -96,11 +102,13 @@ export type FilterOptions = {
96
102
  */
97
103
  maxConditions?: number;
98
104
  /**
99
- * Searchable field, operator and single-choice controls.
105
+ * Searchable field, operator and single-choice controls; a many-valued
106
+ * operator on a field with static choices gets a `TagPicker`.
100
107
  */
101
108
  searchable?: boolean;
102
109
  /**
103
- * Condition layout; compact rows adapt to container width.
110
+ * Condition layout; compact rows adapt to container width and
111
+ * show the group's "and"/"or" between them, a click on it switching the group's logic.
104
112
  */
105
113
  layout?: 'standard' | 'compact';
106
114
  /**
@@ -186,6 +194,8 @@ export type FilterValueMessages = {
186
194
  */
187
195
  valueAt: (label: string, position: number) => string;
188
196
  };
197
+ /** Units a relative date span may be counted in, in the order the editor offers them. */
198
+ export declare const RELATIVE_DATE_UNITS: readonly string[];
189
199
  /**
190
200
  * Backend-neutral dynamic filter expression editor.
191
201
  * @fires Filter#change
@@ -205,6 +215,7 @@ export declare class Filter extends Component<FilterOptions> {
205
215
  type: 'text' | 'number' | 'money' | 'date' | 'datetime' | 'boolean' | 'enum' | 'status' | 'priority' | 'country' | 'currency' | 'unit' | 'entity' | 'tags' | 'custom';
206
216
  operators?: string[];
207
217
  defaultOperator?: string;
218
+ icon?: string | Node;
208
219
  choices?: Array<{
209
220
  value: string | number | boolean;
210
221
  label: string;
@@ -289,10 +300,36 @@ export declare class Filter extends Component<FilterOptions> {
289
300
  _render(): void;
290
301
  /** @param {any} group @param {number} depth @param {boolean} root @returns {HTMLElement} */
291
302
  _renderGroup(group: any, depth: number, root: boolean): HTMLElement;
303
+ /**
304
+ * The word between two rows of a compact group — "and" or "or" — so the logic reads down the
305
+ * list rather than only from the group's legend. A click switches the group's logic. It is a
306
+ * pointer shortcut kept out of the Tab order: the legend's select is the same control, reached
307
+ * once per group rather than once per row. A restricted root shows the word without the switch.
308
+ * @param {any} group Group the rows belong to.
309
+ * @param {boolean} root Whether it is the root group.
310
+ * @returns {HTMLElement}
311
+ */
312
+ _connector(group: any, root: boolean): HTMLElement;
313
+ /**
314
+ * Rewrites a group's connectors after its logic changed through the legend's select, which is
315
+ * not redrawn — the reader's focus is on it.
316
+ * @param {any} group
317
+ * @returns {void}
318
+ */
319
+ _syncConnectors(group: any): void;
292
320
  /** @param {any} node @returns {HTMLElement} */
293
321
  _renderCondition(node: any): HTMLElement;
294
322
  /** @param {any} node @param {FilterField|null} field @param {any} operator @returns {HTMLElement} */
295
323
  _renderValue(node: any, field: FilterField | null, operator: any): HTMLElement;
324
+ /**
325
+ * The editor for a relative date span (`withinLast`, `withinNext`): a whole-number amount and a
326
+ * unit select. Both controls write the pair `[amount, unit]`; a value that is not such a pair —
327
+ * two dates saved by an older editor, say — shows as an empty amount in days.
328
+ * @param {any} node Condition.
329
+ * @param {FilterField} field Date field.
330
+ * @returns {HTMLElement}
331
+ */
332
+ _relativeDateEditor(node: any, field: FilterField): HTMLElement;
296
333
  /**
297
334
  * Owns a themed picker and defers mutation until Select finishes its selection event.
298
335
  * @param {Array<{value:unknown,label:string}>} items Choices.
@@ -307,6 +344,16 @@ export declare class Filter extends Component<FilterOptions> {
307
344
  value: unknown;
308
345
  label: string;
309
346
  }>, value: unknown, label: string, nodeId: string, part: string, changed: (value: unknown) => void): HTMLElement;
347
+ /**
348
+ * Owns a themed multi-value picker for a many-valued operator on a field with static choices:
349
+ * the chosen values as removable tags, the rest in a searchable list. It writes the value without
350
+ * redrawing the editor, so the list stays open while the reader picks several.
351
+ * @param {FilterField} field Field with `choices`.
352
+ * @param {any} node Condition.
353
+ * @param {FilterValueMessages} messages Resolved value-builder text.
354
+ * @returns {HTMLElement} Picker root.
355
+ */
356
+ _tagPicker(field: FilterField, node: any, messages: FilterValueMessages): HTMLElement;
310
357
  /** @param {Event} event @returns {void} */
311
358
  _handleChange(event: Event): void;
312
359
  /** @param {Event} event @returns {void} */
@@ -371,6 +418,83 @@ export declare class Filter extends Component<FilterOptions> {
371
418
  */
372
419
  _message(key: string, fallback: string, ...args: unknown[]): string;
373
420
  }
421
+ /**
422
+ * The word a compact row's connector shows for a group's logic, and the name it is read by. The
423
+ * name starts with the visible word (WCAG 2.5.3, label in name) and says what a click does.
424
+ * @param {'and'|'or'} logic Group logic.
425
+ * @param {(key: string, fallback: string, ...args: unknown[]) => string} [message] Message
426
+ * resolver; omitted uses the built-in English text.
427
+ * @returns {{word: string, name: string}}
428
+ */
429
+ export declare function filterConnectorText(logic: 'and' | 'or', message?: (key: string, fallback: string, ...args: unknown[]) => string): {
430
+ word: string;
431
+ name: string;
432
+ };
433
+ /**
434
+ * The logic a group's connector switches it to: the other one, or null when there is no such
435
+ * group or it is the root and `rootLogic` restricts it. The group's select offers the same two
436
+ * values, so the connector and the select always name one state.
437
+ * @param {FilterAst} value Expression.
438
+ * @param {string} groupId Group to switch.
439
+ * @param {'and'|'or'|null} [rootLogic=null] Root restriction, as the `rootLogic` option.
440
+ * @returns {'and'|'or'|null}
441
+ */
442
+ export declare function nextFilterGroupLogic(value: FilterAst, groupId: string, rootLogic?: 'and' | 'or' | null): 'and' | 'or' | null;
443
+ /**
444
+ * Builds the value of a relative date condition from what its two controls hold: the pair
445
+ * `[amount, unit]`. An empty or non-numeric amount is kept as null — the condition is then
446
+ * incomplete rather than silently zero — and an unknown unit falls back to days.
447
+ * @param {unknown} amount Amount control value.
448
+ * @param {unknown} unit Unit control value.
449
+ * @returns {[number|null, 'days'|'weeks'|'months']}
450
+ */
451
+ export declare function relativeDateValue(amount: unknown, unit: unknown): [number | null, 'days' | 'weeks' | 'months'];
452
+ /**
453
+ * Reads a stored relative date value for display. Anything that is not `[amount, unit]` — null,
454
+ * or two dates written by the date-pair editor these operators used to get — reads as an empty
455
+ * amount in days.
456
+ * @param {unknown} value Stored condition value.
457
+ * @returns {{amount: number|null, unit: 'days'|'weeks'|'months'}}
458
+ */
459
+ export declare function readRelativeDateValue(value: unknown): {
460
+ amount: number | null;
461
+ unit: 'days' | 'weeks' | 'months';
462
+ };
463
+ /**
464
+ * Why a relative date value is unusable, or null when it is a positive whole number of a known
465
+ * unit: `[7, 'days']`, `[2, 'weeks']`, `[3, 'months']`.
466
+ * @param {unknown} value Condition value.
467
+ * @returns {'shape'|'amount'|'unit'|null}
468
+ */
469
+ export declare function relativeDateValueError(value: unknown): 'shape' | 'amount' | 'unit' | null;
470
+ /**
471
+ * Static choices as `TagPicker` items: the raw value — a number stays a number — the label, and
472
+ * the icon as given, a name or a node (the picker copies a node).
473
+ * @param {FilterField['choices']} choices
474
+ * @returns {Array<{value: string|number|boolean, label: string, icon?: Node|string, color?: string}>}
475
+ */
476
+ export declare function filterTagItems(choices: FilterField['choices']): Array<{
477
+ value: string | number | boolean;
478
+ label: string;
479
+ icon?: Node | string;
480
+ color?: string;
481
+ }>;
482
+ /**
483
+ * The value a `TagPicker` change writes into a many-valued condition: a JSON-safe copy of the
484
+ * chosen raw values, in the order chosen.
485
+ * @param {unknown} values Picker values.
486
+ * @returns {import('./filter-model.js').FilterJson}
487
+ */
488
+ export declare function filterTagValue(values: unknown): import('./filter-model.js').FilterJson;
489
+ /**
490
+ * A host's `msg` option with one more message: added as a plain key and to every locale table,
491
+ * since a locale entry is looked up first and would otherwise win.
492
+ * @param {Record<string, any>|null|undefined} msg Host messages, flat or by locale.
493
+ * @param {string} key Message key.
494
+ * @param {string} value Message text.
495
+ * @returns {Record<string, any>}
496
+ */
497
+ export declare function withFilterMessage(msg: Record<string, any> | null | undefined, key: string, value: string): Record<string, any>;
374
498
  /** @event Filter#change @type {CustomEvent<Record<string,unknown>>} */
375
499
  /** @event Filter#apply @type {CustomEvent<{value:FilterAst}>} */
376
500
  /** @event Filter#invalid @type {CustomEvent<Record<string,unknown>>} */
@@ -107,6 +107,14 @@ export type FilterPanelOptions = {
107
107
  * lower bound takes the start of its day and its upper bound the end, so a one-day range matches.
108
108
  */
109
109
  serialize?: FilterPanelSerialize;
110
+ /**
111
+ * IANA zone the calendar days are counted in, such as the
112
+ * ZeyOS instance's `Europe/Vienna`. A day serializes as the first (or last) instant of that day
113
+ * in this zone, and an incoming instant shows as the day it falls on there — the same rule
114
+ * `zeyosForm()` and `zeyosTable()` apply to date-only fields. Null uses the runtime's own zone.
115
+ * An unknown zone throws a `RangeError`.
116
+ */
117
+ timeZone?: string | null;
110
118
  /**
111
119
  * Text shown when `fields` is empty; null resolves
112
120
  * `filterPanel.empty`.
@@ -175,6 +183,11 @@ export type FilterPanelOptions = {
175
183
  * applies every committed edit.
176
184
  * @property {FilterPanelSerialize} [serialize='seconds'] How a date leaves the component. A range's
177
185
  * lower bound takes the start of its day and its upper bound the end, so a one-day range matches.
186
+ * @property {string|null} [timeZone=null] IANA zone the calendar days are counted in, such as the
187
+ * ZeyOS instance's `Europe/Vienna`. A day serializes as the first (or last) instant of that day
188
+ * in this zone, and an incoming instant shows as the day it falls on there — the same rule
189
+ * `zeyosForm()` and `zeyosTable()` apply to date-only fields. Null uses the runtime's own zone.
190
+ * An unknown zone throws a `RangeError`.
178
191
  * @property {string|null} [emptyText=null] Text shown when `fields` is empty; null resolves
179
192
  * `filterPanel.empty`.
180
193
  * @property {Record<string, string>|Record<string, Record<string, string>>} [msg] Localized messages.
@@ -211,6 +224,7 @@ export declare class FilterPanel extends Component<FilterPanelOptions> {
211
224
  _draft: {};
212
225
  _applied: {};
213
226
  _appliedDraft: string;
227
+ _timeZone: string;
214
228
  _fields: {
215
229
  key: string;
216
230
  field: FilterPanelField;
@@ -402,23 +416,29 @@ export declare function isActiveValue(value: unknown): boolean;
402
416
  export declare function pruneValue(value: Record<string, unknown>): Record<string, unknown>;
403
417
  /**
404
418
  * Converts anything a calendar day can arrive as — a `YYYY-MM-DD` string, an ISO timestamp, a
405
- * `Date`, Unix seconds or milliseconds — into the local calendar day a native date input holds.
419
+ * `Date`, Unix seconds or milliseconds — into the calendar day a native date input holds.
406
420
  * Numbers below 1e11 are read as seconds, which is the boundary between the two epochs in use.
421
+ * An instant — Unix seconds or milliseconds, an ISO timestamp — names the day it falls on in
422
+ * `timeZone`. A `Date` is read as a picked day and keeps its local calendar day, matching
423
+ * `calendarDayToUnixSeconds()` in the ZeyOS binding.
407
424
  * @param {unknown} value Candidate day.
425
+ * @param {string|null} [timeZone=null] IANA zone instants are read in; null for the runtime's own.
408
426
  * @returns {string} `YYYY-MM-DD`, or an empty string when there is no day in it.
409
427
  */
410
- export declare function toDateInput(value: unknown): string;
428
+ export declare function toDateInput(value: unknown, timeZone?: string | null): string;
411
429
  /**
412
430
  * Serializes one calendar day at one edge of a range. The `from` edge takes the first instant of
413
- * its local day and the `to` edge the last, so a range whose ends name the same day still matches
414
- * everything recorded on it.
431
+ * its day and the `to` edge the last, so a range whose ends name the same day still matches
432
+ * everything recorded on it. The day is counted in `timeZone`: with `Europe/Vienna`, 2026-03-10
433
+ * starts at 23:00 UTC on the 9th whatever zone the browser is in.
415
434
  * @param {unknown} day Calendar day in any form `toDateInput()` accepts.
416
435
  * @param {FilterPanelEdge} edge Which end of the range the day is.
417
436
  * @param {FilterPanelSerialize} [serialize='seconds'] Output format, or a function receiving the
418
437
  * edge instant as a `Date`.
438
+ * @param {string|null} [timeZone=null] IANA zone the day is counted in; null for the runtime's own.
419
439
  * @returns {unknown} The serialized day, or null when there is no day.
420
440
  */
421
- export declare function serializeDate(day: unknown, edge: FilterPanelEdge, serialize?: FilterPanelSerialize): unknown;
441
+ export declare function serializeDate(day: unknown, edge: FilterPanelEdge, serialize?: FilterPanelSerialize, timeZone?: string | null): unknown;
422
442
  /**
423
443
  * Normalizes declared select options. `{value, label}`, `{ID, name}`, and bare primitives all
424
444
  * arrive from one instance or another.
@@ -435,15 +455,24 @@ export declare function normalizeOptions(options: unknown): Array<{
435
455
  * Running it on a draft returns the same draft, so it is safe on either shape.
436
456
  * @param {Record<string, unknown>|null|undefined} value Incoming values keyed by field.
437
457
  * @param {Record<string, FilterPanelField>} fields Field metadata.
458
+ * @param {string|null} [timeZone=null] IANA zone incoming instants are read in.
438
459
  * @returns {Record<string, unknown>}
439
460
  */
440
- export declare function toDraft(value: Record<string, unknown> | null | undefined, fields: Record<string, FilterPanelField>): Record<string, unknown>;
461
+ export declare function toDraft(value: Record<string, unknown> | null | undefined, fields: Record<string, FilterPanelField>, timeZone?: string | null): Record<string, unknown>;
441
462
  /**
442
463
  * Turns values into the query object a list endpoint is sent: only the constraints that are set,
443
464
  * dates serialized at the right edge, unknown field types excluded.
444
465
  * @param {Record<string, unknown>|null|undefined} value Values keyed by field, raw or drafted.
445
466
  * @param {Record<string, FilterPanelField>} fields Field metadata.
446
467
  * @param {FilterPanelSerialize} [serialize='seconds'] Date output format.
468
+ * @param {string|null} [timeZone=null] IANA zone calendar days are counted in.
447
469
  * @returns {Record<string, unknown>}
448
470
  */
449
- export declare function serializeFilterValue(value: Record<string, unknown> | null | undefined, fields: Record<string, FilterPanelField>, serialize?: FilterPanelSerialize): Record<string, unknown>;
471
+ export declare function serializeFilterValue(value: Record<string, unknown> | null | undefined, fields: Record<string, FilterPanelField>, serialize?: FilterPanelSerialize, timeZone?: string | null): Record<string, unknown>;
472
+ /**
473
+ * Validates the `timeZone` option.
474
+ * @param {unknown} timeZone IANA zone name; nullish or empty means the runtime's own zone.
475
+ * @returns {string|null} Canonical zone name, or null for the runtime's own zone.
476
+ * @throws {RangeError} When the runtime does not know the zone.
477
+ */
478
+ export declare function normalizePanelTimeZone(timeZone: unknown): string | null;
@@ -397,6 +397,8 @@ export type LauncherPageEntry = {
397
397
  */
398
398
  export declare class Launcher extends Component<LauncherOptions> {
399
399
  _createdRoot: boolean;
400
+ /** @type {import('../../core/overlay-stack.js').OverlayHandle|null} Entry on the overlay stack while open. */
401
+ _overlay: import('../../core/overlay-stack.js').OverlayHandle | null;
400
402
  _original: {
401
403
  attributes: string[][];
402
404
  children: ChildNode[];
@@ -468,6 +470,12 @@ export declare class Launcher extends Component<LauncherOptions> {
468
470
  setCurrent(id: string | number | null): this;
469
471
  /** Replaces the root's asynchronous sources and aborts work from the old set; on a page they load once the root is back. @param {LauncherSource[]} sources @returns {this} */
470
472
  setSources(sources: LauncherSource[]): this;
473
+ /**
474
+ * Takes the launcher off the overlay stack. Safe to call repeatedly.
475
+ * @returns {void}
476
+ * @private
477
+ */
478
+ private _releaseOverlay;
471
479
  /** Aborts sources and removes the owned dialog. @returns {void} */
472
480
  destroy(): void;
473
481
  /**
@@ -341,8 +341,10 @@ export declare class ListToolbar extends Component<ListToolbarOptions> {
341
341
  */
342
342
  focusSearch(): this;
343
343
  /**
344
- * Optional sugar for a `TableView` or `CardView`: it wires the shape switch to the view and
345
- * mounts the view's field chooser into this bar.
344
+ * Optional sugar for a `TableView`, `CardView`, or `KanbanView`: it wires the shape switch to
345
+ * the view and mounts the view's field chooser into this bar — through the view's public
346
+ * `mountFieldControls()` when it has one, which every `RecordView` does. A `TableView` with the
347
+ * default `fieldControls: true` contributes its Table's column chooser.
346
348
  *
347
349
  * Nothing is imported and nothing is required — every capability is feature-detected, so a view
348
350
  * that offers none of them still works and still gets `viewchange`, and the host swaps the view
@@ -410,7 +412,8 @@ export declare class ListToolbar extends Component<ListToolbarOptions> {
410
412
  */
411
413
  _mountFieldControls(view: Record<string, any>): void;
412
414
  /**
413
- * Finds a view's field chooser without importing the view, newest accessor first.
415
+ * Finds a view's field chooser without importing the view: its public `getFieldControls()`,
416
+ * else — for an object that only looks like a record view — the shared chooser's class.
414
417
  * @param {Record<string, any>} view Bound view.
415
418
  * @returns {Element|null}
416
419
  */
@@ -470,6 +473,7 @@ export type AdoptedElement = {
470
473
  element: Element;
471
474
  parent: Node | null;
472
475
  next: Node | null;
476
+ viaView?: boolean;
473
477
  };
474
478
  export type RecordViewCapabilities = {
475
479
  /**
@@ -489,7 +493,8 @@ export type RecordViewCapabilities = {
489
493
  */
490
494
  events: boolean;
491
495
  /**
492
- * Whether the object offers its field chooser through a method.
496
+ * Whether the object offers its field chooser through a method
497
+ * (`getFieldControls()`, which every `RecordView` has).
493
498
  */
494
499
  fieldControls: boolean;
495
500
  };
@@ -521,14 +526,18 @@ export type RecordViewCapabilities = {
521
526
  * @property {boolean} pressed Current pressed state.
522
527
  * @property {((event: MouseEvent) => void)|null} onclick Descriptor callback.
523
528
  */
524
- /** @typedef {{element: Element, parent: Node|null, next: Node|null}} AdoptedElement */
529
+ /**
530
+ * @typedef {{element: Element, parent: Node|null, next: Node|null, viaView?: boolean}} AdoptedElement
531
+ * `viaView` marks a field chooser the bound view moved here itself and takes back on `unbind()`.
532
+ */
525
533
  /**
526
534
  * @typedef {Object} RecordViewCapabilities
527
535
  * @property {boolean} isRecordView Whether the object publishes the record-view state surface.
528
536
  * @property {string|null} setShape Method that changes the view shape, if any.
529
537
  * @property {string|null} getShape Method that reads the view shape, if any.
530
538
  * @property {boolean} events Whether the object emits component events.
531
- * @property {boolean} fieldControls Whether the object offers its field chooser through a method.
539
+ * @property {boolean} fieldControls Whether the object offers its field chooser through a method
540
+ * (`getFieldControls()`, which every `RecordView` has).
532
541
  */
533
542
  /**
534
543
  * Describes what `bind()` can wire on an object, by feature rather than by class.
@@ -110,6 +110,12 @@ export declare class MenuButton extends Component<MenuButtonOptions> {
110
110
  * @returns {this}
111
111
  */
112
112
  close(): this;
113
+ /**
114
+ * Opens the menu when it is closed, and closes it when it is open. Opening this way moves no
115
+ * focus; `focusFirst()` opens with focus on the first item.
116
+ * @returns {this}
117
+ */
118
+ toggle(): this;
113
119
  /**
114
120
  * Reports whether the menu is open.
115
121
  * @returns {boolean}