@zeyos/zx 2.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 +74 -0
- package/LICENSE +21 -0
- package/MIGRATION.md +598 -0
- package/README.md +288 -0
- package/dist/zx-compat.esm.js +16880 -0
- package/dist/zx-compat.esm.min.js +1 -0
- package/dist/zx-compat.global.js +23068 -0
- package/dist/zx-compat.global.min.js +3 -0
- package/dist/zx-zeyos.esm.js +11581 -0
- package/dist/zx-zeyos.esm.min.js +1 -0
- package/dist/zx.css +4946 -0
- package/dist/zx.esm.js +19934 -0
- package/dist/zx.esm.min.js +3 -0
- package/dist/zx.global.js +19958 -0
- package/dist/zx.global.min.js +3 -0
- package/dist/zx.min.css +1 -0
- package/docs/api.json +5248 -0
- package/docs/llms.md +1315 -0
- package/docs/llms.txt +45 -0
- package/package.json +74 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to `@zeyos/zx`. The format follows [Keep a Changelog](https://keepachangelog.com),
|
|
4
|
+
and the project follows [semantic versioning](https://semver.org).
|
|
5
|
+
|
|
6
|
+
Releases before this file existed are summarised from the git history; `git log v2.0.1..v2.0.2`
|
|
7
|
+
and friends remain the complete record.
|
|
8
|
+
|
|
9
|
+
## Unreleased
|
|
10
|
+
|
|
11
|
+
## 2.1.0 — 2026-08-19
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`spinner()`, `ProgressBar`, `InlineLoading`** — three shapes of "wait". A ring for an unknown
|
|
16
|
+
duration, a determinate track for a known share, and a status line that resolves in place
|
|
17
|
+
("Saving…" becoming "Saved"). Previously the only loading affordance was `Table.setLoading()`,
|
|
18
|
+
which belongs to the table and cannot be used anywhere else.
|
|
19
|
+
- **`skeleton()`, `skeletonText()`, `skeletonTable()`** — placeholders shaped like the content that
|
|
20
|
+
is coming, so the layout does not jump when it arrives. All `aria-hidden`; put `aria-busy="true"`
|
|
21
|
+
on the region being filled.
|
|
22
|
+
- **`stack()`, `grid()`, `aspect()`** and the `.zx-stack` / `.zx-grid` / `.zx-aspect` classes —
|
|
23
|
+
the spacing and grid primitives under `Panel` and `SplitView`. `grid()` reflows on its own
|
|
24
|
+
container width rather than the viewport, so it behaves identically inside a split pane or a
|
|
25
|
+
modal.
|
|
26
|
+
- **`breakpoints`, `breakpointOf()`, `matchBreakpoint()`, `onBreakpoint()`** — named width bands
|
|
27
|
+
for the decisions only script can make. `onBreakpoint()` observes an element as readily as the
|
|
28
|
+
window.
|
|
29
|
+
- **`Slider`** and the `slider` field type — a bounded numeric value set by dragging, on a native
|
|
30
|
+
range input, with optional marks, bounds, and a number box. `stepPrecision()` is exported
|
|
31
|
+
alongside it.
|
|
32
|
+
- **`ContextMenu`** — right-click menu for a region or, through `selector`, per row from a single
|
|
33
|
+
instance. Reachable from the keyboard with the Menu key and Shift+F10.
|
|
34
|
+
- **`copyButton()` and `CopyInput`** — copying a value, and confirming it; a refused clipboard
|
|
35
|
+
write reports `false` rather than claiming success.
|
|
36
|
+
- **`truncate()` and `isTruncated()`**, plus the `.zx-truncate` class — line clamping that exposes
|
|
37
|
+
the full value as a `title` only while the text is actually cut off.
|
|
38
|
+
- `copy` added to the built-in icon set.
|
|
39
|
+
- `CHANGELOG.md`, included in the published package.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- The landing page routes by intent — start something new, see what is there, or move an old
|
|
44
|
+
screen across — states how to install the package, lists the entry points, and renders the
|
|
45
|
+
newest changelog entry so a release updates it too. The footer, shared by every page, carries
|
|
46
|
+
grouped links plus the version and the build date.
|
|
47
|
+
|
|
48
|
+
## 2.0.2 — 2026-08-19
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- The base stylesheet now replaces the browser's own focus outline instead of stacking on it, so a
|
|
53
|
+
focused control no longer shows a blue border inside the accent ring.
|
|
54
|
+
- Tabbox variants match the approved draft, and the tab clears the inherited control radius.
|
|
55
|
+
- Every deploy is served from a revision-stamped path, and the imports the markup cannot see are
|
|
56
|
+
fingerprinted with it — working around a CDN that rewrites cache headers.
|
|
57
|
+
|
|
58
|
+
## 2.0.1 — 2026-08-19
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
|
|
62
|
+
- Tabbox gained four square-cornered variants (`divided`, `bracket`, `line`, `segmented`) with
|
|
63
|
+
`--zx-tabbox-radius` as an escape hatch. **The default moved from `line` to `divided`**, so a
|
|
64
|
+
Tabbox with no explicit `variant` changes appearance.
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- The documentation is one scrolling page per component, with the source folded under each example.
|
|
69
|
+
|
|
70
|
+
## 2.0.0 — 2026-08-18
|
|
71
|
+
|
|
72
|
+
First stable release: the dependency-free, vanilla-JavaScript successor to the MooTools-era `gx`
|
|
73
|
+
library. Components, design tokens with light/dark and cozy/compact theming, the `zx-zeyos`
|
|
74
|
+
schema-driven binding, and an opt-in `gx` compatibility layer.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZeyOS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
# Migrating from `gx` to Zx
|
|
2
|
+
|
|
3
|
+
Zx replaces the MooTools-era `gx` UI libraries with dependency-free ES2022 modules. The
|
|
4
|
+
compatibility bundle lets mapped legacy code keep running while classes are migrated one at a
|
|
5
|
+
time. Compatibility constructors warn once per legacy class so remaining call sites are visible.
|
|
6
|
+
|
|
7
|
+
## Deployment script swap
|
|
8
|
+
|
|
9
|
+
For deployments that serve the old libraries directly from
|
|
10
|
+
`net.zeyon.lib.gx-3000/assets/`, copy `dist/zx.global.js`, `dist/zx-compat.global.js`, and
|
|
11
|
+
`dist/zx.css` into that asset directory. Replace:
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<link rel="stylesheet" href="/net.zeyon.lib.gx-3000/assets/gx.css">
|
|
15
|
+
<script src="/net.zeyon.lib.gx-3000/assets/gx-core.js"></script>
|
|
16
|
+
<script src="/net.zeyon.lib.gx-3000/assets/gx-zeyos.js"></script>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
with this order:
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<link rel="stylesheet" href="/net.zeyon.lib.gx-3000/assets/zx.css">
|
|
23
|
+
<script src="/net.zeyon.lib.gx-3000/assets/zx.global.js"></script>
|
|
24
|
+
<script src="/net.zeyon.lib.gx-3000/assets/zx-compat.global.js"></script>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The compatibility entry exposes both `window.zx` and `window.gx`. Element
|
|
28
|
+
`store`/`retrieve`/`eliminate` is installed automatically. If the application uses `__()`, `_()`,
|
|
29
|
+
`String.prototype.htmlSpecialChars`, or `Array.prototype.findBy`, opt in after both scripts load:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
gx.compat.installGlobals();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Do not call this for newly migrated code; import `h`, `htmlEscape`, and the i18n helpers directly.
|
|
36
|
+
|
|
37
|
+
## Class-by-class replacements
|
|
38
|
+
|
|
39
|
+
The snippets show the normal direct-Zx replacement. All strings supplied as component content are
|
|
40
|
+
inserted as text; pass a DOM node when structured content is needed.
|
|
41
|
+
|
|
42
|
+
### `gx.zeyos.Toggle` → `zx.Toggle`
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// gx
|
|
46
|
+
const control = new gx.zeyos.Toggle(host, { on: true, value: 'enabled' });
|
|
47
|
+
control.addEvent('uncheck', () => save(false));
|
|
48
|
+
|
|
49
|
+
// Zx
|
|
50
|
+
const control = new zx.Toggle(host, { checked: true, value: 'enabled' });
|
|
51
|
+
control.on('change', (event) => save(event.detail.checked));
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use `get()`, `getValue()`, `set(boolean)`, and `toggle()` in place of
|
|
55
|
+
`getState()`, `setChecked()`, and `setUnchecked()`.
|
|
56
|
+
|
|
57
|
+
### `gx.zeyos.Msgbox` → `zx.Message`
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
// gx
|
|
61
|
+
const messages = new gx.zeyos.Msgbox();
|
|
62
|
+
messages.show('Saved', 's_msg_32_success');
|
|
63
|
+
|
|
64
|
+
// Zx
|
|
65
|
+
const messages = new zx.Message(null, { timeout: 0 });
|
|
66
|
+
document.body.append(messages.el);
|
|
67
|
+
const handle = messages.show('Saved', { kind: 'success' });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Call `handle.close()` instead of `hide()`.
|
|
71
|
+
|
|
72
|
+
### `gx.bootstrap.Message` → `zx.Message`
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
// gx
|
|
76
|
+
const messages = new gx.bootstrap.Message(host);
|
|
77
|
+
messages.addMessage('Saved', 'success', true);
|
|
78
|
+
messages.showStatus(40, 'Uploading');
|
|
79
|
+
|
|
80
|
+
// Zx
|
|
81
|
+
const messages = new zx.Message(host);
|
|
82
|
+
messages.show('Saved', { kind: 'success', closable: true });
|
|
83
|
+
const progress = zx.Message.progress('Uploading');
|
|
84
|
+
progress.update(40);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use `progress.done()` or `progress.fail(message)` instead of `hideStatus()`.
|
|
88
|
+
|
|
89
|
+
### `gx.zeyos.Popup` and `gx.bootstrap.Popup` → `zx.Dialog`
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
// gx (either Popup class)
|
|
93
|
+
const popup = new gx.zeyos.Popup({ width: 480, content: 'Details', overlayDismiss: true });
|
|
94
|
+
popup.show();
|
|
95
|
+
|
|
96
|
+
// Zx
|
|
97
|
+
const popup = new zx.Dialog(null, { size: 480, content: 'Details', lightDismiss: true });
|
|
98
|
+
popup.open();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Replace `show`/`hide` events and methods with `open`/`close`. Use CSS for custom positioning;
|
|
102
|
+
legacy `setPosition()` is only a warning-producing compatibility no-op.
|
|
103
|
+
|
|
104
|
+
### `gx.bootstrap.PopupAlert` → `zx.Dialog.alert`
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
// gx
|
|
108
|
+
await gx.bootstrap.PopupAlert('Saved', 'The record was saved.');
|
|
109
|
+
|
|
110
|
+
// Zx
|
|
111
|
+
await zx.Dialog.alert({ title: 'Saved', message: 'The record was saved.' });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `gx.bootstrap.PopupConfirm` and `PopupConfirmCanceled` → `zx.Dialog.confirm`
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
// gx
|
|
118
|
+
const result = await gx.bootstrap.PopupConfirm('Delete', 'Delete this record?');
|
|
119
|
+
if (result !== gx.bootstrap.PopupConfirmCanceled) removeRecord();
|
|
120
|
+
|
|
121
|
+
// Zx
|
|
122
|
+
if (await zx.Dialog.confirm({ title: 'Delete', message: 'Delete this record?', danger: true })) {
|
|
123
|
+
removeRecord();
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `gx.zeyos.Dialog` → `zx.Dialog` views
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
// gx
|
|
131
|
+
const dialog = new gx.zeyos.Dialog(null, { title: 'Wizard' });
|
|
132
|
+
dialog.addFrame('review', { title: 'Review', content: reviewNode }, true);
|
|
133
|
+
dialog.openFrame('review');
|
|
134
|
+
|
|
135
|
+
// Zx
|
|
136
|
+
const dialog = new zx.Dialog(null, { title: 'Wizard' });
|
|
137
|
+
dialog.addView('review', { title: 'Review', content: reviewNode });
|
|
138
|
+
dialog.showView('review');
|
|
139
|
+
dialog.open();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Replace `addSubmitFrame`, `addFormFrame`, and `addSuccessFrame` with explicit views, `Form`
|
|
143
|
+
instances, and dialog button actions. Read form data with `form.getValues()`.
|
|
144
|
+
|
|
145
|
+
### `gx.zeyos.Dropdown` → `zx.MenuButton`
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// gx
|
|
149
|
+
const menu = new gx.zeyos.Dropdown(host, { items: { edit: 'Edit', remove: 'Remove' } });
|
|
150
|
+
menu.addEvent('change', (value) => run(value));
|
|
151
|
+
|
|
152
|
+
// Zx
|
|
153
|
+
const menu = new zx.MenuButton(null, {
|
|
154
|
+
label: 'Actions',
|
|
155
|
+
items: [{ value: 'edit', label: 'Edit' }, { value: 'remove', label: 'Remove' }],
|
|
156
|
+
onselect: (event) => run(event.detail.value)
|
|
157
|
+
});
|
|
158
|
+
host.append(menu.el);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `gx.bootstrap.MenuButton` → `zx.MenuButton`
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// gx
|
|
165
|
+
const menu = new gx.bootstrap.MenuButton(host, { label: 'Actions' });
|
|
166
|
+
menu.add('Edit').divider().add('Remove');
|
|
167
|
+
|
|
168
|
+
// Zx
|
|
169
|
+
const menu = new zx.MenuButton(host, {
|
|
170
|
+
label: 'Actions', items: [{ label: 'Edit', value: 'edit' }, '-', { label: 'Remove', value: 'remove' }]
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `gx.zeyos.Select` and `gx.bootstrap.Select` → `zx.Select`
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
// gx (either namespace)
|
|
178
|
+
const select = new gx.zeyos.Select(host, {
|
|
179
|
+
data: rows, elementIndex: 'ID', elementLabel: 'name', allowEmpty: true
|
|
180
|
+
});
|
|
181
|
+
select.addEvent('select', (item) => save(item.ID));
|
|
182
|
+
|
|
183
|
+
// Zx
|
|
184
|
+
const select = new zx.Select(host, {
|
|
185
|
+
items: rows, valueKey: 'ID', labelKey: 'name', clearable: true,
|
|
186
|
+
onchange: (event) => save(event.detail.value)
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Use `value`/`selected`, `set()`, `setItems()`, and `reset()`. A cleared selection is the same
|
|
191
|
+
`change` event with `{value: null, item: null}` rather than a separate `noselect` event.
|
|
192
|
+
|
|
193
|
+
### `gx.zeyos.SelectFilter` and `gx.bootstrap.SelectFilter` → local `zx.Select`
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
// gx
|
|
197
|
+
const select = new gx.zeyos.SelectFilter(host, { data: rows, searchfields: ['name', 'code'] });
|
|
198
|
+
|
|
199
|
+
// Zx
|
|
200
|
+
const select = new zx.Select(host, { items: rows, filter: 'local', searchKeys: ['name', 'code'] });
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `gx.zeyos.SelectDyn` and `gx.bootstrap.SelectDyn` → async `zx.Select`
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
// gx
|
|
207
|
+
const select = new gx.zeyos.SelectDyn(host, { url: '/people', queryParam: 'query' });
|
|
208
|
+
|
|
209
|
+
// Zx
|
|
210
|
+
const http = new zx.Http();
|
|
211
|
+
const select = new zx.Select(host, {
|
|
212
|
+
filter: (query) => http.get('/people', { query }),
|
|
213
|
+
onloaded: (event) => console.log(event.detail.items)
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### `gx.bootstrap.SelectDynREST` → `zx.Select` + `zx.zeyosService`
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
// gx
|
|
221
|
+
const select = new gx.bootstrap.SelectDynREST(host, { entity: 'contacts', limit: 20 });
|
|
222
|
+
|
|
223
|
+
// Zx
|
|
224
|
+
const contacts = zx.zeyosService('contacts');
|
|
225
|
+
const select = new zx.Select(host, {
|
|
226
|
+
filter: (query) => contacts.get('', { search: query, limit: 20 })
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `gx.zeyos.SelectPrio` and `gx.bootstrap.SelectPrio` → `zx.Select.priority`
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
// gx
|
|
234
|
+
const priority = new gx.zeyos.SelectPrio(host, { value: 2 });
|
|
235
|
+
|
|
236
|
+
// Zx
|
|
237
|
+
const priority = zx.Select.priority(host, { value: 2 });
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### `gx.zeyos.Checklist` and `gx.bootstrap.Checklist` → `zx.Checklist`
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
// gx (either namespace)
|
|
244
|
+
const list = new gx.zeyos.Checklist(host, { data: rows, listValue: 'ID', listFormat: 'name' });
|
|
245
|
+
list.setValues([1, 2]);
|
|
246
|
+
|
|
247
|
+
// Zx
|
|
248
|
+
const list = new zx.Checklist(host, { items: rows, valueKey: 'ID', labelKey: 'name' });
|
|
249
|
+
list.setValues([1, 2]);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
For remote data pass `load: () => Promise<items>` and listen for `loaded`.
|
|
253
|
+
|
|
254
|
+
### `gx.zeyos.Permission` → `zx.Permission`
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
// gx
|
|
258
|
+
const permission = new gx.zeyos.Permission(host, { value: true, groups });
|
|
259
|
+
|
|
260
|
+
// Zx
|
|
261
|
+
const permission = new zx.Permission(host, { value: 'public', groups });
|
|
262
|
+
permission.on('change', (event) => save(event.detail.value));
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### `gx.zeyos.Table` and `gx.bootstrap.Table` → `zx.Table`
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
// gx (either namespace)
|
|
269
|
+
const table = new gx.zeyos.Table(host, {
|
|
270
|
+
cols: [{ id: 'name', label: 'Name', filterable: true }],
|
|
271
|
+
structure: (row) => [row.name], data: rows
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Zx
|
|
275
|
+
const table = new zx.Table(host, {
|
|
276
|
+
columns: [{ id: 'name', label: 'Name', sortable: true }],
|
|
277
|
+
data: rows, rowId: 'ID'
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Move `structure()` work into per-column `render(row, index)`. Replace `filter` events with `sort`
|
|
282
|
+
and `click`/`dblclick` with `rowclick`/`rowdblclick`; all payloads are in `event.detail`.
|
|
283
|
+
|
|
284
|
+
### `gx.ui.SimpleTable` → `zx.Table`
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
// gx
|
|
288
|
+
const table = new gx.ui.SimpleTable({ cols: ['Name'] });
|
|
289
|
+
table.addRow({ ID: 1, name: 'Ada' });
|
|
290
|
+
|
|
291
|
+
// Zx
|
|
292
|
+
const table = new zx.Table(null, { columns: [{ id: 'name', label: 'Name' }], rowId: 'ID' });
|
|
293
|
+
table.addData([{ ID: 1, name: 'Ada' }]);
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Use `setData`, `addData`, `updateRow`, `removeRow`, and `getData` for row operations.
|
|
297
|
+
|
|
298
|
+
### `gx.zeyos.Tabbox` and `gx.bootstrap.Tabbox` → `zx.Tabbox`
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
// gx (either namespace; show is one-based)
|
|
302
|
+
const tabs = new gx.zeyos.Tabbox(host, { frames, show: 2 });
|
|
303
|
+
tabs.openTab('history');
|
|
304
|
+
|
|
305
|
+
// Zx
|
|
306
|
+
const tabs = new zx.Tabbox(host, { tabs, active: 'history' });
|
|
307
|
+
tabs.openTab('history');
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Rename `frames` to `tabs`; each entry keeps `name`, `title`, and `content`. Use `setBadge()` in
|
|
311
|
+
place of `setHighlight()`.
|
|
312
|
+
|
|
313
|
+
### `gx.bootstrap.NavigationBar` → `zx.NavigationBar`
|
|
314
|
+
|
|
315
|
+
```js
|
|
316
|
+
// gx
|
|
317
|
+
const navigation = new gx.bootstrap.NavigationBar(host, { title: 'ZeyOS', frames, buttons });
|
|
318
|
+
|
|
319
|
+
// Zx
|
|
320
|
+
const navigation = new zx.NavigationBar(host, { title: 'ZeyOS', items: frames, actions: buttons });
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### `gx.zeyos.Panel` → `zx.Panel`
|
|
324
|
+
|
|
325
|
+
```js
|
|
326
|
+
// gx
|
|
327
|
+
const panel = new gx.zeyos.Panel(host, 'Details', contentNode, true);
|
|
328
|
+
|
|
329
|
+
// Zx
|
|
330
|
+
const panel = new zx.Panel(host, { title: 'Details', content: contentNode, open: true });
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### `gx.zeyos.MasterPanel` → `zx.MasterPanel`
|
|
334
|
+
|
|
335
|
+
```js
|
|
336
|
+
// gx
|
|
337
|
+
const panel = new gx.zeyos.MasterPanel(host, 'Contacts', contentNode, buttons);
|
|
338
|
+
|
|
339
|
+
// Zx
|
|
340
|
+
const panel = new zx.MasterPanel(host, { title: 'Contacts', content: contentNode, buttons });
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### `gx.zeyos.Groupbox` → `zx.Groupbox`
|
|
344
|
+
|
|
345
|
+
```js
|
|
346
|
+
// gx
|
|
347
|
+
const group = new gx.zeyos.Groupbox(host, { title: 'Advanced', open: false });
|
|
348
|
+
|
|
349
|
+
// Zx
|
|
350
|
+
const group = new zx.Groupbox(host, { title: 'Advanced', open: false });
|
|
351
|
+
group.open();
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### `gx.zeyos.Search` → `zx.Search`
|
|
355
|
+
|
|
356
|
+
```js
|
|
357
|
+
// gx
|
|
358
|
+
const search = new gx.zeyos.Search();
|
|
359
|
+
search.addEvent('keypress', () => load(search.get()));
|
|
360
|
+
|
|
361
|
+
// Zx
|
|
362
|
+
const search = new zx.Search(null, { onsubmit: (event) => load(event.detail.value) });
|
|
363
|
+
host.append(search.el);
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### `gx.zeyos.Datebox` → `zx.Datebox` or `zx.DateTimeBox`
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
// gx
|
|
370
|
+
const date = new gx.zeyos.Datebox(host, { timestamp, unit: 'seconds', format: ['d', '.', 'M', '.', 'y'] });
|
|
371
|
+
|
|
372
|
+
// Zx
|
|
373
|
+
const date = new zx.Datebox(host, { value: timestamp, format: '%d.%m.%Y' });
|
|
374
|
+
const timestampSeconds = date.get('seconds');
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Use `zx.DateTimeBox(host, options)` when the legacy format included hours/minutes.
|
|
378
|
+
|
|
379
|
+
### `gx.zeyos.DatePicker` → `zx.DatePicker`
|
|
380
|
+
|
|
381
|
+
```js
|
|
382
|
+
// gx
|
|
383
|
+
const picker = new gx.zeyos.DatePicker(host, { date: initial, weeknumbers: true });
|
|
384
|
+
|
|
385
|
+
// Zx
|
|
386
|
+
const picker = new zx.DatePicker(host, { value: initial, showWeekNumbers: true });
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### `gx.zeyos.MonthPicker` → `zx.MonthPicker`
|
|
390
|
+
|
|
391
|
+
```js
|
|
392
|
+
// gx
|
|
393
|
+
const picker = new gx.zeyos.MonthPicker(host, { date: initial });
|
|
394
|
+
|
|
395
|
+
// Zx
|
|
396
|
+
const picker = new zx.MonthPicker(host, { value: initial });
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### `gx.zeyos.TimePicker` → `zx.TimePicker`
|
|
400
|
+
|
|
401
|
+
```js
|
|
402
|
+
// gx
|
|
403
|
+
const picker = new gx.zeyos.TimePicker(host, { date: initial, format: '%H:%M:%S' });
|
|
404
|
+
|
|
405
|
+
// Zx
|
|
406
|
+
const picker = new zx.TimePicker(host, { value: initial, seconds: true });
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Direct picker `change` events carry `{date}` or `{time}`. Use `Date#getTime()` or the exported
|
|
410
|
+
date formatting helpers when a timestamp or formatted string is required.
|
|
411
|
+
|
|
412
|
+
### `gx.ui.Timebox`, `gx.zeyos.Timebox`, and `gx.bootstrap.Timebox` → `zx.Timebox`
|
|
413
|
+
|
|
414
|
+
```js
|
|
415
|
+
// gx (any namespace)
|
|
416
|
+
const duration = new gx.zeyos.Timebox(host, { time: -90, unit: 'minutes', prefix: true });
|
|
417
|
+
|
|
418
|
+
// Zx
|
|
419
|
+
const duration = new zx.Timebox(host, { value: -90, unit: 'minutes', signed: true });
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Use `get(unit)`, `set(value, unit)`, `enable()`, and `disable()`.
|
|
423
|
+
|
|
424
|
+
### `gx.bootstrap.CheckButton` → `zx.CheckButton`
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
// gx
|
|
428
|
+
const check = new gx.bootstrap.CheckButton(host, { label: ['On', 'Off'], value: true });
|
|
429
|
+
|
|
430
|
+
// Zx
|
|
431
|
+
const check = new zx.CheckButton(host, { label: ['On', 'Off'], checked: true });
|
|
432
|
+
check.on('change', (event) => save(event.detail.checked));
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### `gx.bootstrap.Form` → `zx.Form`
|
|
436
|
+
|
|
437
|
+
```js
|
|
438
|
+
// gx
|
|
439
|
+
const form = new gx.bootstrap.Form(host, { horizontal: true, fields: legacyFields });
|
|
440
|
+
|
|
441
|
+
// Zx
|
|
442
|
+
const form = new zx.Form(host, {
|
|
443
|
+
fieldsets: [{ fields: modernFields }],
|
|
444
|
+
actions: [{ id: 'save', label: 'Save', type: 'submit', kind: 'primary' }]
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Use `getValues`, `setValues`, `getField`, `setHighlights`, `reset`, and the preventable `submit`
|
|
449
|
+
event.
|
|
450
|
+
|
|
451
|
+
### `gx.bootstrap.Fieldset` → `zx.Fieldset`
|
|
452
|
+
|
|
453
|
+
```js
|
|
454
|
+
// gx
|
|
455
|
+
const fields = new gx.bootstrap.Fieldset(host, { title: 'Contact', fields: legacyFields });
|
|
456
|
+
|
|
457
|
+
// Zx
|
|
458
|
+
const fields = new zx.Fieldset(host, { title: 'Contact', columns: 2, fields: modernFields });
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### `gx.bootstrap.Field` → `zx.Field`
|
|
462
|
+
|
|
463
|
+
```js
|
|
464
|
+
// gx
|
|
465
|
+
const field = new gx.bootstrap.Field({ type: 'text', label: 'Name', value: 'Ada' });
|
|
466
|
+
host.append(field.toElement());
|
|
467
|
+
|
|
468
|
+
// Zx
|
|
469
|
+
const field = new zx.Field(host, { id: 'name', type: 'text', label: 'Name', value: 'Ada' });
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Legacy `gxselect`, date/month/time widgets, option lists, and custom HTML fields map to registered
|
|
473
|
+
Zx field adapters. Highlights use `danger`, `warning`, or `success`.
|
|
474
|
+
|
|
475
|
+
### `gx.bootstrap.ValueList` → `zx.ValueList`
|
|
476
|
+
|
|
477
|
+
```js
|
|
478
|
+
// gx
|
|
479
|
+
const values = new gx.bootstrap.ValueList(host, { deletable: true });
|
|
480
|
+
values.addValue('one');
|
|
481
|
+
|
|
482
|
+
// Zx
|
|
483
|
+
const values = new zx.ValueList(host, { deletable: true, sortable: true });
|
|
484
|
+
values.addValue('one');
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### `gx.bootstrap.MultiValueEditor` → `zx.MultiValueEditor`
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
// gx (JSON string)
|
|
491
|
+
const editor = new gx.bootstrap.MultiValueEditor(host);
|
|
492
|
+
editor.setValue('["one","two"]');
|
|
493
|
+
|
|
494
|
+
// Zx (array)
|
|
495
|
+
const editor = new zx.MultiValueEditor(host);
|
|
496
|
+
editor.setValues(['one', 'two']);
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
The compatibility wrapper deliberately preserves JSON-string `getValue()`/`setValue()` only for
|
|
500
|
+
unmigrated callers.
|
|
501
|
+
|
|
502
|
+
### `gx.bootstrap.FieldUpload` → `zx.FieldUpload`
|
|
503
|
+
|
|
504
|
+
```js
|
|
505
|
+
// gx
|
|
506
|
+
const upload = new gx.bootstrap.FieldUpload({ uploadurl: '/upload', inputname: 'document' });
|
|
507
|
+
host.append(upload.toElement());
|
|
508
|
+
|
|
509
|
+
// Zx
|
|
510
|
+
const upload = new zx.FieldUpload(host, { url: '/upload', paramName: 'document' });
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Use `params`, `accept`, `maxSize`, `multiple`, and the `select`, `progress`, `success`, `error`, and
|
|
514
|
+
`abort` events.
|
|
515
|
+
|
|
516
|
+
### `gx.bootstrap.DataFilter` → `zx.DataFilter`
|
|
517
|
+
|
|
518
|
+
```js
|
|
519
|
+
// gx
|
|
520
|
+
const filter = new gx.bootstrap.DataFilter(host);
|
|
521
|
+
filter.addFulltextFilter('query', ['name', 'city']).initData(rows).doFilter();
|
|
522
|
+
|
|
523
|
+
// Zx
|
|
524
|
+
const filter = new zx.DataFilter(host, {
|
|
525
|
+
data: rows,
|
|
526
|
+
filters: [{ type: 'text', id: 'query', label: 'Search', fields: ['name', 'city'] }]
|
|
527
|
+
});
|
|
528
|
+
const visibleRows = filter.apply();
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Use `setData`, `setState`, `getState`, `apply`, `clear`, and `addFilter`.
|
|
532
|
+
|
|
533
|
+
### `gx.zeyos.Client` → `zx.Http`
|
|
534
|
+
|
|
535
|
+
```js
|
|
536
|
+
// gx
|
|
537
|
+
const client = new gx.zeyos.Client({ url: '/api/' });
|
|
538
|
+
client.get('contacts', { active: true });
|
|
539
|
+
|
|
540
|
+
// Zx
|
|
541
|
+
const client = new zx.Http({ base: '/api/' });
|
|
542
|
+
await client.get('contacts', { active: true });
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### `gx.zeyos.Request` → `zx.zeyosService`
|
|
546
|
+
|
|
547
|
+
```js
|
|
548
|
+
// gx
|
|
549
|
+
const request = new gx.zeyos.Request({ service: 'contacts', accesskey: token });
|
|
550
|
+
request.post('create', data);
|
|
551
|
+
|
|
552
|
+
// Zx
|
|
553
|
+
const request = zx.zeyosService('contacts', token);
|
|
554
|
+
await request.post('create', data);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
`Http` uses promises and exposes `request`, `get`, `post`, `put`, and `delete`. Uploads use
|
|
558
|
+
`request(path, {method, files, data})`. Request failures reject; use `try`/`catch` or `onError`.
|
|
559
|
+
|
|
560
|
+
### `gx.zeyos.Factory` → `zx.button`, `zx.buttonGroup`, and `zx.icon`
|
|
561
|
+
|
|
562
|
+
```js
|
|
563
|
+
// gx
|
|
564
|
+
const save = gx.zeyos.Factory.Button('Save', 'primary', 'check');
|
|
565
|
+
const glyph = gx.zeyos.Factory.Icon('trash');
|
|
566
|
+
|
|
567
|
+
// Zx
|
|
568
|
+
const save = zx.button({ label: 'Save', kind: 'primary', icon: 'check' });
|
|
569
|
+
const glyph = zx.icon('trash');
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## Intentionally not reproduced
|
|
573
|
+
|
|
574
|
+
- `gx.core.Settings` and `gx.ui.Container`: direct construction now throws. Use plain option
|
|
575
|
+
objects and extend `zx.Component`; emulating the MooTools inheritance model would retain the
|
|
576
|
+
coupling Zx removes.
|
|
577
|
+
- `gx.ui.Collapse` and `gx.ui.Blend`: compatibility names are migration-error stubs. Use CSS
|
|
578
|
+
transitions guarded by `prefers-reduced-motion`; Zx does not reproduce `Fx.*` timing or the
|
|
579
|
+
MooTools `Class`/`Fx` APIs.
|
|
580
|
+
- `gx.ui.Hud`: use `zx.Dialog` or `zx.Modal` so focus, Escape, and the top layer remain native.
|
|
581
|
+
- `gx.ui.Toggling`: use `zx.Toggle`, `zx.CheckButton`, `zx.Panel`, or direct ARIA/data state.
|
|
582
|
+
- `gx.ui.HGroup`: use application CSS grid/flex layout.
|
|
583
|
+
- `gx.ui.Templates`: use native `<template>`, `zx.h()`, or explicit renderer functions.
|
|
584
|
+
- Legacy bugs are fixed, not emulated: `MenuButton.setStyle`'s typo, the dead
|
|
585
|
+
`MultiValueEditor` delete path, duplicate CheckButton `check`, the Request.File comma bug,
|
|
586
|
+
Tabbox's wrong root, and `Request.delete()` sending PUT. Update tests that depended on those
|
|
587
|
+
defects; `Http.delete()` sends DELETE.
|
|
588
|
+
- `_theme` class-map overrides, including `gx.ui.Table._theme`, are not supported. Override Zx
|
|
589
|
+
semantic tokens or documented component selectors instead.
|
|
590
|
+
- Legacy atomic utility CSS and pixel-identical legacy styling are not shipped. Keep temporary
|
|
591
|
+
app-owned utilities during migration, then replace them with layout CSS and semantic tokens.
|
|
592
|
+
- Fontello numeric glyph codes are not supported. Use the named icons accepted by `zx.icon()`.
|
|
593
|
+
- Full MooTools `getCoordinates()` objects are not emulated. Wrappers expose only
|
|
594
|
+
`width`/`height`/`top`/`left`; migrated code should use `getBoundingClientRect()`.
|
|
595
|
+
- `dispatchEvents` is not reproduced. Use native `dispatchEvent()` or a component's `emit()` and
|
|
596
|
+
listen for bubbling `zx-*` DOM events.
|
|
597
|
+
- `gx.Browser` is not reproduced. Prefer feature detection (`CSS.supports`, element/method
|
|
598
|
+
presence, media queries) over browser-name branching.
|