@zeyos/zx 2.1.0 → 2.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.
- package/CHANGELOG.md +39 -0
- package/README.md +15 -0
- package/dist/types/compat/base.d.ts +156 -0
- package/dist/types/compat/globals.d.ts +20 -0
- package/dist/types/compat/index.d.ts +128 -0
- package/dist/types/compat/map/basic.d.ts +175 -0
- package/dist/types/compat/map/data.d.ts +102 -0
- package/dist/types/compat/map/date-time.d.ts +80 -0
- package/dist/types/compat/map/factory.d.ts +9 -0
- package/dist/types/compat/map/form.d.ts +98 -0
- package/dist/types/compat/map/helpers.d.ts +12 -0
- package/dist/types/compat/map/http.d.ts +36 -0
- package/dist/types/compat/map/layout.d.ts +106 -0
- package/dist/types/compat/map/options.d.ts +80 -0
- package/dist/types/compat/map/select.d.ts +95 -0
- package/dist/types/compat/map/stubs.d.ts +32 -0
- package/dist/types/compat/map/utilities.d.ts +37 -0
- package/dist/types/compat-entry.d.ts +5 -0
- package/dist/types/components/badge/badge.d.ts +46 -0
- package/dist/types/components/breadcrumb/breadcrumb.d.ts +200 -0
- package/dist/types/components/button/button.d.ts +42 -0
- package/dist/types/components/check-button/check-button.d.ts +98 -0
- package/dist/types/components/checklist/checklist.d.ts +143 -0
- package/dist/types/components/checklist/field-adapter.d.ts +5 -0
- package/dist/types/components/context-menu/context-menu.d.ts +130 -0
- package/dist/types/components/copy/copy-button.d.ts +48 -0
- package/dist/types/components/copy/copy-input.d.ts +91 -0
- package/dist/types/components/data-filter/data-filter.d.ts +250 -0
- package/dist/types/components/data-filter/filter-core.d.ts +52 -0
- package/dist/types/components/date-picker/date-picker.d.ts +137 -0
- package/dist/types/components/date-picker/date-range-picker.d.ts +350 -0
- package/dist/types/components/date-picker/field-adapter.d.ts +6 -0
- package/dist/types/components/date-picker/month-picker.d.ts +75 -0
- package/dist/types/components/date-picker/range-field-adapter.d.ts +7 -0
- package/dist/types/components/date-picker/time-picker.d.ts +127 -0
- package/dist/types/components/datebox/date-range-box.d.ts +218 -0
- package/dist/types/components/datebox/datebox.d.ts +160 -0
- package/dist/types/components/datebox/field-adapter.d.ts +5 -0
- package/dist/types/components/dialog/dialog.d.ts +284 -0
- package/dist/types/components/dropdown/dropdown.d.ts +118 -0
- package/dist/types/components/empty-state/empty-state.d.ts +38 -0
- package/dist/types/components/field/field.d.ts +231 -0
- package/dist/types/components/field-upload/field-adapter.d.ts +5 -0
- package/dist/types/components/field-upload/field-upload.d.ts +213 -0
- package/dist/types/components/fieldset/fieldset.d.ts +125 -0
- package/dist/types/components/finder/finder.d.ts +252 -0
- package/dist/types/components/form/form.d.ts +194 -0
- package/dist/types/components/groupbox/groupbox.d.ts +89 -0
- package/dist/types/components/layout/layout.d.ts +132 -0
- package/dist/types/components/loading/inline-loading.d.ts +86 -0
- package/dist/types/components/loading/progress-bar.d.ts +168 -0
- package/dist/types/components/loading/spinner.d.ts +34 -0
- package/dist/types/components/master-panel/master-panel.d.ts +112 -0
- package/dist/types/components/menu-button/menu-button.d.ts +142 -0
- package/dist/types/components/message/message.d.ts +212 -0
- package/dist/types/components/modal/modal.d.ts +105 -0
- package/dist/types/components/multi-value-editor/field-adapter.d.ts +5 -0
- package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +66 -0
- package/dist/types/components/navigation-bar/navigation-bar.d.ts +229 -0
- package/dist/types/components/number-field/field-adapter.d.ts +5 -0
- package/dist/types/components/number-field/number-field.d.ts +292 -0
- package/dist/types/components/pagination/pagination.d.ts +267 -0
- package/dist/types/components/panel/panel.d.ts +194 -0
- package/dist/types/components/permission/permission.d.ts +93 -0
- package/dist/types/components/rating/field-adapter.d.ts +5 -0
- package/dist/types/components/rating/rating.d.ts +213 -0
- package/dist/types/components/search/search.d.ts +98 -0
- package/dist/types/components/select/field-adapter.d.ts +5 -0
- package/dist/types/components/select/filter.d.ts +11 -0
- package/dist/types/components/select/select.d.ts +235 -0
- package/dist/types/components/skeleton/skeleton.d.ts +97 -0
- package/dist/types/components/slider/field-adapter.d.ts +5 -0
- package/dist/types/components/slider/slider.d.ts +216 -0
- package/dist/types/components/split-view/split-view.d.ts +335 -0
- package/dist/types/components/stepper/stepper.d.ts +314 -0
- package/dist/types/components/stepper/steps.d.ts +131 -0
- package/dist/types/components/tabbox/tabbox.d.ts +230 -0
- package/dist/types/components/table/sort.d.ts +49 -0
- package/dist/types/components/table/table.d.ts +872 -0
- package/dist/types/components/tag-picker/field-adapter.d.ts +5 -0
- package/dist/types/components/tag-picker/tag-picker.d.ts +375 -0
- package/dist/types/components/timebox/field-adapter.d.ts +5 -0
- package/dist/types/components/timebox/timebox.d.ts +121 -0
- package/dist/types/components/toggle/field-adapter.d.ts +5 -0
- package/dist/types/components/toggle/toggle.d.ts +94 -0
- package/dist/types/components/toolbar/toolbar.d.ts +230 -0
- package/dist/types/components/tooltip/tooltip.d.ts +183 -0
- package/dist/types/components/tree/hierarchy.d.ts +113 -0
- package/dist/types/components/tree/tree.d.ts +383 -0
- package/dist/types/components/truncate/truncate.d.ts +61 -0
- package/dist/types/components/value-list/field-adapter.d.ts +5 -0
- package/dist/types/components/value-list/value-list.d.ts +143 -0
- package/dist/types/core/breakpoint.d.ts +68 -0
- package/dist/types/core/component.d.ts +115 -0
- package/dist/types/core/date.d.ts +50 -0
- package/dist/types/core/dom.d.ts +86 -0
- package/dist/types/core/export.d.ts +70 -0
- package/dist/types/core/fontawesome.d.ts +107 -0
- package/dist/types/core/format.d.ts +107 -0
- package/dist/types/core/http.d.ts +122 -0
- package/dist/types/core/i18n.d.ts +35 -0
- package/dist/types/core/icons.d.ts +137 -0
- package/dist/types/core/keyboard.d.ts +72 -0
- package/dist/types/core/position.d.ts +45 -0
- package/dist/types/core/storage.d.ts +46 -0
- package/dist/types/core/util.d.ts +117 -0
- package/dist/types/elements/define.d.ts +73 -0
- package/dist/types/elements/reflect.d.ts +27 -0
- package/dist/types/index.d.ts +79 -0
- package/dist/types/zeyos/connect.d.ts +65 -0
- package/dist/types/zeyos/form.d.ts +140 -0
- package/dist/types/zeyos/icons.d.ts +104 -0
- package/dist/types/zeyos/index.d.ts +12 -0
- package/dist/types/zeyos/modules.d.ts +110 -0
- package/dist/types/zeyos/query.d.ts +157 -0
- package/dist/types/zeyos/schema.d.ts +79 -0
- package/dist/types/zeyos/select.d.ts +167 -0
- package/dist/types/zeyos/table.d.ts +205 -0
- package/dist/zx-compat.esm.js +362 -33
- package/dist/zx-compat.esm.min.js +1 -1
- package/dist/zx-compat.global.js +359 -67
- package/dist/zx-compat.global.min.js +3 -3
- package/dist/zx-zeyos.esm.js +342 -43
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +68 -6
- package/dist/zx.esm.js +346 -67
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +346 -67
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +48 -2
- package/docs/llms.md +28 -0
- package/package.json +37 -9
- package/src/compat/base.js +291 -0
- package/src/compat/globals.js +165 -0
- package/src/compat/index.js +84 -0
- package/src/compat/map/basic.js +464 -0
- package/src/compat/map/data.js +232 -0
- package/src/compat/map/date-time.js +177 -0
- package/src/compat/map/factory.js +45 -0
- package/src/compat/map/form.js +330 -0
- package/src/compat/map/helpers.js +46 -0
- package/src/compat/map/http.js +117 -0
- package/src/compat/map/layout.js +256 -0
- package/src/compat/map/options.js +267 -0
- package/src/compat/map/select.js +198 -0
- package/src/compat/map/stubs.js +26 -0
- package/src/compat/map/utilities.js +113 -0
- package/src/compat-entry.js +11 -0
- package/src/components/badge/badge.css +147 -0
- package/src/components/badge/badge.js +92 -0
- package/src/components/breadcrumb/breadcrumb.css +105 -0
- package/src/components/breadcrumb/breadcrumb.js +331 -0
- package/src/components/button/button.css +104 -0
- package/src/components/button/button.js +76 -0
- package/src/components/check-button/check-button.css +66 -0
- package/src/components/check-button/check-button.js +167 -0
- package/src/components/checklist/checklist.css +65 -0
- package/src/components/checklist/checklist.js +282 -0
- package/src/components/checklist/field-adapter.js +46 -0
- package/src/components/context-menu/context-menu.css +54 -0
- package/src/components/context-menu/context-menu.js +334 -0
- package/src/components/copy/copy-button.css +27 -0
- package/src/components/copy/copy-button.js +78 -0
- package/src/components/copy/copy-input.css +59 -0
- package/src/components/copy/copy-input.js +123 -0
- package/src/components/data-filter/data-filter.css +53 -0
- package/src/components/data-filter/data-filter.js +400 -0
- package/src/components/data-filter/filter-core.js +128 -0
- package/src/components/date-picker/date-picker.css +181 -0
- package/src/components/date-picker/date-picker.js +500 -0
- package/src/components/date-picker/date-range-picker.css +264 -0
- package/src/components/date-picker/date-range-picker.js +990 -0
- package/src/components/date-picker/field-adapter.js +36 -0
- package/src/components/date-picker/month-picker.js +223 -0
- package/src/components/date-picker/range-field-adapter.js +31 -0
- package/src/components/date-picker/time-picker.css +191 -0
- package/src/components/date-picker/time-picker.js +406 -0
- package/src/components/datebox/date-range-box.css +128 -0
- package/src/components/datebox/date-range-box.js +492 -0
- package/src/components/datebox/datebox.css +108 -0
- package/src/components/datebox/datebox.js +358 -0
- package/src/components/datebox/field-adapter.js +34 -0
- package/src/components/dialog/dialog.css +74 -0
- package/src/components/dialog/dialog.js +450 -0
- package/src/components/dropdown/dropdown.css +24 -0
- package/src/components/dropdown/dropdown.js +288 -0
- package/src/components/empty-state/empty-state.css +80 -0
- package/src/components/empty-state/empty-state.js +92 -0
- package/src/components/field/field.css +127 -0
- package/src/components/field/field.js +605 -0
- package/src/components/field-upload/field-adapter.js +21 -0
- package/src/components/field-upload/field-upload.css +108 -0
- package/src/components/field-upload/field-upload.js +475 -0
- package/src/components/fieldset/fieldset.css +37 -0
- package/src/components/fieldset/fieldset.js +307 -0
- package/src/components/finder/finder.css +98 -0
- package/src/components/finder/finder.js +509 -0
- package/src/components/form/form.css +32 -0
- package/src/components/form/form.js +302 -0
- package/src/components/groupbox/groupbox.css +51 -0
- package/src/components/groupbox/groupbox.js +199 -0
- package/src/components/layout/layout.css +117 -0
- package/src/components/layout/layout.js +136 -0
- package/src/components/loading/inline-loading.css +34 -0
- package/src/components/loading/inline-loading.js +140 -0
- package/src/components/loading/progress-bar.css +115 -0
- package/src/components/loading/progress-bar.js +259 -0
- package/src/components/loading/spinner.css +58 -0
- package/src/components/loading/spinner.js +57 -0
- package/src/components/master-panel/master-panel.css +51 -0
- package/src/components/master-panel/master-panel.js +203 -0
- package/src/components/menu-button/menu-button.css +49 -0
- package/src/components/menu-button/menu-button.js +294 -0
- package/src/components/message/message.css +122 -0
- package/src/components/message/message.js +499 -0
- package/src/components/modal/modal.css +47 -0
- package/src/components/modal/modal.js +203 -0
- package/src/components/multi-value-editor/field-adapter.js +44 -0
- package/src/components/multi-value-editor/multi-value-editor.css +56 -0
- package/src/components/multi-value-editor/multi-value-editor.js +170 -0
- package/src/components/navigation-bar/navigation-bar.css +130 -0
- package/src/components/navigation-bar/navigation-bar.js +450 -0
- package/src/components/number-field/field-adapter.js +40 -0
- package/src/components/number-field/number-field.css +77 -0
- package/src/components/number-field/number-field.js +545 -0
- package/src/components/pagination/pagination.css +95 -0
- package/src/components/pagination/pagination.js +481 -0
- package/src/components/panel/panel.css +123 -0
- package/src/components/panel/panel.js +336 -0
- package/src/components/permission/permission.css +47 -0
- package/src/components/permission/permission.js +198 -0
- package/src/components/rating/field-adapter.js +34 -0
- package/src/components/rating/rating.css +97 -0
- package/src/components/rating/rating.js +395 -0
- package/src/components/search/search.css +70 -0
- package/src/components/search/search.js +193 -0
- package/src/components/select/field-adapter.js +24 -0
- package/src/components/select/filter.js +39 -0
- package/src/components/select/select.css +180 -0
- package/src/components/select/select.js +663 -0
- package/src/components/skeleton/skeleton.css +76 -0
- package/src/components/skeleton/skeleton.js +139 -0
- package/src/components/slider/field-adapter.js +36 -0
- package/src/components/slider/slider.css +181 -0
- package/src/components/slider/slider.js +399 -0
- package/src/components/split-view/split-view.css +139 -0
- package/src/components/split-view/split-view.js +806 -0
- package/src/components/stepper/stepper.css +234 -0
- package/src/components/stepper/stepper.js +459 -0
- package/src/components/stepper/steps.js +131 -0
- package/src/components/tabbox/tabbox.css +281 -0
- package/src/components/tabbox/tabbox.js +484 -0
- package/src/components/table/sort.js +85 -0
- package/src/components/table/table.css +364 -0
- package/src/components/table/table.js +1693 -0
- package/src/components/tag-picker/field-adapter.js +35 -0
- package/src/components/tag-picker/tag-picker.css +169 -0
- package/src/components/tag-picker/tag-picker.js +837 -0
- package/src/components/timebox/field-adapter.js +24 -0
- package/src/components/timebox/timebox.css +51 -0
- package/src/components/timebox/timebox.js +276 -0
- package/src/components/toggle/field-adapter.js +24 -0
- package/src/components/toggle/toggle.css +66 -0
- package/src/components/toggle/toggle.js +150 -0
- package/src/components/toolbar/toolbar.css +81 -0
- package/src/components/toolbar/toolbar.js +511 -0
- package/src/components/tooltip/tooltip.css +36 -0
- package/src/components/tooltip/tooltip.js +420 -0
- package/src/components/tree/hierarchy.js +151 -0
- package/src/components/tree/tree.css +99 -0
- package/src/components/tree/tree.js +784 -0
- package/src/components/truncate/truncate.css +20 -0
- package/src/components/truncate/truncate.js +92 -0
- package/src/components/value-list/field-adapter.js +24 -0
- package/src/components/value-list/value-list.css +108 -0
- package/src/components/value-list/value-list.js +336 -0
- package/src/core/breakpoint.js +150 -0
- package/src/core/component.js +292 -0
- package/src/core/date.js +216 -0
- package/src/core/dom.js +260 -0
- package/src/core/export.js +204 -0
- package/src/core/fontawesome.js +177 -0
- package/src/core/format.js +283 -0
- package/src/core/http.js +246 -0
- package/src/core/i18n.js +83 -0
- package/src/core/icons.js +283 -0
- package/src/core/keyboard.js +240 -0
- package/src/core/position.js +177 -0
- package/src/core/storage.js +175 -0
- package/src/core/util.js +336 -0
- package/src/elements/define.js +715 -0
- package/src/elements/reflect.js +79 -0
- package/src/index.js +131 -0
- package/src/zeyos/connect.js +142 -0
- package/src/zeyos/form.js +254 -0
- package/src/zeyos/icons.js +92 -0
- package/src/zeyos/index.js +21 -0
- package/src/zeyos/modules.js +269 -0
- package/src/zeyos/query.js +199 -0
- package/src/zeyos/schema.js +474 -0
- package/src/zeyos/select.js +175 -0
- package/src/zeyos/table.js +272 -0
- package/styles/base.css +124 -0
- package/styles/icons.css +34 -0
- package/styles/tokens/dark.css +84 -0
- package/styles/tokens/density.css +9 -0
- package/styles/tokens/global.css +80 -0
- package/styles/tokens/modules.css +109 -0
- package/styles/tokens/semantic.css +49 -0
- package/styles/zx.css +61 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Groupbox as ZxGroupbox,
|
|
3
|
+
MasterPanel as ZxMasterPanel,
|
|
4
|
+
NavigationBar as ZxNavigationBar,
|
|
5
|
+
Panel as ZxPanel,
|
|
6
|
+
Search as ZxSearch,
|
|
7
|
+
Tabbox as ZxTabbox
|
|
8
|
+
} from '../../index.js';
|
|
9
|
+
import { GxWrapper } from '../base.js';
|
|
10
|
+
import { legacyContent, targetElement } from './helpers.js';
|
|
11
|
+
import { LEGACY_EVENT_ARGS, translateTabboxOptions } from './options.js';
|
|
12
|
+
|
|
13
|
+
/** Legacy ZeyOS collapsible groupbox. */
|
|
14
|
+
export class Groupbox extends GxWrapper {
|
|
15
|
+
static legacyName = 'gx.zeyos.Groupbox';
|
|
16
|
+
|
|
17
|
+
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
18
|
+
constructor(display, options = {}) {
|
|
19
|
+
super(options, { title: '', open: true });
|
|
20
|
+
const component = new ZxGroupbox(targetElement(display), {
|
|
21
|
+
title: String(options.title ?? ''), open: options.open !== false
|
|
22
|
+
});
|
|
23
|
+
this._attach(component, {
|
|
24
|
+
events: {
|
|
25
|
+
open: { type: 'open', args: () => [this] },
|
|
26
|
+
close: { type: 'close', args: () => [this] }
|
|
27
|
+
},
|
|
28
|
+
ui: { title: 'summary', inner: 'content' },
|
|
29
|
+
setters: { title: 'setTitle', open: (value) => value ? this.open() : this.close() }
|
|
30
|
+
});
|
|
31
|
+
if (Object.hasOwn(options, 'content')) component.setContent(legacyContent(options.content));
|
|
32
|
+
this._syncAct();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @returns {this} */
|
|
36
|
+
toggle() { this._zx.toggle(); this._syncAct(); return this; }
|
|
37
|
+
/** @returns {this} */
|
|
38
|
+
open() { this._zx.open(); this._syncAct(); return this; }
|
|
39
|
+
/** @returns {this} */
|
|
40
|
+
close() { this._zx.close(); this._syncAct(); return this; }
|
|
41
|
+
/** @returns {boolean} */
|
|
42
|
+
isOpen() { return this._zx.isOpen(); }
|
|
43
|
+
/** @param {string} title @returns {this} */
|
|
44
|
+
setTitle(title) { this._zx.setTitle(title); return this; }
|
|
45
|
+
/** @returns {void} */
|
|
46
|
+
_syncAct() { this._mirrorAct(this.display('title'), this.isOpen()); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Legacy positional panel wrapper. */
|
|
50
|
+
export class Panel extends GxWrapper {
|
|
51
|
+
static legacyName = 'gx.zeyos.Panel';
|
|
52
|
+
|
|
53
|
+
/** @param {Element|string|null} display @param {string} title @param {unknown} content @param {boolean} [open=true] */
|
|
54
|
+
constructor(display, title = '', content = null, open = true) {
|
|
55
|
+
super({ title, content, open });
|
|
56
|
+
const component = new ZxPanel(targetElement(display), {
|
|
57
|
+
title: String(title ?? ''), content: legacyContent(content), open: open !== false
|
|
58
|
+
});
|
|
59
|
+
this._attach(component, {
|
|
60
|
+
events: { open: 'open', close: 'close' },
|
|
61
|
+
// `title` is the clickable header: the Zx panel splits that into a toggle plus an action
|
|
62
|
+
// area, and the toggle is what the legacy display key stood for.
|
|
63
|
+
ui: { title: 'toggle', header: 'header', inner: 'content', content: 'content' },
|
|
64
|
+
setters: { title: 'setTitle', content: 'setContent', open: (value) => value ? this.open() : this.close() }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @returns {this} */
|
|
69
|
+
toggle() { this._zx.toggle(); return this; }
|
|
70
|
+
/** @returns {this} */
|
|
71
|
+
open() { this._zx.open(); return this; }
|
|
72
|
+
/** @returns {this} */
|
|
73
|
+
close() { this._zx.close(); return this; }
|
|
74
|
+
/** @returns {boolean} */
|
|
75
|
+
isOpen() { return this._zx.isOpen(); }
|
|
76
|
+
/** @param {unknown} content @returns {this} */
|
|
77
|
+
setContent(content) { this._zx.setContent(legacyContent(content)); return this; }
|
|
78
|
+
/** @param {string} title @returns {this} */
|
|
79
|
+
setTitle(title) { this._zx.setTitle(title); return this; }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Legacy positional master panel wrapper. */
|
|
83
|
+
export class MasterPanel extends GxWrapper {
|
|
84
|
+
static legacyName = 'gx.zeyos.MasterPanel';
|
|
85
|
+
|
|
86
|
+
/** @param {Element|string|null} display @param {string} title @param {unknown} content @param {unknown[]} [buttons=[]] */
|
|
87
|
+
constructor(display, title = '', content = null, buttons = []) {
|
|
88
|
+
super({ title, content, buttons });
|
|
89
|
+
const component = new ZxMasterPanel(targetElement(display), {
|
|
90
|
+
title: String(title ?? ''), content: legacyContent(content), buttons: normalizeButtons(buttons)
|
|
91
|
+
});
|
|
92
|
+
this._attach(component, {
|
|
93
|
+
ui: { title: 'title', inner: 'content', content: 'content', buttons: 'buttons' },
|
|
94
|
+
setters: { title: 'setTitle', content: 'setContent', buttons: (value) => component.setButtons(normalizeButtons(value)) }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** @param {unknown} content @returns {this} */
|
|
99
|
+
setContent(content) { this._zx.setContent(legacyContent(content)); return this; }
|
|
100
|
+
/** @param {string} title @returns {this} */
|
|
101
|
+
setTitle(title) { this._zx.setTitle(title); return this; }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Shared legacy tabbox implementation; subclasses only change warning identity. */
|
|
105
|
+
export class Tabbox extends GxWrapper {
|
|
106
|
+
static legacyName = 'gx.zeyos.Tabbox';
|
|
107
|
+
|
|
108
|
+
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
109
|
+
constructor(display, options = {}) {
|
|
110
|
+
super(options, { frames: [], show: 1 });
|
|
111
|
+
const translated = translateTabboxOptions(options);
|
|
112
|
+
const component = new ZxTabbox(targetElement(display), {
|
|
113
|
+
tabs: translated.tabs.map(normalizeTab), active: translated.active
|
|
114
|
+
});
|
|
115
|
+
this._attach(component, {
|
|
116
|
+
events: {
|
|
117
|
+
change: { type: 'change', args: (detail) => LEGACY_EVENT_ARGS.tabChange(detail) },
|
|
118
|
+
close: { type: 'close', args: (detail) => [detail.name] }
|
|
119
|
+
},
|
|
120
|
+
ui: { tablist: 'tablist', content: 'panels', div: 'tablist' },
|
|
121
|
+
setters: { show: 'openTab', height: (value) => this.setStyle('height', value) }
|
|
122
|
+
});
|
|
123
|
+
if (translated.height != null) this.setStyle('height', translated.height);
|
|
124
|
+
component.on('change', () => queueMicrotask(() => this._syncAct()));
|
|
125
|
+
this._syncAct();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @param {Record<string, any>|string} frame @param {string} [title] @param {unknown} [content] @returns {this} */
|
|
129
|
+
addTab(frame, title, content) {
|
|
130
|
+
const definition = typeof frame === 'object' ? frame : { name: frame, title, content };
|
|
131
|
+
this._zx.addTab(normalizeTab(definition));
|
|
132
|
+
this._syncAct();
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** @param {string} name @returns {this} */
|
|
137
|
+
closeTab(name) { this._zx.removeTab(String(name)); this._syncAct(); return this; }
|
|
138
|
+
/** @param {string|number} name @returns {this} */
|
|
139
|
+
openTab(name) {
|
|
140
|
+
const resolved = typeof name === 'number' ? this._zx._tabs?.[name - 1]?.definition.name : String(name);
|
|
141
|
+
if (resolved) this._zx.openTab(resolved);
|
|
142
|
+
this._syncAct();
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
/** @param {string} name @param {string} title @returns {this} */
|
|
146
|
+
setTabTitle(name, title) { this._zx.setTitle(String(name), title); return this; }
|
|
147
|
+
/** @param {string} name @param {unknown} content @param {string} [_style] @returns {this} */
|
|
148
|
+
setHighlight(name, content, _style) { this._zx.setBadge(String(name), content == null || content === '' ? null : String(content)); return this; }
|
|
149
|
+
/** @returns {string|null} */
|
|
150
|
+
getActive() { return this._zx.getActive(); }
|
|
151
|
+
/** @returns {void} */
|
|
152
|
+
_syncAct() {
|
|
153
|
+
for (const tab of this.display('tablist')?.querySelectorAll?.('[role="tab"]') ?? []) {
|
|
154
|
+
this._mirrorAct(tab, tab.getAttribute('aria-selected') === 'true');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Bootstrap-flavoured tabbox with the same behavior. */
|
|
160
|
+
export class BootstrapTabbox extends Tabbox {
|
|
161
|
+
static legacyName = 'gx.bootstrap.Tabbox';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Legacy bootstrap navigation bar. */
|
|
165
|
+
export class NavigationBar extends GxWrapper {
|
|
166
|
+
static legacyName = 'gx.bootstrap.NavigationBar';
|
|
167
|
+
|
|
168
|
+
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
169
|
+
constructor(display, options = {}) {
|
|
170
|
+
super(options, { frames: [], title: '', buttons: [] });
|
|
171
|
+
const frames = Array.isArray(options.frames) ? options.frames : [];
|
|
172
|
+
this._frames = frames.map((frame) => ({ ...frame }));
|
|
173
|
+
const active = typeof options.show === 'number' ? frames[options.show - 1]?.name : options.show;
|
|
174
|
+
const component = new ZxNavigationBar(targetElement(display), {
|
|
175
|
+
title: String(options.title ?? ''),
|
|
176
|
+
items: frames.map(normalizeTab),
|
|
177
|
+
active: active == null ? null : String(active),
|
|
178
|
+
actions: normalizeButtons(options.buttons ?? [])
|
|
179
|
+
});
|
|
180
|
+
this._attach(component, {
|
|
181
|
+
events: { change: { type: 'change', args: (detail) => [detail.name] } },
|
|
182
|
+
ui: { title: 'title', tablist: 'items', content: 'panels', buttons: 'actions' },
|
|
183
|
+
setters: { title: 'setTitle' }
|
|
184
|
+
});
|
|
185
|
+
component.on('change', () => queueMicrotask(() => this._syncAct()));
|
|
186
|
+
this._syncAct();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** @param {Record<string, any>|string} frame @param {string} [title] @param {unknown} [content] @returns {this} */
|
|
190
|
+
addTab(frame, title, content) {
|
|
191
|
+
const definition = typeof frame === 'object' ? { ...frame } : { name: frame, title, content };
|
|
192
|
+
this._frames.push(definition); this._rebuild(); return this;
|
|
193
|
+
}
|
|
194
|
+
/** @param {string} name @returns {this} */
|
|
195
|
+
closeTab(name) { this._frames = this._frames.filter((frame) => String(frame.name) !== String(name)); this._rebuild(); return this; }
|
|
196
|
+
/** @param {string} name @returns {this} */
|
|
197
|
+
openTab(name) { this._zx.setActive(String(name)); this._syncAct(); return this; }
|
|
198
|
+
/** @param {string|Element} title @returns {this} */
|
|
199
|
+
setTitle(title) { this._zx.setTitle(typeof title === 'string' ? title : title?.textContent ?? ''); return this; }
|
|
200
|
+
/** @param {string} name @param {string} title @returns {this} */
|
|
201
|
+
setTabTitle(name, title) { const frame = this._frames.find((item) => String(item.name) === String(name)); if (frame) frame.title = title; this._rebuild(); return this; }
|
|
202
|
+
/** @param {unknown[]} buttons @returns {this} */
|
|
203
|
+
setNavigationButtons(buttons) { this._zx.setActions(normalizeButtons(buttons)); return this; }
|
|
204
|
+
/** @param {string} name @param {unknown} content @param {string} [_style] @returns {this} */
|
|
205
|
+
setHighlight(name, content, _style) { this._zx.setBadge(String(name), content == null || content === '' ? null : String(content)); return this; }
|
|
206
|
+
/** @returns {void} */
|
|
207
|
+
_rebuild() { const active = this._zx._activeName; this._zx.setItems(this._frames.map(normalizeTab)); if (active && this._frames.some((frame) => String(frame.name) === String(active))) this._zx.setActive(active); this._syncAct(); }
|
|
208
|
+
/** @returns {void} */
|
|
209
|
+
_syncAct() { for (const item of this.display('tablist')?.querySelectorAll?.('[role="tab"]') ?? []) this._mirrorAct(item, item.getAttribute('aria-selected') === 'true'); }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Legacy standalone search control. */
|
|
213
|
+
export class Search extends GxWrapper {
|
|
214
|
+
static legacyName = 'gx.zeyos.Search';
|
|
215
|
+
|
|
216
|
+
/** @param {Record<string, any>} [options={}] */
|
|
217
|
+
constructor(options = {}) {
|
|
218
|
+
super(options);
|
|
219
|
+
const component = new ZxSearch(null, { placeholder: options.placeholder ?? '', debounce: options.debounce ?? 0 });
|
|
220
|
+
this._attach(component, {
|
|
221
|
+
events: {
|
|
222
|
+
input: { type: 'input', args: (_detail, event) => [this, component.refs.input, event] }
|
|
223
|
+
},
|
|
224
|
+
ui: { input: 'input', submit: 'submit', button: 'submit' }
|
|
225
|
+
});
|
|
226
|
+
this._listen(component.refs.input, 'keydown', (event) => {
|
|
227
|
+
if (event.key === 'Enter') this.fireEvent('keypress', [this, component.refs.input, event]);
|
|
228
|
+
});
|
|
229
|
+
this._listen(component.refs.submit, 'click', (event) => this.fireEvent('click', [this, component.refs.input, event]));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** @returns {string} */
|
|
233
|
+
get() { return this._zx.get(); }
|
|
234
|
+
/** @param {string} value @returns {this} */
|
|
235
|
+
set(value) { this._zx.set(value); return this; }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** @param {Record<string, any>} frame @returns {Record<string, any>} */
|
|
239
|
+
function normalizeTab(frame) {
|
|
240
|
+
let content = legacyContent(frame.content);
|
|
241
|
+
if (typeof content === 'string' || typeof content === 'number' || content == null) {
|
|
242
|
+
content = document.createTextNode(content == null ? '' : String(content));
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
name: String(frame.name ?? ''),
|
|
246
|
+
title: String(frame.title ?? ''),
|
|
247
|
+
content,
|
|
248
|
+
closable: Boolean(frame.closable),
|
|
249
|
+
disabled: Boolean(frame.disabled)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** @param {unknown} list @returns {Element[]} */
|
|
254
|
+
function normalizeButtons(list) {
|
|
255
|
+
return (Array.isArray(list) ? list : [list]).filter(Boolean).map((item) => item?.toElement?.() ?? item).filter((item) => item?.nodeType === 1);
|
|
256
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure option and event translations shared by the gx compatibility wrappers.
|
|
3
|
+
* Keeping these helpers DOM-free makes the migration contract directly testable in Node.
|
|
4
|
+
* @module gx-compat-options
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
8
|
+
export const SELECT_OPTION_MAP = Object.freeze({
|
|
9
|
+
data: 'items',
|
|
10
|
+
elementIndex: 'valueKey',
|
|
11
|
+
elementLabel: 'labelKey',
|
|
12
|
+
elementSelect: 'renderValue',
|
|
13
|
+
allowEmpty: 'clearable',
|
|
14
|
+
resetable: 'clearable',
|
|
15
|
+
searchfields: 'searchKeys',
|
|
16
|
+
height: 'listHeight'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
20
|
+
export const CHECKLIST_OPTION_MAP = Object.freeze({
|
|
21
|
+
data: 'items',
|
|
22
|
+
listValue: 'valueKey',
|
|
23
|
+
listFormat: 'labelKey',
|
|
24
|
+
listActive: 'checkedKey',
|
|
25
|
+
defaultState: 'defaultChecked'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
29
|
+
export const TABLE_OPTION_MAP = Object.freeze({
|
|
30
|
+
cols: 'columns'
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
34
|
+
export const FORM_OPTION_MAP = Object.freeze({
|
|
35
|
+
horizontal: 'layout',
|
|
36
|
+
default: 'value'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
40
|
+
export const FIELD_TYPE_MAP = Object.freeze({
|
|
41
|
+
string: 'text',
|
|
42
|
+
integer: 'int',
|
|
43
|
+
gxselect: 'zxselect',
|
|
44
|
+
date: 'date',
|
|
45
|
+
month: 'month',
|
|
46
|
+
time: 'time',
|
|
47
|
+
optionlist: 'optionlist',
|
|
48
|
+
html: 'html',
|
|
49
|
+
multivalueeditor: 'multivalueeditor',
|
|
50
|
+
checklist: 'checklist'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Renames known keys while retaining unrelated options.
|
|
55
|
+
* @param {Record<string, any>|null|undefined} source Legacy options.
|
|
56
|
+
* @param {Readonly<Record<string, string>>} mapping Rename table.
|
|
57
|
+
* @returns {Record<string, any>} Translated copy.
|
|
58
|
+
*/
|
|
59
|
+
export function renameOptions(source, mapping) {
|
|
60
|
+
const translated = {};
|
|
61
|
+
if (!source || typeof source !== 'object') return translated;
|
|
62
|
+
for (const [key, value] of Object.entries(source)) {
|
|
63
|
+
if (/^on[A-Z]/.test(key)) continue;
|
|
64
|
+
translated[mapping[key] ?? key] = value;
|
|
65
|
+
}
|
|
66
|
+
return translated;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Converts legacy Select options to their Zx equivalents.
|
|
71
|
+
* @param {Record<string, any>} [options={}] Legacy Select options.
|
|
72
|
+
* @returns {Record<string, any>} Zx Select options.
|
|
73
|
+
*/
|
|
74
|
+
export function translateSelectOptions(options = {}) {
|
|
75
|
+
const translated = renameOptions(options, SELECT_OPTION_MAP);
|
|
76
|
+
if (Object.hasOwn(options, 'data')) translated.items = Array.isArray(options.data) ? options.data.slice() : [];
|
|
77
|
+
if (Object.hasOwn(options, 'allowEmpty') || Object.hasOwn(options, 'resetable')) {
|
|
78
|
+
translated.clearable = Boolean(options.allowEmpty || options.resetable);
|
|
79
|
+
}
|
|
80
|
+
if (options.msg && typeof options.msg === 'object' && options.msg.noSelection != null) {
|
|
81
|
+
translated.placeholder = String(options.msg.noSelection);
|
|
82
|
+
}
|
|
83
|
+
if (Object.hasOwn(options, 'height')) translated.listHeight = numericSize(options.height, 280);
|
|
84
|
+
delete translated.elementDefault;
|
|
85
|
+
delete translated.parseDefault;
|
|
86
|
+
delete translated.queryParam;
|
|
87
|
+
delete translated.requestData;
|
|
88
|
+
delete translated.requestHeader;
|
|
89
|
+
delete translated.url;
|
|
90
|
+
delete translated.method;
|
|
91
|
+
delete translated.entity;
|
|
92
|
+
delete translated.limit;
|
|
93
|
+
return translated;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Converts legacy Checklist options to Zx Checklist options.
|
|
98
|
+
* @param {Record<string, any>} [options={}] Legacy Checklist options.
|
|
99
|
+
* @returns {Record<string, any>} Zx Checklist options.
|
|
100
|
+
*/
|
|
101
|
+
export function translateChecklistOptions(options = {}) {
|
|
102
|
+
const translated = renameOptions(options, CHECKLIST_OPTION_MAP);
|
|
103
|
+
if (typeof options.getItemValue === 'function') translated.valueKey = options.getItemValue;
|
|
104
|
+
if (Object.hasOwn(options, 'height')) translated.height = numericSize(options.height, 280);
|
|
105
|
+
delete translated.url;
|
|
106
|
+
delete translated.method;
|
|
107
|
+
delete translated.requestData;
|
|
108
|
+
delete translated.decodeResponse;
|
|
109
|
+
delete translated.width;
|
|
110
|
+
delete translated.onClick;
|
|
111
|
+
return translated;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Converts the legacy Datebox token array to the kernel format string.
|
|
116
|
+
* Existing percent-token format strings pass through unchanged.
|
|
117
|
+
* @param {unknown} format Legacy array or format string.
|
|
118
|
+
* @returns {string} Kernel date format.
|
|
119
|
+
*/
|
|
120
|
+
export function translateDateboxFormat(format) {
|
|
121
|
+
if (typeof format === 'string') return format.replaceAll(' ', ' ');
|
|
122
|
+
const parts = Array.isArray(format) ? format : ['d', '.', 'M', '.', 'y'];
|
|
123
|
+
const tokens = {
|
|
124
|
+
d: '%d', m: '%m', M: '%m', y: '%Y', h: '%H', i: '%M', s: '%S'
|
|
125
|
+
};
|
|
126
|
+
return parts.map((part) => tokens[part] ?? String(part).replaceAll(' ', ' ')).join('');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Resolves the legacy one-based `show` option to a tab name.
|
|
131
|
+
* @param {Array<{name?: unknown}>} frames Legacy frame list.
|
|
132
|
+
* @param {unknown} show Name or one-based numeric index.
|
|
133
|
+
* @returns {string|null} Resolved name.
|
|
134
|
+
*/
|
|
135
|
+
export function resolveTabName(frames, show) {
|
|
136
|
+
if (typeof show === 'string') return show;
|
|
137
|
+
if (typeof show !== 'number' || !Number.isFinite(show)) return null;
|
|
138
|
+
const frame = frames[Math.trunc(show) - 1];
|
|
139
|
+
return frame?.name == null ? null : String(frame.name);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Converts legacy Tabbox options without normalizing DOM content.
|
|
144
|
+
* @param {Record<string, any>} [options={}] Legacy Tabbox options.
|
|
145
|
+
* @returns {{tabs: Array<Record<string, any>>, active: string|null, height: unknown}}
|
|
146
|
+
*/
|
|
147
|
+
export function translateTabboxOptions(options = {}) {
|
|
148
|
+
const frames = Array.isArray(options.frames) ? options.frames : [];
|
|
149
|
+
return {
|
|
150
|
+
tabs: frames.map((frame) => ({
|
|
151
|
+
name: String(frame.name ?? ''),
|
|
152
|
+
title: String(frame.title ?? ''),
|
|
153
|
+
content: frame.content,
|
|
154
|
+
closable: Boolean(frame.closable),
|
|
155
|
+
disabled: Boolean(frame.disabled)
|
|
156
|
+
})),
|
|
157
|
+
active: resolveTabName(frames, options.show ?? 1),
|
|
158
|
+
height: options.height ?? null
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Converts a legacy table column list and its initial filter state.
|
|
164
|
+
* A cell adapter can turn legacy cell objects into DOM nodes in browser wrappers.
|
|
165
|
+
* @param {Record<string, any>} [options={}] Legacy Table options.
|
|
166
|
+
* @param {(cell: unknown) => unknown} [adaptCell=defaultCellAdapter] Cell adapter.
|
|
167
|
+
* @returns {Record<string, any>} Zx Table options.
|
|
168
|
+
*/
|
|
169
|
+
export function translateTableOptions(options = {}, adaptCell = defaultCellAdapter) {
|
|
170
|
+
const cols = Array.isArray(options.cols) ? options.cols : [];
|
|
171
|
+
const structure = typeof options.structure === 'function' ? options.structure : (row) => cols.map((col) => row?.[col.id]);
|
|
172
|
+
const cache = new WeakMap();
|
|
173
|
+
const getCells = (row, index) => {
|
|
174
|
+
if (row && typeof row === 'object') {
|
|
175
|
+
const cached = cache.get(row);
|
|
176
|
+
if (cached?.index === index) return cached.cells;
|
|
177
|
+
}
|
|
178
|
+
const result = structure(row, index);
|
|
179
|
+
const cells = Array.isArray(result) ? result : (Array.isArray(result?.row) ? result.row : []);
|
|
180
|
+
if (row && typeof row === 'object') cache.set(row, { index, cells });
|
|
181
|
+
return cells;
|
|
182
|
+
};
|
|
183
|
+
const columns = cols.map((column, columnIndex) => ({
|
|
184
|
+
id: String(column.id ?? columnIndex),
|
|
185
|
+
label: String(column.label ?? ''),
|
|
186
|
+
width: column.width ?? 'auto',
|
|
187
|
+
align: normalizeAlignment(column.align ?? column['text-align']),
|
|
188
|
+
sortable: column.filter != null || column.filterable !== false,
|
|
189
|
+
render: (row, rowIndex) => adaptCell(getCells(row, rowIndex)[columnIndex])
|
|
190
|
+
}));
|
|
191
|
+
const sorted = cols.find((column) => column.filter != null);
|
|
192
|
+
return {
|
|
193
|
+
columns,
|
|
194
|
+
data: Array.isArray(options.data) ? options.data.slice() : [],
|
|
195
|
+
sort: sorted ? { id: String(sorted.id), dir: sortDirection(sorted.mode ?? sorted.filter) } : null,
|
|
196
|
+
sortMode: 'server',
|
|
197
|
+
selectable: options.selectable === true ? 'single' : (['single', 'multi'].includes(options.selectable) ? options.selectable : false),
|
|
198
|
+
height: options.height ?? null,
|
|
199
|
+
stickyHeader: options.scroll !== false,
|
|
200
|
+
rowId: typeof options.rowId === 'function' || typeof options.rowId === 'string' ? options.rowId : legacyRowId
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Converts a legacy field descriptor to Zx Field options.
|
|
206
|
+
* Component-specific `props` are completed by the browser wrapper.
|
|
207
|
+
* @param {Record<string, any>} [options={}] Legacy field descriptor.
|
|
208
|
+
* @returns {Record<string, any>} Zx Field options.
|
|
209
|
+
*/
|
|
210
|
+
export function translateFieldOptions(options = {}) {
|
|
211
|
+
const type = FIELD_TYPE_MAP[String(options.type ?? 'text').toLowerCase()] ?? String(options.type ?? 'text').toLowerCase();
|
|
212
|
+
const translated = {
|
|
213
|
+
id: options.id ?? null,
|
|
214
|
+
type,
|
|
215
|
+
label: options.label ?? '',
|
|
216
|
+
description: options.description ?? '',
|
|
217
|
+
value: Object.hasOwn(options, 'value') ? options.value : options.default,
|
|
218
|
+
placeholder: options.placeholder ?? '',
|
|
219
|
+
required: Boolean(options.required),
|
|
220
|
+
disabled: Boolean(options.disabled),
|
|
221
|
+
options: options.options ?? null,
|
|
222
|
+
layout: options.horizontal === false ? 'stack' : (options.horizontal ? 'inline' : 'stack'),
|
|
223
|
+
props: {}
|
|
224
|
+
};
|
|
225
|
+
if (type === 'html') translated.value = options.content ?? translated.value;
|
|
226
|
+
return translated;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Positional legacy event arguments for the mappings exercised by wrappers.
|
|
231
|
+
* @type {Readonly<Record<string, (detail: Record<string, any>, wrapper: unknown, event?: Event) => unknown[]>>}
|
|
232
|
+
*/
|
|
233
|
+
export const LEGACY_EVENT_ARGS = Object.freeze({
|
|
234
|
+
select: (detail, wrapper) => [detail.item ?? null, wrapper],
|
|
235
|
+
noselect: (_detail, wrapper) => [null, wrapper],
|
|
236
|
+
tableClick: (detail) => [detail.row, detail.event?.target?.closest?.('tr') ?? null, detail.event],
|
|
237
|
+
tableFilter: (detail, wrapper) => [wrapper?._legacyColumn?.(detail.id) ?? { id: detail.id }, detail.dir],
|
|
238
|
+
tabChange: (detail) => [detail.name]
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
/** @param {unknown} value @param {number} fallback @returns {number} */
|
|
242
|
+
function numericSize(value, fallback) {
|
|
243
|
+
const number = typeof value === 'string' ? Number.parseFloat(value) : Number(value);
|
|
244
|
+
return Number.isFinite(number) ? Math.max(0, number) : fallback;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** @param {unknown} align @returns {'start'|'center'|'end'|'left'|'right'} */
|
|
248
|
+
function normalizeAlignment(align) {
|
|
249
|
+
const value = String(align ?? 'start');
|
|
250
|
+
return ['center', 'end', 'left', 'right'].includes(value) ? value : 'start';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** @param {unknown} direction @returns {'asc'|'desc'} */
|
|
254
|
+
function sortDirection(direction) {
|
|
255
|
+
return direction === 'desc' ? 'desc' : 'asc';
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** @param {unknown} cell @returns {unknown} */
|
|
259
|
+
function defaultCellAdapter(cell) {
|
|
260
|
+
if (cell && typeof cell === 'object' && !Array.isArray(cell) && Object.hasOwn(cell, 'label')) return cell.label;
|
|
261
|
+
return cell;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** @param {Record<string, any>} row @returns {unknown} */
|
|
265
|
+
function legacyRowId(row) {
|
|
266
|
+
return row?.ID ?? row?.id ?? row;
|
|
267
|
+
}
|