@zeyos/zx 3.0.0 → 4.1.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 +95 -0
- package/DESIGN-SYSTEM.md +87 -71
- package/README.md +16 -37
- package/dist/types/components/app-icon/app-icon.d.ts +88 -0
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +106 -32
- package/dist/types/components/card/card.d.ts +128 -0
- package/dist/types/components/chart/chart.d.ts +1 -0
- package/dist/types/components/filter/filter-model.d.ts +87 -0
- package/dist/types/components/filter/filter.d.ts +331 -0
- package/dist/types/components/launcher/launcher.d.ts +65 -6
- package/dist/types/components/select/select.d.ts +97 -4
- package/dist/types/components/table/table.d.ts +107 -3
- package/dist/types/components/tag-picker/tag-picker.d.ts +16 -0
- package/dist/types/core/dom.d.ts +9 -1
- package/dist/types/core/util.d.ts +9 -0
- package/dist/types/index.d.ts +6 -2
- package/dist/types/{components/app-rail → internal}/app-rail.d.ts +34 -19
- package/dist/types/zeyos/icons.d.ts +24 -2
- package/dist/types/zeyos/index.d.ts +3 -2
- package/dist/types/zeyos/launcher.d.ts +147 -0
- package/dist/types/zeyos/select.d.ts +41 -0
- package/dist/zx-zeyos.esm.js +2018 -113
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +815 -16
- package/dist/zx.esm.js +2661 -338
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +2661 -338
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +602 -110
- package/docs/llms.md +181 -123
- package/docs/llms.txt +24 -21
- package/package.json +8 -17
- package/src/components/app-icon/app-icon.css +105 -0
- package/src/components/app-icon/app-icon.js +134 -0
- package/src/components/app-sidebar/app-sidebar.css +12 -0
- package/src/components/app-sidebar/app-sidebar.js +310 -110
- package/src/components/card/card.css +149 -0
- package/src/components/card/card.js +285 -0
- package/src/components/chart/chart.js +8 -3
- package/src/components/filter/filter-model.js +226 -0
- package/src/components/filter/filter.css +147 -0
- package/src/components/filter/filter.js +554 -0
- package/src/components/grid/grid.css +1 -1
- package/src/components/grid/grid.js +14 -4
- package/src/components/launcher/launcher.css +113 -3
- package/src/components/launcher/launcher.js +234 -26
- package/src/components/message/message.css +36 -3
- package/src/components/select/field-adapter.js +9 -4
- package/src/components/select/select.css +161 -10
- package/src/components/select/select.js +361 -48
- package/src/components/table/table.css +85 -0
- package/src/components/table/table.js +426 -31
- package/src/components/tag-picker/tag-picker.css +19 -0
- package/src/components/tag-picker/tag-picker.js +42 -5
- package/src/core/dom.js +21 -1
- package/src/core/util.js +20 -0
- package/src/index.js +9 -2
- package/src/{components/app-rail → internal}/app-rail.js +80 -30
- package/src/zeyos/icons.js +38 -20
- package/src/zeyos/index.js +8 -2
- package/src/zeyos/launcher.js +338 -0
- package/src/zeyos/modules.js +1 -0
- package/src/zeyos/select.js +116 -1
- package/styles/tokens/global.css +1 -1
- package/styles/tokens/modules.css +1 -0
- package/styles/tokens/semantic.css +9 -0
- package/styles/tokens/themes.css +2 -2
- package/styles/zx.css +3 -0
- package/MIGRATION.md +0 -749
- package/dist/types/compat/base.d.ts +0 -156
- package/dist/types/compat/globals.d.ts +0 -20
- package/dist/types/compat/index.d.ts +0 -128
- package/dist/types/compat/map/basic.d.ts +0 -175
- package/dist/types/compat/map/data.d.ts +0 -103
- package/dist/types/compat/map/date-time.d.ts +0 -80
- package/dist/types/compat/map/factory.d.ts +0 -9
- package/dist/types/compat/map/form.d.ts +0 -98
- package/dist/types/compat/map/helpers.d.ts +0 -12
- package/dist/types/compat/map/http.d.ts +0 -36
- package/dist/types/compat/map/layout.d.ts +0 -106
- package/dist/types/compat/map/options.d.ts +0 -80
- package/dist/types/compat/map/select.d.ts +0 -95
- package/dist/types/compat/map/stubs.d.ts +0 -32
- package/dist/types/compat/map/utilities.d.ts +0 -37
- package/dist/types/compat-entry.d.ts +0 -5
- package/dist/zx-compat.esm.js +0 -17848
- package/dist/zx-compat.esm.min.js +0 -1
- package/dist/zx-compat.global.js +0 -29008
- package/dist/zx-compat.global.min.js +0 -3
- package/src/compat/base.js +0 -291
- package/src/compat/globals.js +0 -167
- package/src/compat/index.js +0 -84
- package/src/compat/map/basic.js +0 -464
- package/src/compat/map/data.js +0 -254
- package/src/compat/map/date-time.js +0 -177
- package/src/compat/map/factory.js +0 -45
- package/src/compat/map/form.js +0 -330
- package/src/compat/map/helpers.js +0 -46
- package/src/compat/map/http.js +0 -117
- package/src/compat/map/layout.js +0 -256
- package/src/compat/map/options.js +0 -267
- package/src/compat/map/select.js +0 -198
- package/src/compat/map/stubs.js +0 -26
- package/src/compat/map/utilities.js +0 -113
- package/src/compat-entry.js +0 -11
package/src/compat/map/basic.js
DELETED
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CheckButton as ZxCheckButton,
|
|
3
|
-
Dialog as ZxDialog,
|
|
4
|
-
MenuButton as ZxMenuButton,
|
|
5
|
-
Message as ZxMessage,
|
|
6
|
-
Toggle as ZxToggle
|
|
7
|
-
} from '../../index.js';
|
|
8
|
-
import { GxWrapper } from '../base.js';
|
|
9
|
-
import { legacyContent, messageKind, targetElement, textLabel, warnFunctionOnce, warnMethodOnce } from './helpers.js';
|
|
10
|
-
|
|
11
|
-
/** Legacy ZeyOS switch. */
|
|
12
|
-
export class Toggle extends GxWrapper {
|
|
13
|
-
static legacyName = 'gx.zeyos.Toggle';
|
|
14
|
-
|
|
15
|
-
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
16
|
-
constructor(display, options = {}) {
|
|
17
|
-
super(options, { on: false, value: true });
|
|
18
|
-
const { target, host } = buttonTarget(display);
|
|
19
|
-
const component = new ZxToggle(target, {
|
|
20
|
-
checked: Boolean(options.on), value: options.value ?? true,
|
|
21
|
-
label: options.label ?? null, disabled: Boolean(options.disabled)
|
|
22
|
-
});
|
|
23
|
-
if (host) host.append(component.toElement());
|
|
24
|
-
this._attach(component, {
|
|
25
|
-
events: {
|
|
26
|
-
check: { type: 'change', filter: (detail) => detail.checked, args: () => [this] },
|
|
27
|
-
uncheck: { type: 'change', filter: (detail) => !detail.checked, args: () => [this] },
|
|
28
|
-
change: { type: 'change', args: (detail) => [detail.checked] }
|
|
29
|
-
},
|
|
30
|
-
setters: { on: (value) => value ? this.setChecked() : this.setUnchecked(), value: (value) => { component.options.value = value; } }
|
|
31
|
-
});
|
|
32
|
-
component.on('change', () => this._syncAct());
|
|
33
|
-
this._syncAct();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** @returns {boolean} */
|
|
37
|
-
getState() { return this._zx.get(); }
|
|
38
|
-
/** @returns {unknown} */
|
|
39
|
-
getValue() { return this._zx.getValue(); }
|
|
40
|
-
/** @returns {this} */
|
|
41
|
-
toggle() { this._zx.toggle(); this._syncAct(); return this; }
|
|
42
|
-
/** @param {boolean} [suppress=false] @returns {this} */
|
|
43
|
-
setChecked(suppress = false) { this._zx.set(true, { silent: Boolean(suppress) }); this._syncAct(); return this; }
|
|
44
|
-
/** @param {boolean} [suppress=false] @returns {this} */
|
|
45
|
-
setUnchecked(suppress = false) { this._zx.set(false, { silent: Boolean(suppress) }); this._syncAct(); return this; }
|
|
46
|
-
/** @returns {void} */
|
|
47
|
-
_syncAct() { this._mirrorAct(this.toElement(), this.getState()); }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** Legacy ZeyOS floating message box. */
|
|
51
|
-
export class Msgbox extends GxWrapper {
|
|
52
|
-
static legacyName = 'gx.zeyos.Msgbox';
|
|
53
|
-
|
|
54
|
-
/** @param {Record<string, any>} [options={}] */
|
|
55
|
-
constructor(options = {}) {
|
|
56
|
-
super(options, { closable: true, content: false });
|
|
57
|
-
const component = new ZxMessage(null, { timeout: 0, closable: options.closable !== false, maxVisible: 1 });
|
|
58
|
-
document.body.append(component.toElement());
|
|
59
|
-
this._handle = null;
|
|
60
|
-
this._content = options.content || '';
|
|
61
|
-
this._attach(component, { ui: { frame: 'root', content: 'root', img: 'root' } });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** @param {unknown} content @returns {this} */
|
|
65
|
-
setContent(content) { this._content = legacyContent(content); return this; }
|
|
66
|
-
/** @param {unknown} [message] @param {string} [className='info'] @returns {this} */
|
|
67
|
-
show(message, className = 'info') {
|
|
68
|
-
if (message != null) this.setContent(message);
|
|
69
|
-
this._handle?.close();
|
|
70
|
-
this._handle = this._zx.show(this._content, { kind: messageKind(className), timeout: 0, closable: this.options.closable !== false });
|
|
71
|
-
this._mirrorAct(this.toElement(), true);
|
|
72
|
-
return this;
|
|
73
|
-
}
|
|
74
|
-
/** @returns {this} */
|
|
75
|
-
hide() { this._handle?.close(); this._handle = null; this._mirrorAct(this.toElement(), false); return this; }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Legacy bootstrap message/status service. */
|
|
79
|
-
export class BootstrapMessage extends GxWrapper {
|
|
80
|
-
static legacyName = 'gx.bootstrap.Message';
|
|
81
|
-
|
|
82
|
-
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
83
|
-
constructor(display, options = {}) {
|
|
84
|
-
super(options, { duration: 3000 });
|
|
85
|
-
const component = new ZxMessage(targetElement(display), {
|
|
86
|
-
timeout: Number(options.duration) || 0, closable: true, maxVisible: options.maxVisible ?? 5
|
|
87
|
-
});
|
|
88
|
-
if (!targetElement(display)) document.body.append(component.toElement());
|
|
89
|
-
this._handles = new Map();
|
|
90
|
-
this._progress = null;
|
|
91
|
-
this._progressValue = 0;
|
|
92
|
-
this._attach(component, { ui: { windows: 'root', status: 'root' } });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** @param {unknown} message @param {string} [iconClass='info'] @param {boolean} [closable=true] @param {boolean} [_blend=false] @param {boolean} [autoclose=true] @returns {Element} */
|
|
96
|
-
addMessage(message, iconClass = 'info', closable = true, _blend = false, autoclose = true) {
|
|
97
|
-
const marker = document.createElement('span');
|
|
98
|
-
marker.hidden = true;
|
|
99
|
-
const handle = this._zx.show(legacyContent(message), {
|
|
100
|
-
kind: messageKind(iconClass), closable: closable !== false,
|
|
101
|
-
timeout: autoclose === false ? 0 : Number(this.options.duration) || 0
|
|
102
|
-
});
|
|
103
|
-
this._handles.set(marker, handle);
|
|
104
|
-
return marker;
|
|
105
|
-
}
|
|
106
|
-
/** @param {Element} marker @returns {this} */
|
|
107
|
-
closeMessage(marker) { this._handles.get(marker)?.close(); this._handles.delete(marker); return this; }
|
|
108
|
-
/** @returns {this} */
|
|
109
|
-
clear() { for (const handle of this._handles.values()) handle.close(); this._handles.clear(); return this; }
|
|
110
|
-
/** @param {number} progress @param {string} [message=''] @param {boolean} [_blend=false] @returns {this} */
|
|
111
|
-
showStatus(progress, message = '', _blend = false) {
|
|
112
|
-
if (!this._progress) this._progress = ZxMessage.progress(String(message));
|
|
113
|
-
this._progressValue = Number(progress) || 0;
|
|
114
|
-
this._progress.update(this._progressValue, String(message));
|
|
115
|
-
return this;
|
|
116
|
-
}
|
|
117
|
-
/** @param {number} progress @param {string} [message] @returns {this} */
|
|
118
|
-
incProgress(progress, message) { return this.setProgress(this._progressValue + (Number(progress) || 0), message); }
|
|
119
|
-
/** @param {number} progress @param {string} [message] @param {unknown} [_tween] @returns {this} */
|
|
120
|
-
setProgress(progress, message, _tween) {
|
|
121
|
-
if (!this._progress) this._progress = ZxMessage.progress(String(message ?? ''));
|
|
122
|
-
this._progressValue = Number(progress) || 0;
|
|
123
|
-
this._progress.update(this._progressValue, message == null ? undefined : String(message));
|
|
124
|
-
return this;
|
|
125
|
-
}
|
|
126
|
-
/** @returns {this} */
|
|
127
|
-
hideStatus() { this._progress?.done(); this._progress = null; this._progressValue = 0; return this; }
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Shared Dialog-backed popup behavior. */
|
|
131
|
-
class PopupBase extends GxWrapper {
|
|
132
|
-
/** @param {Record<string, any>} options */
|
|
133
|
-
constructor(options = {}) {
|
|
134
|
-
super(options, { width: 600, closable: true, content: null });
|
|
135
|
-
const component = new ZxDialog(null, {
|
|
136
|
-
title: String(options.title ?? ''), size: numericWidth(options.width),
|
|
137
|
-
closable: options.closable !== false,
|
|
138
|
-
lightDismiss: Boolean(options.overlayDismiss ?? options.clickable),
|
|
139
|
-
content: legacyContent(options.content)
|
|
140
|
-
});
|
|
141
|
-
this._attach(component, {
|
|
142
|
-
events: {
|
|
143
|
-
show: { type: 'open', args: () => [this] },
|
|
144
|
-
hide: { type: 'close', args: (detail) => [detail.result, this] },
|
|
145
|
-
open: { type: 'open', args: () => [this] }
|
|
146
|
-
},
|
|
147
|
-
ui: { modal: 'root', aside: 'content', body: 'content', content: 'content', title: 'title', footer: 'footer', cross: 'close' },
|
|
148
|
-
setters: { content: 'setContent', title: 'setTitle', open: (value) => value ? this.show() : this.hide() }
|
|
149
|
-
});
|
|
150
|
-
this.isOpen = false;
|
|
151
|
-
if (options.footer) component.setButtons(footerButtons(options.footer));
|
|
152
|
-
if (options.open) this.show();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** @param {unknown} [argument] @returns {this} */
|
|
156
|
-
show(argument) { this.isOpen = true; this._showArgument = argument; this._zx.open(); return this; }
|
|
157
|
-
/** @param {unknown} [argument] @returns {this} */
|
|
158
|
-
hide(argument) { this.isOpen = false; this._zx.close(argument); return this; }
|
|
159
|
-
/** @param {unknown} content @returns {this} */
|
|
160
|
-
setContent(content) { this._zx.setContent(legacyContent(content)); return this; }
|
|
161
|
-
/** @param {string} title @returns {this} */
|
|
162
|
-
setTitle(title) { this._zx.setTitle(title); return this; }
|
|
163
|
-
/** @returns {Element} */
|
|
164
|
-
getContent() { return this._zx.refs.content; }
|
|
165
|
-
/** @param {unknown} [_x] @param {unknown} [_y] @returns {this} */
|
|
166
|
-
setPosition(_x, _y) { warnMethodOnce(this.constructor, 'setPosition', 'CSS dialog positioning'); return this; }
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/** Legacy ZeyOS popup. */
|
|
170
|
-
export class Popup extends PopupBase {
|
|
171
|
-
static legacyName = 'gx.zeyos.Popup';
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** Legacy bootstrap popup. */
|
|
175
|
-
export class BootstrapPopup extends PopupBase {
|
|
176
|
-
static legacyName = 'gx.bootstrap.Popup';
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Sentinel returned when a legacy confirmation is canceled. */
|
|
180
|
-
export const PopupConfirmCanceled = Object.freeze({});
|
|
181
|
-
|
|
182
|
-
/** @param {string} title @param {unknown} message @param {Record<string, any>|string} [options={}] @returns {Promise<void>} */
|
|
183
|
-
export function PopupAlert(title, message, options = {}) {
|
|
184
|
-
warnFunctionOnce(PopupAlert, 'gx.bootstrap.PopupAlert', 'Dialog.alert');
|
|
185
|
-
const settings = typeof options === 'string' ? { type: options } : options;
|
|
186
|
-
return new Promise((resolve) => {
|
|
187
|
-
const popup = new BootstrapPopup({ ...settings, title, content: message, width: settings.width ?? 400 });
|
|
188
|
-
popup._zx.setButtons([{ label: settings.okLabel ?? 'Ok', kind: 'primary', autofocus: true, action: () => {
|
|
189
|
-
if (typeof settings.onOk === 'function' && settings.onOk() === false) return;
|
|
190
|
-
popup.hide(); resolve();
|
|
191
|
-
} }]);
|
|
192
|
-
popup._zx.once('close', () => popup.destroy());
|
|
193
|
-
popup.show();
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** @param {string} title @param {unknown} message @param {Record<string, any>|string} [options={}] @returns {Promise<void|typeof PopupConfirmCanceled>} */
|
|
198
|
-
export function PopupConfirm(title, message, options = {}) {
|
|
199
|
-
warnFunctionOnce(PopupConfirm, 'gx.bootstrap.PopupConfirm', 'Dialog.confirm');
|
|
200
|
-
const settings = typeof options === 'string' ? { type: options } : options;
|
|
201
|
-
return new Promise((resolve) => {
|
|
202
|
-
const popup = new BootstrapPopup({ ...settings, title, content: message, width: settings.width ?? 400, closable: false });
|
|
203
|
-
popup._zx.setButtons([
|
|
204
|
-
{ label: settings.cancelLabel ?? 'Cancel', action: () => { popup.hide(); resolve(PopupConfirmCanceled); } },
|
|
205
|
-
{ label: settings.okLabel ?? 'Ok', kind: 'primary', action: () => {
|
|
206
|
-
if (typeof settings.onOk === 'function' && settings.onOk() === false) return;
|
|
207
|
-
popup.hide(); resolve();
|
|
208
|
-
} }
|
|
209
|
-
]);
|
|
210
|
-
popup._zx.once('close', () => popup.destroy());
|
|
211
|
-
popup.show();
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/** Legacy multi-frame ZeyOS dialog. */
|
|
216
|
-
export class Dialog extends GxWrapper {
|
|
217
|
-
static legacyName = 'gx.zeyos.Dialog';
|
|
218
|
-
|
|
219
|
-
/** @param {Element|string|null} _display @param {Record<string, any>} [options={}] */
|
|
220
|
-
constructor(_display, options = {}) {
|
|
221
|
-
super(options, { title: '', height: 400 });
|
|
222
|
-
const component = new ZxDialog(null, { title: String(options.title ?? ''), content: null });
|
|
223
|
-
this._frames = {};
|
|
224
|
-
this._current = null;
|
|
225
|
-
this._attach(component, { ui: { title: 'title', content: 'content', footer: 'footer' }, setters: { title: 'setTitle' } });
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** @param {string} title @returns {this} */
|
|
229
|
-
setTitle(title) { this._zx.setTitle(textLabel(title)); return this; }
|
|
230
|
-
/** @param {string} key @param {Record<string, any>} options @param {boolean} [open] @returns {this} */
|
|
231
|
-
addFrame(key, options, open) {
|
|
232
|
-
const buttons = footerButtons(options?.footer);
|
|
233
|
-
const view = this._zx.addView(String(key), {
|
|
234
|
-
title: options?.title == null ? undefined : textLabel(options.title),
|
|
235
|
-
content: legacyContent(options?.content), buttons
|
|
236
|
-
});
|
|
237
|
-
this._frames[key] = { title: options?.title ?? null, content: view.content, footer: buttons, view };
|
|
238
|
-
if ((!this._current && open !== false) || open === true) this.openFrame(key);
|
|
239
|
-
return this;
|
|
240
|
-
}
|
|
241
|
-
/** @param {string} key @returns {Record<string, any>} */
|
|
242
|
-
openFrame(key) { this._zx.showView(String(key)); this._current = this._frames[key]; return this._current; }
|
|
243
|
-
/** @param {string} key @returns {Record<string, any>|null} */
|
|
244
|
-
getFrame(key) { return this._frames[key] ?? null; }
|
|
245
|
-
/** @param {string} key @param {unknown} content @param {Function} onSubmit @param {boolean} [open] @returns {unknown} */
|
|
246
|
-
addSubmitFrame(key, content, onSubmit, open) {
|
|
247
|
-
this.addFrame(key, { title: this.options.title, content: containerFor(content), footer: {
|
|
248
|
-
close: { label: 'Close', click: () => this._zx.close() },
|
|
249
|
-
ok: { label: 'OK', primary: true, click: () => onSubmit?.() }
|
|
250
|
-
} }, open);
|
|
251
|
-
return content;
|
|
252
|
-
}
|
|
253
|
-
/** @param {string} key @param {Record<string, [unknown, unknown]>} form @param {Function} onSubmit @param {boolean} [open] @returns {Record<string, unknown>} */
|
|
254
|
-
addFormFrame(key, form, onSubmit, open) {
|
|
255
|
-
const fields = {};
|
|
256
|
-
const container = document.createElement('div');
|
|
257
|
-
for (const [name, definition] of Object.entries(form ?? {})) {
|
|
258
|
-
const label = document.createElement('p');
|
|
259
|
-
label.textContent = definition?.[0] == null ? '' : String(definition[0]);
|
|
260
|
-
container.append(label);
|
|
261
|
-
const field = definition?.[1];
|
|
262
|
-
const node = legacyContent(field);
|
|
263
|
-
if (node?.nodeType) container.append(node); else if (node?.toElement?.()) container.append(node.toElement());
|
|
264
|
-
fields[name] = field;
|
|
265
|
-
}
|
|
266
|
-
this.addSubmitFrame(key, container, onSubmit, open);
|
|
267
|
-
return fields;
|
|
268
|
-
}
|
|
269
|
-
/** @param {string} key @param {unknown} message @param {string} [link] @param {boolean} [open] @returns {this} */
|
|
270
|
-
addSuccessFrame(key, message, link, open) {
|
|
271
|
-
const container = containerFor(message);
|
|
272
|
-
if (link) {
|
|
273
|
-
const anchor = document.createElement('a'); anchor.href = link; anchor.textContent = 'Open'; container.append(anchor);
|
|
274
|
-
}
|
|
275
|
-
return this.addFrame(key, { title: this.options.title, content: container }, open);
|
|
276
|
-
}
|
|
277
|
-
/** @param {Record<string, any>} form @returns {Record<string, unknown>} */
|
|
278
|
-
getFormValues(form) {
|
|
279
|
-
const values = {};
|
|
280
|
-
for (const [key, field] of Object.entries(form ?? {})) {
|
|
281
|
-
if (field?.value != null) values[key] = field.value;
|
|
282
|
-
else if (typeof field?.getValue === 'function') values[key] = field.getValue();
|
|
283
|
-
else if (typeof field?.getValues === 'function') values[key] = field.getValues();
|
|
284
|
-
else if (typeof field?.getId === 'function') values[key] = field.getId();
|
|
285
|
-
else if (typeof field?.get === 'function') values[key] = field.get();
|
|
286
|
-
}
|
|
287
|
-
return values;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/** Legacy object-backed dropdown. */
|
|
292
|
-
export class Dropdown extends GxWrapper {
|
|
293
|
-
static legacyName = 'gx.zeyos.Dropdown';
|
|
294
|
-
|
|
295
|
-
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
296
|
-
constructor(display, options = {}) {
|
|
297
|
-
super(options, { items: {}, label: '', resettable: false, compact: false, upside: false });
|
|
298
|
-
const { target, host } = buttonTarget(display);
|
|
299
|
-
this._items = normalizeDropdownItems(options.items, options.resettable, options.emptyCaption);
|
|
300
|
-
this._selected = null;
|
|
301
|
-
const component = new ZxMenuButton(target, {
|
|
302
|
-
label: String(options.label ?? ''), items: this._items,
|
|
303
|
-
placement: options.upside ? 'top-start' : 'bottom-start'
|
|
304
|
-
});
|
|
305
|
-
if (host) host.append(component.toElement());
|
|
306
|
-
this._attach(component, {
|
|
307
|
-
events: {
|
|
308
|
-
change: { type: 'select', args: (detail) => {
|
|
309
|
-
this._selected = detail.value == null ? null : detail.item;
|
|
310
|
-
component.setLabel(detail.value == null ? String(options.label ?? '') : String(detail.item.label));
|
|
311
|
-
return [detail.value, detail.item.label, this];
|
|
312
|
-
} }
|
|
313
|
-
},
|
|
314
|
-
ui: { frame: 'root', button: 'root', section: () => document.querySelector(`[aria-labelledby="${component.el.id}"]`) },
|
|
315
|
-
setters: { items: 'setItems' }
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
/** @param {Record<string, unknown>} items @returns {this} */
|
|
319
|
-
setItems(items) { this._items = normalizeDropdownItems(items, this.options.resettable, this.options.emptyCaption); this._zx.setItems(this._items); return this; }
|
|
320
|
-
/** @param {unknown} value @param {string} [text] @returns {this} */
|
|
321
|
-
selectItem(value, text) {
|
|
322
|
-
const item = this._items.find((entry) => entry !== '-' && entry.value == value);
|
|
323
|
-
this._selected = item ?? { value, label: text ?? String(value) };
|
|
324
|
-
this._zx.setLabel(text ?? this._selected.label); this.fireEvent('change', [value, text ?? this._selected.label, this]); this._zx.close(); return this;
|
|
325
|
-
}
|
|
326
|
-
/** @returns {this} */
|
|
327
|
-
reset() { this._selected = null; this._zx.setLabel(String(this.options.label ?? '')); this.fireEvent('change', [null, this.options.emptyCaption, this]); this._zx.close(); return this; }
|
|
328
|
-
/** @returns {{value: unknown, label: string}|null} */
|
|
329
|
-
getSelected() { return this._selected ? { value: this._selected.value, label: this._selected.label } : null; }
|
|
330
|
-
/** @returns {unknown} */
|
|
331
|
-
getValue() { return this._selected?.value ?? ''; }
|
|
332
|
-
/** @returns {this} */
|
|
333
|
-
show() { this._zx.open(); return this; }
|
|
334
|
-
/** @returns {this} */
|
|
335
|
-
close() { this._zx.close(); return this; }
|
|
336
|
-
/** @returns {this} */
|
|
337
|
-
toggle() { this._zx.isOpen() ? this._zx.close() : this._zx.open(); return this; }
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/** Legacy bootstrap menu button. */
|
|
341
|
-
export class MenuButton extends GxWrapper {
|
|
342
|
-
static legacyName = 'gx.bootstrap.MenuButton';
|
|
343
|
-
|
|
344
|
-
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
345
|
-
constructor(display, options = {}) {
|
|
346
|
-
super(options, { entries: [], label: '', orientation: 'left', direction: 'down' });
|
|
347
|
-
const { target, host } = buttonTarget(display);
|
|
348
|
-
this._entries = [];
|
|
349
|
-
const component = new ZxMenuButton(target, {
|
|
350
|
-
label: String(options.label ?? ''), items: [], kind: styleKind(options.style),
|
|
351
|
-
placement: `${options.direction === 'up' ? 'top' : 'bottom'}-${options.orientation === 'right' ? 'end' : 'start'}`
|
|
352
|
-
});
|
|
353
|
-
if (host) host.append(component.toElement());
|
|
354
|
-
this._attach(component, { events: { change: { type: 'select', args: (detail) => [detail.value, detail.item, this] } }, ui: { button: 'root', frame: 'root', menu: 'root' } });
|
|
355
|
-
for (const entry of options.entries ?? []) this.add(entry);
|
|
356
|
-
}
|
|
357
|
-
/** @param {string|false|null} label @param {string} [icon] @returns {Element|null} */
|
|
358
|
-
add(label, icon) {
|
|
359
|
-
if (!label) { this._entries.push('-'); this._zx.setItems(this._entries); return null; }
|
|
360
|
-
const item = { label: String(label), icon, value: this._entries.length };
|
|
361
|
-
this._entries.push(item); this._zx.setItems(this._entries);
|
|
362
|
-
return this.toElement();
|
|
363
|
-
}
|
|
364
|
-
/** @returns {this} */
|
|
365
|
-
divider() { this.add(false); return this; }
|
|
366
|
-
/** @returns {this} */
|
|
367
|
-
toggle() { this._zx.isOpen() ? this._zx.close() : this._zx.open(); return this; }
|
|
368
|
-
/** @returns {this} */
|
|
369
|
-
open() { this._zx.open(); return this; }
|
|
370
|
-
/** @returns {this} */
|
|
371
|
-
close() { this._zx.close(); return this; }
|
|
372
|
-
/** @param {string} label @returns {this} */
|
|
373
|
-
setLabel(label) { this._zx.setLabel(label); return this; }
|
|
374
|
-
/** @param {string} style @returns {this} */
|
|
375
|
-
setStyle(style) { this.toElement().setAttribute('data-kind', styleKind(style)); return this; }
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/** Legacy bootstrap two-state check button. */
|
|
379
|
-
export class CheckButton extends GxWrapper {
|
|
380
|
-
static legacyName = 'gx.bootstrap.CheckButton';
|
|
381
|
-
|
|
382
|
-
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
383
|
-
constructor(display, options = {}) {
|
|
384
|
-
super(options, { label: '', value: false });
|
|
385
|
-
const { target, host } = buttonTarget(display);
|
|
386
|
-
const component = new ZxCheckButton(target, { label: options.label, checked: Boolean(options.value), disabled: Boolean(options.disabled) });
|
|
387
|
-
if (host) host.append(component.toElement());
|
|
388
|
-
this._attach(component, {
|
|
389
|
-
events: {
|
|
390
|
-
change: { type: 'change', args: (detail) => [detail.checked] },
|
|
391
|
-
check: { type: 'change', filter: (detail) => detail.checked, args: () => [] },
|
|
392
|
-
uncheck: { type: 'change', filter: (detail) => !detail.checked, args: () => [] }
|
|
393
|
-
},
|
|
394
|
-
ui: { button: 'root', indicator: 'root', group: 'root' },
|
|
395
|
-
setters: { value: 'set', disabled: 'setDisabled', label: 'setLabel' }
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
/** @returns {boolean} */ get() { return this._zx.get(); }
|
|
399
|
-
/** @param {boolean} [suppress=false] @returns {false} */ toggle(suppress = false) { this._zx.set(!this.get(), { silent: Boolean(suppress) }); return false; }
|
|
400
|
-
/** @param {boolean} [suppress=false] @returns {this} */ check(suppress = false) { this._zx.set(true, { silent: Boolean(suppress) }); return this; }
|
|
401
|
-
/** @param {boolean} [suppress=false] @returns {this} */ uncheck(suppress = false) { this._zx.set(false, { silent: Boolean(suppress) }); return this; }
|
|
402
|
-
/** @param {boolean} value @returns {this} */ set(value) { return value ? this.check() : this.uncheck(); }
|
|
403
|
-
/** @param {boolean} disabled @returns {this} */ setDisabled(disabled) { disabled ? this._zx.disable() : this._zx.enable(); return this; }
|
|
404
|
-
/** @param {string|string[]} label @returns {this} */ setLabel(label) { this._zx.setLabel(label); return this; }
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/** @param {Element|string|null|undefined} display @returns {{target: HTMLButtonElement|null, host: Element|null}} */
|
|
408
|
-
function buttonTarget(display) {
|
|
409
|
-
const element = targetElement(display);
|
|
410
|
-
if (element?.localName === 'button') return { target: element, host: null };
|
|
411
|
-
return { target: null, host: element };
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/** @param {unknown} width @returns {'sm'|'md'|'lg'|number} */
|
|
415
|
-
function numericWidth(width) {
|
|
416
|
-
if (typeof width === 'number' && Number.isFinite(width)) return width;
|
|
417
|
-
const number = Number.parseFloat(String(width ?? ''));
|
|
418
|
-
return Number.isFinite(number) ? number : 'md';
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/** @param {unknown} footer @returns {Array<Record<string, any>>} */
|
|
422
|
-
function footerButtons(footer) {
|
|
423
|
-
if (!footer) return [];
|
|
424
|
-
const entries = Array.isArray(footer) ? footer : (footer?.nodeType ? [footer] : Object.values(footer));
|
|
425
|
-
return entries.map((entry) => {
|
|
426
|
-
if (entry?.nodeType) return { label: entry.textContent ?? '', action: () => entry.click?.() };
|
|
427
|
-
return { label: String(entry?.label ?? ''), kind: entry?.primary ? 'primary' : 'default', action: () => entry?.click?.() };
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/** @param {unknown} content @returns {HTMLElement} */
|
|
432
|
-
function containerFor(content) {
|
|
433
|
-
const container = document.createElement('div');
|
|
434
|
-
const values = Array.isArray(content) ? content : [content];
|
|
435
|
-
for (const value of values) {
|
|
436
|
-
const node = legacyContent(value);
|
|
437
|
-
if (node?.nodeType) container.append(node);
|
|
438
|
-
else if (node != null) container.append(document.createTextNode(String(node)));
|
|
439
|
-
}
|
|
440
|
-
return container;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/** @param {Record<string, unknown>} items @param {boolean} resettable @param {unknown} emptyCaption @returns {Array<Record<string, any>>} */
|
|
444
|
-
function normalizeDropdownItems(items = {}, resettable = false, emptyCaption = null) {
|
|
445
|
-
const list = [];
|
|
446
|
-
if (resettable) list.push({ label: String(emptyCaption ?? 'Empty'), value: null });
|
|
447
|
-
for (const [value, source] of Object.entries(items ?? {})) {
|
|
448
|
-
const object = source && typeof source === 'object' ? source : null;
|
|
449
|
-
list.push({
|
|
450
|
-
label: String(object?.text ?? object?.label ?? source), value,
|
|
451
|
-
onselect: typeof object?.onClick === 'function' ? object.onClick : undefined
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
return list;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/** @param {unknown} style @returns {'default'|'primary'|'danger'|'ghost'} */
|
|
458
|
-
function styleKind(style) {
|
|
459
|
-
const value = String(style ?? '').toLowerCase();
|
|
460
|
-
if (value.includes('danger') || value.includes('error')) return 'danger';
|
|
461
|
-
if (value.includes('primary') || value.includes('success')) return 'primary';
|
|
462
|
-
if (value.includes('link') || value.includes('ghost')) return 'ghost';
|
|
463
|
-
return 'default';
|
|
464
|
-
}
|