@zeyos/zx 2.2.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +197 -0
  2. package/DESIGN-SYSTEM.md +136 -0
  3. package/MIGRATION.md +155 -4
  4. package/README.md +51 -14
  5. package/dist/types/compat/map/data.d.ts +3 -2
  6. package/dist/types/components/account-menu/account-menu.d.ts +144 -0
  7. package/dist/types/components/app-rail/app-rail.d.ts +250 -0
  8. package/dist/types/components/app-sidebar/app-sidebar.d.ts +169 -0
  9. package/dist/types/components/avatar/avatar.d.ts +100 -0
  10. package/dist/types/components/chart/chart.d.ts +321 -0
  11. package/dist/types/components/date-picker/month-picker.d.ts +6 -0
  12. package/dist/types/components/dialog/dialog.d.ts +9 -0
  13. package/dist/types/components/dock/dock.d.ts +495 -0
  14. package/dist/types/components/dropdown/dropdown.d.ts +2 -2
  15. package/dist/types/components/field/field.d.ts +14 -0
  16. package/dist/types/components/field-upload/field-upload.d.ts +37 -4
  17. package/dist/types/components/form/form.d.ts +25 -3
  18. package/dist/types/components/grid/grid.d.ts +172 -0
  19. package/dist/types/components/launcher/launcher.d.ts +300 -0
  20. package/dist/types/components/layout/layout.d.ts +4 -4
  21. package/dist/types/components/menu-button/menu-button.d.ts +10 -2
  22. package/dist/types/components/modal/modal.d.ts +25 -0
  23. package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +74 -9
  24. package/dist/types/components/questionnaire/items.d.ts +327 -0
  25. package/dist/types/components/questionnaire/questionnaire.d.ts +449 -0
  26. package/dist/types/components/select/select.d.ts +36 -1
  27. package/dist/types/components/sheet/sheet-stack.d.ts +167 -0
  28. package/dist/types/components/sheet/sheet.d.ts +294 -0
  29. package/dist/types/components/split-view/split-view.d.ts +2 -21
  30. package/dist/types/components/tabbox/tabbox.d.ts +12 -3
  31. package/dist/types/components/table/table.d.ts +219 -12
  32. package/dist/types/components/tooltip/tooltip.d.ts +2 -2
  33. package/dist/types/components/value-list/value-list.d.ts +24 -3
  34. package/dist/types/core/dom.d.ts +114 -0
  35. package/dist/types/core/drag-axis.d.ts +111 -0
  36. package/dist/types/core/position.d.ts +4 -2
  37. package/dist/types/index.d.ts +12 -2
  38. package/dist/zx-compat.esm.js +943 -311
  39. package/dist/zx-compat.esm.min.js +1 -1
  40. package/dist/zx-compat.global.js +7893 -2252
  41. package/dist/zx-compat.global.min.js +3 -3
  42. package/dist/zx-zeyos.esm.js +826 -114
  43. package/dist/zx-zeyos.esm.min.js +1 -1
  44. package/dist/zx.css +1720 -243
  45. package/dist/zx.esm.js +8227 -2599
  46. package/dist/zx.esm.min.js +3 -3
  47. package/dist/zx.global.js +8227 -2599
  48. package/dist/zx.global.min.js +3 -3
  49. package/dist/zx.min.css +1 -1
  50. package/docs/api.json +2597 -255
  51. package/docs/llms.md +475 -37
  52. package/docs/llms.txt +21 -9
  53. package/package.json +4 -2
  54. package/src/compat/globals.js +3 -1
  55. package/src/compat/map/data.js +31 -9
  56. package/src/components/account-menu/account-menu.css +70 -0
  57. package/src/components/account-menu/account-menu.js +208 -0
  58. package/src/components/app-rail/app-rail.css +107 -0
  59. package/src/components/app-rail/app-rail.js +668 -0
  60. package/src/components/app-sidebar/app-sidebar.css +68 -0
  61. package/src/components/app-sidebar/app-sidebar.js +388 -0
  62. package/src/components/avatar/avatar.css +61 -0
  63. package/src/components/avatar/avatar.js +222 -0
  64. package/src/components/button/button.css +0 -1
  65. package/src/components/chart/chart.css +61 -0
  66. package/src/components/chart/chart.js +518 -0
  67. package/src/components/date-picker/date-range-picker.css +7 -0
  68. package/src/components/date-picker/month-picker.js +9 -0
  69. package/src/components/dialog/dialog.js +11 -4
  70. package/src/components/dock/dock.css +228 -0
  71. package/src/components/dock/dock.js +977 -0
  72. package/src/components/dropdown/dropdown.js +1 -1
  73. package/src/components/field/field.js +2 -0
  74. package/src/components/field-upload/field-upload.js +9 -4
  75. package/src/components/fieldset/fieldset.css +7 -0
  76. package/src/components/form/form.css +7 -0
  77. package/src/components/form/form.js +6 -3
  78. package/src/components/grid/grid.css +6 -0
  79. package/src/components/grid/grid.js +213 -0
  80. package/src/components/launcher/launcher.css +100 -0
  81. package/src/components/launcher/launcher.js +557 -0
  82. package/src/components/layout/layout.js +2 -2
  83. package/src/components/menu-button/menu-button.js +27 -2
  84. package/src/components/modal/modal.css +5 -1
  85. package/src/components/modal/modal.js +37 -2
  86. package/src/components/multi-value-editor/multi-value-editor.css +99 -15
  87. package/src/components/multi-value-editor/multi-value-editor.js +237 -19
  88. package/src/components/navigation-bar/navigation-bar.css +7 -0
  89. package/src/components/questionnaire/items.js +370 -0
  90. package/src/components/questionnaire/questionnaire.css +387 -0
  91. package/src/components/questionnaire/questionnaire.js +1033 -0
  92. package/src/components/search/search.css +10 -2
  93. package/src/components/select/select.css +6 -1
  94. package/src/components/select/select.js +99 -11
  95. package/src/components/sheet/sheet-stack.js +304 -0
  96. package/src/components/sheet/sheet.css +351 -0
  97. package/src/components/sheet/sheet.js +551 -0
  98. package/src/components/split-view/split-view.js +76 -161
  99. package/src/components/stepper/stepper.css +12 -2
  100. package/src/components/tabbox/tabbox.css +13 -3
  101. package/src/components/tabbox/tabbox.js +34 -10
  102. package/src/components/table/table.css +43 -0
  103. package/src/components/table/table.js +523 -45
  104. package/src/components/tooltip/tooltip.js +5 -2
  105. package/src/components/value-list/value-list.js +6 -3
  106. package/src/core/dom.js +302 -0
  107. package/src/core/drag-axis.js +203 -0
  108. package/src/core/position.js +68 -22
  109. package/src/index.js +19 -2
  110. package/styles/tokens/dark.css +15 -13
  111. package/styles/tokens/global.css +17 -5
  112. package/styles/tokens/semantic.css +14 -8
  113. package/styles/tokens/themes.css +72 -0
  114. package/styles/zx.css +11 -1
  115. package/dist/types/components/permission/permission.d.ts +0 -93
  116. package/src/components/permission/permission.css +0 -47
  117. package/src/components/permission/permission.js +0 -198
@@ -0,0 +1,387 @@
1
+ /*
2
+ * Questionnaire — one question at a time, with the answers as cards rather than a dense form row.
3
+ *
4
+ * The choice is a `<label>` wrapping a real radio or checkbox, so `:has(:checked)` is the whole
5
+ * selected-state mechanism: no class bookkeeping, and the card stays in step with the control even
6
+ * when something else moves the selection. The native input itself is hidden from sight but not
7
+ * from the accessibility tree or the focus order — `:focus-visible` on it rings the card instead.
8
+ */
9
+
10
+ .zx-questionnaire {
11
+ /* Card geometry shared by the choices and the review rows. */
12
+ --zx-questionnaire-radius: var(--zx-radius-lg);
13
+ --zx-questionnaire-gap: var(--zx-space-3);
14
+ display: block;
15
+ color: var(--zx-color-text);
16
+ }
17
+
18
+ .zx-questionnaire__form,
19
+ .zx-questionnaire:is(form) {
20
+ display: grid;
21
+ gap: var(--zx-space-5);
22
+ }
23
+
24
+ .zx-questionnaire__progress {
25
+ display: block;
26
+ }
27
+
28
+ /*
29
+ * Every part the component shows and hides needs this. `[hidden]` is a UA rule of the lowest
30
+ * possible specificity, so any `display` a class sets silently beats it — which is how the review
31
+ * screen ended up rendering underneath the question it replaces.
32
+ */
33
+ .zx-questionnaire__progress[hidden],
34
+ .zx-questionnaire__item[hidden],
35
+ .zx-questionnaire__review[hidden],
36
+ .zx-questionnaire__error[hidden],
37
+ .zx-questionnaire__actions > .zx-btn[hidden] {
38
+ display: none;
39
+ }
40
+
41
+ /* ------------------------------------------------------------------ item */
42
+
43
+ .zx-questionnaire__item {
44
+ display: grid;
45
+ gap: var(--zx-questionnaire-gap);
46
+ margin: 0;
47
+ border: 0;
48
+ /* A fieldset carries default padding in every browser; the grid owns the spacing here. */
49
+ padding: 0;
50
+ min-inline-size: 0;
51
+ }
52
+
53
+ .zx-questionnaire__item:focus {
54
+ outline: none;
55
+ }
56
+
57
+ .zx-questionnaire__item:focus-visible {
58
+ outline: none;
59
+ box-shadow: var(--zx-focus-ring);
60
+ border-radius: var(--zx-questionnaire-radius);
61
+ }
62
+
63
+ /* `<legend>` is laid out by the fieldset rather than by its own display, so it is taken out of
64
+ that flow and placed as an ordinary block before the answers. */
65
+ .zx-questionnaire__prompt {
66
+ display: block;
67
+ float: none;
68
+ margin: 0;
69
+ padding: 0;
70
+ inline-size: 100%;
71
+ color: var(--zx-color-text);
72
+ font-size: var(--zx-text-lg);
73
+ font-weight: 600;
74
+ line-height: 1.35;
75
+ }
76
+
77
+ .zx-questionnaire__description {
78
+ margin: 0;
79
+ color: var(--zx-color-text-muted);
80
+ font-size: var(--zx-text-sm);
81
+ line-height: 1.5;
82
+ }
83
+
84
+ .zx-questionnaire__error {
85
+ display: flex;
86
+ gap: var(--zx-space-2);
87
+ margin: 0;
88
+ color: var(--zx-color-danger);
89
+ font-size: var(--zx-text-sm);
90
+ }
91
+
92
+
93
+ /* --------------------------------------------------------------- choices */
94
+
95
+ .zx-questionnaire__choices {
96
+ display: grid;
97
+ gap: var(--zx-space-2);
98
+ }
99
+
100
+ .zx-questionnaire__choice {
101
+ display: flex;
102
+ align-items: flex-start;
103
+ gap: var(--zx-space-3);
104
+ border: 1px solid var(--zx-color-border-control);
105
+ border-radius: var(--zx-questionnaire-radius);
106
+ background: var(--zx-color-bg-control);
107
+ padding: var(--zx-space-3);
108
+ min-inline-size: 0;
109
+ cursor: pointer;
110
+ }
111
+
112
+ @media (prefers-reduced-motion: no-preference) {
113
+ .zx-questionnaire__choice {
114
+ transition: border-color var(--zx-dur-fast) var(--zx-ease),
115
+ background-color var(--zx-dur-fast) var(--zx-ease);
116
+ }
117
+ }
118
+
119
+ .zx-questionnaire__choice:hover:not([data-disabled]) {
120
+ border-color: var(--zx-color-border-strong);
121
+ background: var(--zx-color-bg-hover);
122
+ }
123
+
124
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:checked) {
125
+ border-color: var(--zx-color-accent);
126
+ background: var(--zx-color-bg-selected);
127
+ }
128
+
129
+ /* The ring belongs on the card, since the control it belongs to is the thing being hidden. */
130
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:focus-visible) {
131
+ box-shadow: var(--zx-focus-ring);
132
+ }
133
+
134
+ .zx-questionnaire__choice[data-disabled] {
135
+ opacity: 0.55;
136
+ cursor: not-allowed;
137
+ }
138
+
139
+ /* Kept in the layout at zero size: hiding it with `display: none` would take it out of the focus
140
+ order and out of the accessibility tree, which is the entire semantic contract here. */
141
+ .zx-questionnaire__control {
142
+ position: absolute;
143
+ margin: 0;
144
+ border: 0;
145
+ padding: 0;
146
+ inline-size: 1px;
147
+ block-size: 1px;
148
+ overflow: hidden;
149
+ clip-path: inset(50%);
150
+ white-space: nowrap;
151
+ }
152
+
153
+ .zx-questionnaire__marker {
154
+ flex: none;
155
+ display: grid;
156
+ place-items: center;
157
+ margin-block-start: 1px;
158
+ border: 1px solid var(--zx-color-border-strong);
159
+ inline-size: 18px;
160
+ block-size: 18px;
161
+ background: var(--zx-color-bg-surface);
162
+ }
163
+
164
+ /* Radios are round, checkboxes are square — the shape is how a reader tells "pick one" from
165
+ "pick any", so it follows the control type rather than a component option. */
166
+ .zx-questionnaire__choice:has(.zx-questionnaire__control[type="radio"]) .zx-questionnaire__marker {
167
+ border-radius: 50%;
168
+ }
169
+
170
+ .zx-questionnaire__choice:has(.zx-questionnaire__control[type="checkbox"]) .zx-questionnaire__marker {
171
+ border-radius: var(--zx-radius-sm);
172
+ }
173
+
174
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:checked) .zx-questionnaire__marker {
175
+ border-color: var(--zx-color-accent);
176
+ background: var(--zx-color-accent);
177
+ }
178
+
179
+ .zx-questionnaire__marker::after {
180
+ content: "";
181
+ inline-size: 8px;
182
+ block-size: 8px;
183
+ border-radius: inherit;
184
+ background: var(--zx-color-on-accent);
185
+ transform: scale(0);
186
+ }
187
+
188
+ @media (prefers-reduced-motion: no-preference) {
189
+ .zx-questionnaire__marker::after {
190
+ transition: transform var(--zx-dur-fast) var(--zx-ease);
191
+ }
192
+ }
193
+
194
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:checked) .zx-questionnaire__marker::after {
195
+ transform: scale(1);
196
+ }
197
+
198
+ .zx-questionnaire__choice > .zx-icon {
199
+ flex: none;
200
+ margin-block-start: 1px;
201
+ color: var(--zx-color-text-muted);
202
+ }
203
+
204
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:checked) > .zx-icon {
205
+ color: var(--zx-color-accent);
206
+ }
207
+
208
+ .zx-questionnaire__text {
209
+ display: grid;
210
+ gap: 2px;
211
+ flex: 1 1 auto;
212
+ min-inline-size: 0;
213
+ }
214
+
215
+ .zx-questionnaire__label {
216
+ font-size: var(--zx-control-font-size);
217
+ line-height: 1.4;
218
+ }
219
+
220
+ .zx-questionnaire__hint {
221
+ color: var(--zx-color-text-muted);
222
+ font-size: var(--zx-text-sm);
223
+ line-height: 1.45;
224
+ }
225
+
226
+ /* The key cap advertises the shortcut. It is `aria-hidden`: a screen-reader user navigates the
227
+ group with the arrow keys, and reading "one" before every answer would only be noise. */
228
+ .zx-questionnaire__key {
229
+ flex: none;
230
+ display: grid;
231
+ place-items: center;
232
+ border: 1px solid var(--zx-color-border);
233
+ border-radius: var(--zx-radius-sm);
234
+ background: var(--zx-color-bg-muted);
235
+ padding-inline: var(--zx-space-2);
236
+ min-inline-size: 22px;
237
+ block-size: 22px;
238
+ color: var(--zx-color-text-muted);
239
+ font-family: inherit;
240
+ font-size: var(--zx-text-xs);
241
+ text-transform: uppercase;
242
+ }
243
+
244
+ .zx-questionnaire__choice:has(.zx-questionnaire__control:checked) .zx-questionnaire__key {
245
+ border-color: var(--zx-color-accent);
246
+ color: var(--zx-color-accent);
247
+ }
248
+
249
+ /* -------------------------------------------------------------- freeform */
250
+
251
+ .zx-questionnaire__freeform {
252
+ display: grid;
253
+ gap: var(--zx-space-2);
254
+ padding-block-start: var(--zx-space-1);
255
+ }
256
+
257
+ .zx-questionnaire__freeform-label {
258
+ color: var(--zx-color-text-muted);
259
+ font-size: var(--zx-text-sm);
260
+ }
261
+
262
+ .zx-questionnaire__freeform-input {
263
+ border: 1px solid var(--zx-color-border-control);
264
+ border-radius: var(--zx-control-radius);
265
+ background: var(--zx-color-bg-control);
266
+ padding: var(--zx-space-2) var(--zx-control-pad-x);
267
+ min-block-size: var(--zx-control-height);
268
+ color: var(--zx-color-text);
269
+ font: inherit;
270
+ font-size: var(--zx-control-font-size);
271
+ }
272
+
273
+ .zx-questionnaire__freeform-input::placeholder {
274
+ color: var(--zx-color-text-placeholder);
275
+ }
276
+
277
+ .zx-questionnaire__freeform-input:focus-visible {
278
+ outline: none;
279
+ border-color: var(--zx-color-accent);
280
+ box-shadow: var(--zx-focus-ring);
281
+ }
282
+
283
+ /* ----------------------------------------------------------------- field */
284
+
285
+ /* A `field` item is named by the legend above it, so the Field's own label would say it twice —
286
+ hidden from sight, kept for the accessibility tree that uses it as the control's name. */
287
+ .zx-questionnaire__field[data-hide-label] > .zx-field__label {
288
+ position: absolute;
289
+ inline-size: 1px;
290
+ block-size: 1px;
291
+ overflow: hidden;
292
+ clip-path: inset(50%);
293
+ white-space: nowrap;
294
+ }
295
+
296
+ /* ---------------------------------------------------------------- review */
297
+
298
+ .zx-questionnaire__review {
299
+ display: grid;
300
+ gap: var(--zx-space-3);
301
+ }
302
+
303
+ .zx-questionnaire__review:focus {
304
+ outline: none;
305
+ }
306
+
307
+
308
+ .zx-questionnaire__review-title {
309
+ margin: 0;
310
+ font-size: var(--zx-text-lg);
311
+ font-weight: 600;
312
+ }
313
+
314
+ .zx-questionnaire__answers {
315
+ display: grid;
316
+ gap: var(--zx-space-2);
317
+ margin: 0;
318
+ }
319
+
320
+ .zx-questionnaire__answer {
321
+ display: grid;
322
+ grid-template-columns: minmax(0, 1fr) auto;
323
+ align-items: center;
324
+ gap: 0 var(--zx-space-3);
325
+ border: 1px solid var(--zx-color-border);
326
+ border-radius: var(--zx-questionnaire-radius);
327
+ background: var(--zx-color-bg-surface);
328
+ padding: var(--zx-space-3);
329
+ }
330
+
331
+ .zx-questionnaire__answer-prompt {
332
+ grid-column: 1;
333
+ color: var(--zx-color-text-muted);
334
+ font-size: var(--zx-text-sm);
335
+ }
336
+
337
+ .zx-questionnaire__answer-value {
338
+ grid-column: 1;
339
+ margin: 0;
340
+ min-inline-size: 0;
341
+ overflow-wrap: anywhere;
342
+ }
343
+
344
+ .zx-questionnaire__answer-value[data-empty] {
345
+ color: var(--zx-color-text-muted);
346
+ font-style: italic;
347
+ }
348
+
349
+ .zx-questionnaire__answer > .zx-btn {
350
+ grid-area: 1 / 2 / 3 / 3;
351
+ }
352
+
353
+ /* --------------------------------------------------------------- actions */
354
+
355
+ .zx-questionnaire__actions {
356
+ display: flex;
357
+ align-items: center;
358
+ gap: var(--zx-space-2);
359
+ flex-wrap: wrap;
360
+ }
361
+
362
+ .zx-questionnaire__spacer {
363
+ flex: 1 1 auto;
364
+ }
365
+
366
+
367
+ /* The forward action carries the pending state, because it is the control that started the wait. */
368
+ .zx-questionnaire[data-state="checking"] .zx-questionnaire__item,
369
+ .zx-questionnaire[data-state="checking"] .zx-questionnaire__choice {
370
+ cursor: progress;
371
+ }
372
+
373
+ .zx-questionnaire[data-state="complete"] .zx-questionnaire__item {
374
+ opacity: 0.7;
375
+ }
376
+
377
+ /* --------------------------------------------------------------- narrow */
378
+
379
+ @media (max-width: 480px) {
380
+ .zx-questionnaire__key {
381
+ display: none;
382
+ }
383
+
384
+ .zx-questionnaire__actions > .zx-btn {
385
+ flex: 1 1 auto;
386
+ }
387
+ }