@zeyos/zx 4.4.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/CHANGELOG.md +447 -0
  2. package/README.md +44 -11
  3. package/dist/types/components/account-menu/account-menu.d.ts +8 -0
  4. package/dist/types/components/activity-list/activity-list.d.ts +31 -1
  5. package/dist/types/components/app-icon/app-icon.d.ts +14 -2
  6. package/dist/types/components/app-sidebar/app-sidebar.d.ts +293 -17
  7. package/dist/types/components/avatar/avatar.d.ts +46 -7
  8. package/dist/types/components/badge/badge.d.ts +21 -1
  9. package/dist/types/components/button/button.d.ts +15 -0
  10. package/dist/types/components/calendar/calendar.d.ts +67 -5
  11. package/dist/types/components/card-view/card-view.d.ts +7 -4
  12. package/dist/types/components/card-view/record-card.d.ts +11 -0
  13. package/dist/types/components/chart/chart.d.ts +10 -0
  14. package/dist/types/components/checklist/checklist.d.ts +9 -0
  15. package/dist/types/components/code-editor/code-editor.d.ts +6 -17
  16. package/dist/types/components/context-menu/context-menu.d.ts +6 -2
  17. package/dist/types/components/data-filter/data-filter.d.ts +4 -4
  18. package/dist/types/components/datebox/date-range-box.d.ts +5 -1
  19. package/dist/types/components/datebox/datebox.d.ts +7 -2
  20. package/dist/types/components/dialog/dialog.d.ts +46 -6
  21. package/dist/types/components/dropdown/dropdown.d.ts +24 -9
  22. package/dist/types/components/entity-ref/entity-ref.d.ts +2 -2
  23. package/dist/types/components/field/field.d.ts +54 -2
  24. package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
  25. package/dist/types/components/fieldset/fieldset.d.ts +26 -1
  26. package/dist/types/components/file-item/file-item.d.ts +34 -6
  27. package/dist/types/components/file-list/file-list.d.ts +35 -3
  28. package/dist/types/components/filter/filter.d.ts +127 -3
  29. package/dist/types/components/filter-panel/filter-panel.d.ts +36 -7
  30. package/dist/types/components/form/form.d.ts +12 -1
  31. package/dist/types/components/kanban-view/kanban-card.d.ts +8 -0
  32. package/dist/types/components/launcher/launcher.d.ts +268 -15
  33. package/dist/types/components/list-toolbar/list-toolbar.d.ts +16 -7
  34. package/dist/types/components/menu-button/menu-button.d.ts +39 -5
  35. package/dist/types/components/message/message.d.ts +132 -17
  36. package/dist/types/components/modal/modal.d.ts +43 -2
  37. package/dist/types/components/module-bar/module-bar.d.ts +395 -0
  38. package/dist/types/components/pagination/pagination.d.ts +17 -3
  39. package/dist/types/components/select/color.d.ts +12 -0
  40. package/dist/types/components/select/glyphs.d.ts +124 -0
  41. package/dist/types/components/select/select.d.ts +17 -3
  42. package/dist/types/components/sheet/sheet.d.ts +15 -0
  43. package/dist/types/components/stat-tile/stat-tile.d.ts +16 -5
  44. package/dist/types/components/tabbox/tabbox.d.ts +9 -0
  45. package/dist/types/components/table/table.d.ts +311 -18
  46. package/dist/types/components/tag-picker/tag-picker.d.ts +21 -4
  47. package/dist/types/components/tree/tree.d.ts +13 -0
  48. package/dist/types/components/view/record-view.d.ts +59 -2
  49. package/dist/types/components/view-settings/view-settings.d.ts +879 -0
  50. package/dist/types/components/workspace-switcher/workspace-switcher.d.ts +327 -0
  51. package/dist/types/core/breakpoint.d.ts +1 -1
  52. package/dist/types/core/component.d.ts +12 -2
  53. package/dist/types/core/i18n.d.ts +27 -3
  54. package/dist/types/core/icons.d.ts +23 -25
  55. package/dist/types/core/keyboard.d.ts +98 -1
  56. package/dist/types/core/messages.d.ts +382 -0
  57. package/dist/types/core/motion.d.ts +59 -0
  58. package/dist/types/core/overlay-host.d.ts +42 -1
  59. package/dist/types/core/overlay-stack.d.ts +260 -0
  60. package/dist/types/index.d.ts +10 -5
  61. package/dist/types/internal/app-rail.d.ts +38 -0
  62. package/dist/types/internal/menu-items.d.ts +71 -3
  63. package/dist/types/zeyos/connect.d.ts +6 -0
  64. package/dist/types/zeyos/form.d.ts +50 -9
  65. package/dist/types/zeyos/index.d.ts +2 -1
  66. package/dist/types/zeyos/launcher.d.ts +9 -0
  67. package/dist/types/zeyos/module-bar.d.ts +176 -0
  68. package/dist/types/zeyos/query.d.ts +110 -5
  69. package/dist/types/zeyos/schema.d.ts +24 -1
  70. package/dist/types/zeyos/table.d.ts +345 -22
  71. package/dist/types/zeyos/view.d.ts +26 -2
  72. package/dist/zx-zeyos.esm.js +6178 -1008
  73. package/dist/zx-zeyos.esm.min.js +53 -5
  74. package/dist/zx.css +2861 -827
  75. package/dist/zx.esm.js +8909 -1480
  76. package/dist/zx.esm.min.js +55 -7
  77. package/dist/zx.global.js +8911 -1482
  78. package/dist/zx.global.min.js +55 -7
  79. package/dist/zx.min.css +1 -1
  80. package/docs/api.json +1079 -117
  81. package/docs/llms.md +956 -154
  82. package/docs/llms.txt +9 -5
  83. package/package.json +1 -1
  84. package/src/components/account-menu/account-menu.css +35 -10
  85. package/src/components/account-menu/account-menu.js +12 -0
  86. package/src/components/activity-item/activity-item.css +1 -1
  87. package/src/components/activity-item/activity-item.js +3 -0
  88. package/src/components/activity-list/activity-list.css +38 -3
  89. package/src/components/activity-list/activity-list.js +61 -1
  90. package/src/components/app-icon/app-icon.css +14 -3
  91. package/src/components/app-icon/app-icon.js +11 -1
  92. package/src/components/app-rail/app-rail.css +59 -79
  93. package/src/components/app-sidebar/app-sidebar.css +304 -168
  94. package/src/components/app-sidebar/app-sidebar.js +667 -46
  95. package/src/components/aurora/aurora.css +5 -3
  96. package/src/components/avatar/avatar.css +32 -7
  97. package/src/components/avatar/avatar.js +72 -8
  98. package/src/components/badge/badge.css +54 -2
  99. package/src/components/badge/badge.js +29 -2
  100. package/src/components/breadcrumb/breadcrumb.css +1 -1
  101. package/src/components/button/button.css +67 -9
  102. package/src/components/button/button.js +38 -0
  103. package/src/components/calendar/calendar.css +47 -47
  104. package/src/components/calendar/calendar.js +26 -52
  105. package/src/components/card/card.css +4 -4
  106. package/src/components/card-view/card-view.css +14 -12
  107. package/src/components/card-view/card-view.js +13 -9
  108. package/src/components/card-view/record-card.js +14 -3
  109. package/src/components/chart/chart.css +4 -1
  110. package/src/components/chart/chart.js +12 -0
  111. package/src/components/check-button/check-button.css +10 -2
  112. package/src/components/checklist/checklist.css +9 -2
  113. package/src/components/checklist/checklist.js +11 -5
  114. package/src/components/checklist/field-adapter.js +3 -1
  115. package/src/components/code-editor/code-editor.css +7 -6
  116. package/src/components/code-editor/code-editor.js +19 -1
  117. package/src/components/code-editor/field-adapter.js +9 -2
  118. package/src/components/context-menu/context-menu.css +9 -4
  119. package/src/components/context-menu/context-menu.js +8 -2
  120. package/src/components/copy/copy-button.css +6 -0
  121. package/src/components/copy/copy-input.css +9 -4
  122. package/src/components/data-filter/data-filter.css +5 -4
  123. package/src/components/data-filter/data-filter.js +2 -2
  124. package/src/components/date-picker/date-picker.css +6 -6
  125. package/src/components/date-picker/date-range-picker.css +3 -3
  126. package/src/components/date-picker/time-picker.css +3 -3
  127. package/src/components/datebox/date-range-box.css +79 -2
  128. package/src/components/datebox/date-range-box.js +13 -2
  129. package/src/components/datebox/datebox.css +79 -2
  130. package/src/components/datebox/datebox.js +13 -2
  131. package/src/components/dialog/dialog.css +26 -0
  132. package/src/components/dialog/dialog.js +99 -17
  133. package/src/components/dock/dock.css +5 -4
  134. package/src/components/dropdown/dropdown.css +1 -1
  135. package/src/components/dropdown/dropdown.js +159 -72
  136. package/src/components/empty-state/empty-state.css +2 -2
  137. package/src/components/entity-ref/entity-ref.css +1 -1
  138. package/src/components/entity-ref/entity-ref.js +1 -1
  139. package/src/components/field/field.css +28 -9
  140. package/src/components/field/field.js +101 -29
  141. package/src/components/field-upload/field-upload.css +1 -1
  142. package/src/components/fieldset/external-adapter.js +363 -0
  143. package/src/components/fieldset/fieldset.css +5 -3
  144. package/src/components/fieldset/fieldset.js +38 -64
  145. package/src/components/file-item/file-item.js +144 -10
  146. package/src/components/file-list/file-list.js +144 -21
  147. package/src/components/filter/filter.css +86 -2
  148. package/src/components/filter/filter.js +307 -11
  149. package/src/components/filter-panel/filter-panel.css +1 -1
  150. package/src/components/filter-panel/filter-panel.js +149 -32
  151. package/src/components/finder/finder.css +16 -14
  152. package/src/components/form/form.css +5 -4
  153. package/src/components/form/form.js +11 -2
  154. package/src/components/grid/grid.css +1 -1
  155. package/src/components/groupbox/groupbox.css +1 -1
  156. package/src/components/kanban-view/kanban-card.js +11 -3
  157. package/src/components/kanban-view/kanban-view.css +42 -18
  158. package/src/components/kanban-view/kanban-view.js +9 -6
  159. package/src/components/launcher/launcher.css +108 -26
  160. package/src/components/launcher/launcher.js +530 -42
  161. package/src/components/list-toolbar/list-toolbar.css +13 -8
  162. package/src/components/list-toolbar/list-toolbar.js +40 -14
  163. package/src/components/master-panel/master-panel.css +2 -0
  164. package/src/components/master-panel/master-panel.js +0 -1
  165. package/src/components/menu-button/menu-button.css +72 -4
  166. package/src/components/menu-button/menu-button.js +160 -18
  167. package/src/components/message/message.css +33 -3
  168. package/src/components/message/message.js +264 -22
  169. package/src/components/modal/modal.css +1 -1
  170. package/src/components/modal/modal.js +83 -15
  171. package/src/components/module-bar/module-bar.css +486 -0
  172. package/src/components/module-bar/module-bar.js +1074 -0
  173. package/src/components/multi-value-editor/multi-value-editor.css +1 -1
  174. package/src/components/navigation-bar/navigation-bar.css +18 -9
  175. package/src/components/number-field/field-adapter.js +3 -1
  176. package/src/components/number-field/number-field.css +70 -0
  177. package/src/components/number-field/number-field.js +2 -0
  178. package/src/components/pagination/pagination.css +13 -11
  179. package/src/components/pagination/pagination.js +20 -4
  180. package/src/components/panel/panel.css +4 -3
  181. package/src/components/questionnaire/questionnaire.css +4 -4
  182. package/src/components/rating/field-adapter.js +2 -1
  183. package/src/components/rating/rating.css +8 -1
  184. package/src/components/search/search.css +4 -1
  185. package/src/components/select/color.js +22 -0
  186. package/src/components/select/field-adapter.js +2 -0
  187. package/src/components/select/glyphs.js +165 -0
  188. package/src/components/select/select.css +138 -45
  189. package/src/components/select/select.js +92 -47
  190. package/src/components/sheet/sheet.css +12 -9
  191. package/src/components/sheet/sheet.js +74 -32
  192. package/src/components/slider/field-adapter.js +6 -1
  193. package/src/components/slider/slider.css +18 -4
  194. package/src/components/slider/slider.js +1 -1
  195. package/src/components/sort-control/sort-control.css +4 -1
  196. package/src/components/split-view/split-view.css +1 -1
  197. package/src/components/stat-tile/stat-tile.css +42 -47
  198. package/src/components/stat-tile/stat-tile.js +17 -6
  199. package/src/components/stepper/stepper.css +1 -1
  200. package/src/components/tabbox/tabbox.css +41 -32
  201. package/src/components/tabbox/tabbox.js +5 -1
  202. package/src/components/table/table.css +187 -37
  203. package/src/components/table/table.js +718 -73
  204. package/src/components/tag-picker/field-adapter.js +2 -1
  205. package/src/components/tag-picker/tag-picker.css +83 -5
  206. package/src/components/tag-picker/tag-picker.js +25 -8
  207. package/src/components/timebox/timebox.css +22 -2
  208. package/src/components/toggle/toggle.css +12 -1
  209. package/src/components/toolbar/toolbar.js +2 -2
  210. package/src/components/tooltip/tooltip.css +4 -0
  211. package/src/components/tooltip/tooltip.js +44 -19
  212. package/src/components/tree/tree.css +26 -17
  213. package/src/components/tree/tree.js +31 -0
  214. package/src/components/value-list/value-list.css +3 -3
  215. package/src/components/view/record-view.css +1 -1
  216. package/src/components/view/record-view.js +178 -18
  217. package/src/components/view-settings/view-settings.css +285 -0
  218. package/src/components/view-settings/view-settings.js +1830 -0
  219. package/src/components/workspace-switcher/workspace-switcher.css +188 -0
  220. package/src/components/workspace-switcher/workspace-switcher.js +463 -0
  221. package/src/core/breakpoint.js +1 -1
  222. package/src/core/component.js +88 -17
  223. package/src/core/fontawesome.js +5 -1
  224. package/src/core/i18n.js +47 -4
  225. package/src/core/icons.js +204 -61
  226. package/src/core/keyboard.js +206 -11
  227. package/src/core/messages.js +427 -0
  228. package/src/core/motion.js +147 -0
  229. package/src/core/overlay-host.js +77 -3
  230. package/src/core/overlay-stack.js +487 -0
  231. package/src/core/position.js +22 -3
  232. package/src/index.js +10 -5
  233. package/src/internal/app-rail.js +135 -55
  234. package/src/internal/menu-items.js +61 -3
  235. package/src/zeyos/connect.js +6 -2
  236. package/src/zeyos/form.js +69 -27
  237. package/src/zeyos/index.js +4 -1
  238. package/src/zeyos/launcher.js +8 -3
  239. package/src/zeyos/module-bar.js +181 -0
  240. package/src/zeyos/query.js +197 -13
  241. package/src/zeyos/schema.js +144 -27
  242. package/src/zeyos/table.js +287 -84
  243. package/src/zeyos/view.js +49 -93
  244. package/styles/base.css +72 -1
  245. package/styles/icons.css +11 -1
  246. package/styles/print.css +1 -1
  247. package/styles/tokens/dark.css +117 -37
  248. package/styles/tokens/global.css +121 -27
  249. package/styles/tokens/semantic.css +140 -43
  250. package/styles/tokens/themes.css +7 -6
  251. package/styles/zx.css +3 -1
  252. package/styles/tokens/density.css +0 -9
package/src/zeyos/view.js CHANGED
@@ -1,8 +1,6 @@
1
- import { buildListQuery } from './query.js';
2
1
  import { connect } from './connect.js';
3
- import { normalizeZeyosListResult } from './select.js';
4
2
  import { createSavedViewRegistry } from './saved-views.js';
5
- import { buildZeyosTableConfig } from './table.js';
3
+ import { buildZeyosTableConfig, createServerPager } from './table.js';
6
4
 
7
5
  /** @typedef {import('../components/view/record-view.js').ViewField} ViewField */
8
6
  /** @typedef {import('../components/view/record-view.js').ViewSort} ViewSort */
@@ -26,9 +24,14 @@ import { buildZeyosTableConfig } from './table.js';
26
24
  * @property {string[]} [fields] Curated ordered schema field allow-list.
27
25
  * @property {string[]} [exclude] Schema fields to omit.
28
26
  * @property {Record<string, string>} [labels] Per-field label overrides.
27
+ * @property {Record<string, string>} [formats] Per-field semantic format overrides, such as
28
+ * `{ duedate: 'date' }` for a Unix-second field that holds a calendar day.
29
+ * @property {string} [timeZone] IANA time zone of the ZeyOS instance; date-only fields show the
30
+ * calendar day their stored midnight names in it. Defaults to the runtime's own zone.
29
31
  * @property {Record<string, Partial<ViewField>>} [fieldOverrides] View descriptor overrides.
30
32
  * @property {string|((record:Record<string,unknown>)=>unknown)} [recordId='ID'] Record id accessor.
31
- * @property {number} [pageSize=50] Server page size.
33
+ * @property {number} [pageSize=50] Server page size, a positive integer — the same default and
34
+ * validation as `zeyosTable()`, because both bindings page through one shared loader.
32
35
  * @property {ViewSort|null} [sort=null] Initial server sort.
33
36
  * @property {Record<string, unknown>} [filters] Initial ZeyOS predicates.
34
37
  * @property {string} [search=''] Initial full-text query.
@@ -58,7 +61,10 @@ import { buildZeyosTableConfig } from './table.js';
58
61
  * @typedef {Object} ZeyosViewLoadOptions
59
62
  * @property {string} [search] Replacement full-text query.
60
63
  * @property {Record<string, unknown>} [filters] Replacement predicates.
61
- * @property {number} [page=0] Zero-based page; pages above zero append.
64
+ * @property {number} [page=0] Zero-based page, a non-negative integer; pages above zero append
65
+ * unless `replace` is set.
66
+ * @property {boolean} [replace] Replace the records with this page instead of appending it.
67
+ * @property {number} [pageSize] New page size for this and every later load.
62
68
  */
63
69
 
64
70
  /**
@@ -102,6 +108,7 @@ import { buildZeyosTableConfig } from './table.js';
102
108
  * @property {()=>Promise<ZeyosViewLoadResult>} loadMore Loads the next page when available.
103
109
  * @property {number|null} count Current server count.
104
110
  * @property {number} page Current zero-based page.
111
+ * @property {number} pageSize Current server page size.
105
112
  * @property {boolean} hasMore Whether another page is available.
106
113
  * @property {Record<string,any>|null} savedViews Saved-view registry when configured.
107
114
  * @property {Promise<SavedViewApplyResult|null>} ready Default restoration completed before loads.
@@ -134,6 +141,8 @@ export function buildZeyosViewConfig(client, resource, opts = {}) {
134
141
  const table = buildZeyosTableConfig(client, resource, {
135
142
  fields: requested,
136
143
  labels: opts.labels,
144
+ formats: opts.formats,
145
+ timeZone: opts.timeZone,
137
146
  rowId: opts.recordId ?? 'ID',
138
147
  sort: opts.sort ?? null
139
148
  });
@@ -192,7 +201,17 @@ export function zeyosView(client, resource, View, opts = {}) {
192
201
  }
193
202
  }
194
203
  const facade = connect(client);
195
- const pageSize = normalizePageSize(opts.pageSize);
204
+ let pager;
205
+ try {
206
+ pager = createServerPager({
207
+ client, facade, resource, projection: config.projection, target: view,
208
+ pageSize: opts.pageSize, sort: opts.sort ?? null, filters: opts.filters ?? {}, search: opts.search,
209
+ searchFields: opts.searchFields, label: 'ZeyOS view'
210
+ });
211
+ } catch (error) {
212
+ view.destroy();
213
+ throw error;
214
+ }
196
215
  let saved;
197
216
  try {
198
217
  saved = resolveSavedViews(opts.savedViews, View, resource);
@@ -211,50 +230,8 @@ export function zeyosView(client, resource, View, opts = {}) {
211
230
  }
212
231
  }
213
232
  }
214
- let currentSort = opts.sort ?? null;
215
- let currentFilters = copyFilters(opts.filters ?? {});
216
- let currentSearch = String(opts.search ?? '');
217
- let currentPage = 0;
218
- let totalCount = null;
219
- let more = false;
220
- let requestSequence = 0;
221
233
  let destroyed = false;
222
-
223
- const performLoad = async (options = {}) => {
224
- if (destroyed) throw new Error('ZeyOS view binding has been destroyed');
225
- if (Object.prototype.hasOwnProperty.call(options, 'search')) currentSearch = String(options.search ?? '');
226
- if (Object.prototype.hasOwnProperty.call(options, 'filters')) currentFilters = copyFilters(options.filters ?? {});
227
- const page = normalizePage(options.page ?? 0);
228
- const query = buildListQuery({
229
- fields: config.projection,
230
- sort: currentSort,
231
- filters: currentFilters,
232
- search: currentSearch,
233
- searchFields: opts.searchFields,
234
- limit: pageSize,
235
- offset: page * pageSize,
236
- count: true
237
- });
238
- const sequence = ++requestSequence;
239
- view.setLoading(true);
240
- try {
241
- const normalized = normalizeZeyosListResult(client, await facade.list(resource, query));
242
- const count = normalized.count ?? null;
243
- const hasMore = count == null
244
- ? normalized.data.length === pageSize
245
- : page * pageSize + normalized.data.length < count;
246
- if (!destroyed && sequence === requestSequence) {
247
- currentPage = page;
248
- totalCount = count;
249
- more = hasMore;
250
- if (page === 0) view.setData(normalized.data);
251
- else view.addData(normalized.data);
252
- }
253
- return { data: normalized.data, count, page, hasMore, query };
254
- } finally {
255
- if (!destroyed && sequence === requestSequence) view.setLoading(false);
256
- }
257
- };
234
+ const performLoad = pager.load;
258
235
 
259
236
  /** @param {string} idOrName @param {{load?:boolean}} [options={}] @returns {Promise<SavedViewApplyResult>} */
260
237
  const applySaved = async (idOrName, options = {}) => {
@@ -264,15 +241,12 @@ export function zeyosView(client, resource, View, opts = {}) {
264
241
  type: presentation,
265
242
  onQuery: async ({ filters, search }) => {
266
243
  if (destroyed) return;
267
- currentFilters = copyFilters(filters ?? {});
268
- currentSearch = String(search ?? '');
244
+ pager.setQuery({ filters: savedFilters(filters), search });
269
245
  }
270
246
  });
271
247
  if (!result.applied || destroyed) return result;
272
- currentSort = appliedViewSort(view, result.entry);
273
- currentPage = 0;
274
- totalCount = null;
275
- more = false;
248
+ pager.setSort(appliedViewSort(view, result.entry));
249
+ pager.reset();
276
250
  if (options.load !== false) await performLoad({ page: 0 });
277
251
  return result;
278
252
  };
@@ -326,6 +300,8 @@ export function zeyosView(client, resource, View, opts = {}) {
326
300
  };
327
301
 
328
302
  const load = async (options = {}) => {
303
+ // Rejected before saved-view initialization runs, so an invalid call has no side effect.
304
+ pager.check(options);
329
305
  await ensureInitialized({ load: false });
330
306
  return performLoad(options);
331
307
  };
@@ -340,8 +316,8 @@ export function zeyosView(client, resource, View, opts = {}) {
340
316
  name: String(source.name ?? ''),
341
317
  type: presentation,
342
318
  state: view.getViewState(),
343
- filters: copyFilters(currentFilters),
344
- search: currentSearch
319
+ filters: pager.filters,
320
+ search: pager.search
345
321
  };
346
322
  };
347
323
 
@@ -371,8 +347,9 @@ export function zeyosView(client, resource, View, opts = {}) {
371
347
  };
372
348
 
373
349
  const sortHandler = (event) => {
350
+ if (destroyed) return;
374
351
  const id = event.detail?.id;
375
- currentSort = id == null ? null : { id: String(id), dir: event.detail.dir === 'desc' ? 'desc' : 'asc' };
352
+ pager.setSort(id == null ? null : { id: String(id), dir: event.detail.dir === 'desc' ? 'desc' : 'asc' });
376
353
  void load({ page: 0 }).catch(() => { /* connect() already reported the API failure. */ });
377
354
  };
378
355
 
@@ -383,26 +360,12 @@ export function zeyosView(client, resource, View, opts = {}) {
383
360
  setFilters: (filters) => load({ filters, page: 0 }),
384
361
  loadMore: async () => {
385
362
  await ensureInitialized({ load: false });
386
- return more ? performLoad({ page: currentPage + 1 }) : {
387
- data: [],
388
- count: totalCount,
389
- page: currentPage,
390
- hasMore: false,
391
- query: buildListQuery({
392
- fields: config.projection,
393
- sort: currentSort,
394
- filters: currentFilters,
395
- search: currentSearch,
396
- searchFields: opts.searchFields,
397
- limit: pageSize,
398
- offset: currentPage * pageSize,
399
- count: true
400
- })
401
- };
363
+ return pager.loadMore();
402
364
  },
403
- get count() { return totalCount; },
404
- get page() { return currentPage; },
405
- get hasMore() { return more; },
365
+ get count() { return pager.count; },
366
+ get page() { return pager.page; },
367
+ get pageSize() { return pager.pageSize; },
368
+ get hasMore() { return pager.hasMore; },
406
369
  savedViews,
407
370
  ready,
408
371
  restoreDefault,
@@ -412,7 +375,7 @@ export function zeyosView(client, resource, View, opts = {}) {
412
375
  destroy: () => {
413
376
  if (destroyed) return;
414
377
  destroyed = true;
415
- requestSequence += 1;
378
+ pager.destroy();
416
379
  if (typeof view.off === 'function') view.off('sortchange', sortHandler);
417
380
  else view.removeEventListener?.('sortchange', sortHandler);
418
381
  if (saved?.owned) savedViews?.destroy?.();
@@ -450,21 +413,14 @@ function supplementalFieldIds(opts) {
450
413
  return [...new Set(ids)];
451
414
  }
452
415
 
453
- /** @param {unknown} value @returns {number} */
454
- function normalizePageSize(value) {
455
- const number = Number(value ?? 50);
456
- return Number.isFinite(number) ? Math.max(1, Math.floor(number)) : 50;
457
- }
458
-
459
- /** @param {unknown} value @returns {number} */
460
- function normalizePage(value) {
461
- const number = Number(value);
462
- return Number.isFinite(number) ? Math.max(0, Math.floor(number)) : 0;
463
- }
464
-
465
- /** @param {unknown} value @returns {Record<string, unknown>} */
466
- function copyFilters(value) {
467
- return value && typeof value === 'object' && !Array.isArray(value) ? { ...value } : {};
416
+ /**
417
+ * Filters restored from a saved view are persisted data, not a caller's argument: a malformed
418
+ * entry reads as no filters rather than failing the restore.
419
+ * @param {unknown} value Stored filters.
420
+ * @returns {Record<string, unknown>}
421
+ */
422
+ function savedFilters(value) {
423
+ return value && typeof value === 'object' && !Array.isArray(value) ? { .../** @type {Record<string, unknown>} */ (value) } : {};
468
424
  }
469
425
 
470
426
  /**
package/styles/base.css CHANGED
@@ -12,6 +12,11 @@
12
12
  color: var(--zx-color-text);
13
13
  font-family: var(--zx-font-sans);
14
14
  font-size: var(--zx-text-md);
15
+ /* Inter at 13–14px reads better a touch tight. `cv11` is Inter's single-storey a: at interface
16
+ sizes it is rounder and calmer than the double-storey form, and it tells a from o and e
17
+ apart at least as well. Fonts without the feature ignore it. */
18
+ font-feature-settings: "cv11";
19
+ letter-spacing: var(--zx-tracking-tight);
15
20
  line-height: 1.5;
16
21
  -webkit-font-smoothing: antialiased;
17
22
  scrollbar-gutter: stable;
@@ -27,6 +32,20 @@
27
32
  box-shadow: var(--zx-focus-ring);
28
33
  }
29
34
 
35
+ /* Forced colours (Windows high contrast) drop every box-shadow, so the accent ring disappears and
36
+ the outline is the only focus indicator left. Components therefore never set `outline: 0` or
37
+ `outline: none` on a focusable element — they make it transparent (`outline-color:
38
+ transparent`, plus `outline-offset: -2px` where the ring is inset) and this rule paints it in a
39
+ system colour. `tests/lint-tokens.js` rejects outline suppression outside a marked exception.
40
+ `!important` because a component's own, more specific `outline-color: transparent` would
41
+ otherwise survive on an element that opts out with `forced-color-adjust: none` (a current item
42
+ filled with Highlight). Offsets are left to the component, so inset rings stay inset. */
43
+ @media (forced-colors: active) {
44
+ .zx-scope :focus-visible {
45
+ outline: 2px solid Highlight !important;
46
+ }
47
+ }
48
+
30
49
  .zx-scope ::selection {
31
50
  background: var(--zx-color-accent);
32
51
  color: var(--zx-color-on-accent);
@@ -67,6 +86,41 @@
67
86
  background: var(--zx-color-bg-hover);
68
87
  }
69
88
 
89
+ /* Quiet fields. Inside `[data-zx-fields="quiet"]` — a property panel, an inspector, an inline
90
+ record — native text inputs, selects, and textareas drop their border and fill so the values
91
+ read as text, and show that they are editable on hover (the hover fill) and on focus (the
92
+ normal border, the control fill, and the focus ring). Read-only and disabled fields never
93
+ light up. Zero specificity, like the defaults above: a component that styles its own inner
94
+ input keeps doing so. Composite controls opt in through their own stylesheets. */
95
+ :where(.zx-scope[data-zx-fields="quiet"], .zx-scope [data-zx-fields="quiet"]) :where(
96
+ input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"],
97
+ [type="button"], [type="submit"], [type="reset"], [type="image"]),
98
+ select,
99
+ textarea
100
+ ) {
101
+ border-color: transparent;
102
+ background: transparent;
103
+ }
104
+
105
+ :where(.zx-scope[data-zx-fields="quiet"], .zx-scope [data-zx-fields="quiet"]) :where(
106
+ input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"],
107
+ [type="button"], [type="submit"], [type="reset"], [type="image"]),
108
+ select,
109
+ textarea
110
+ ):where(:hover:not(:focus, :disabled, [readonly])) {
111
+ background: var(--zx-color-bg-hover);
112
+ }
113
+
114
+ :where(.zx-scope[data-zx-fields="quiet"], .zx-scope [data-zx-fields="quiet"]) :where(
115
+ input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"],
116
+ [type="button"], [type="submit"], [type="reset"], [type="image"]),
117
+ select,
118
+ textarea
119
+ ):where(:focus:not([readonly])) {
120
+ border-color: var(--zx-color-border-control);
121
+ background: var(--zx-color-bg-control);
122
+ }
123
+
70
124
  /* Ghost icon button: a borderless, transparent hit target for small glyph actions
71
125
  (notification close, closable tab ×, field clear). Square, no chrome until hovered. */
72
126
  .zx-scope .zx-icon-btn {
@@ -89,7 +143,8 @@
89
143
  }
90
144
 
91
145
  .zx-scope .zx-icon-btn:focus-visible {
92
- outline: 0;
146
+ outline-color: transparent;
147
+ outline-offset: -2px;
93
148
  box-shadow: inset var(--zx-focus-ring);
94
149
  }
95
150
 
@@ -122,3 +177,19 @@
122
177
  transition-duration: 0.01ms !important;
123
178
  }
124
179
  }
180
+
181
+ /* Motion as a setting: the same stop inside any `data-zx-motion="reduced"` region, whatever the
182
+ operating system says (`tokens/global.css` zeroes the duration tokens there too). Only movement
183
+ stops — every transition and animation still runs to its end state, at once, and still fires its
184
+ end event, so a menu still opens and a toast still leaves; a spinner stops turning. There is no
185
+ value that re-enables motion inside a reduced region. */
186
+ [data-zx-motion="reduced"],
187
+ [data-zx-motion="reduced"] *,
188
+ [data-zx-motion="reduced"] *::before,
189
+ [data-zx-motion="reduced"] *::after,
190
+ [data-zx-motion="reduced"] *::backdrop {
191
+ scroll-behavior: auto !important;
192
+ animation-duration: 0.01ms !important;
193
+ animation-iteration-count: 1 !important;
194
+ transition-duration: 0.01ms !important;
195
+ }
package/styles/icons.css CHANGED
@@ -1,7 +1,14 @@
1
1
  /* Icons.
2
2
  Every icon `icon()` builds carries `.zx-icon`, whether it is one of the bundled inline SVG
3
3
  glyphs or a Font Awesome element, so the rules below (and component rules) style both. Font
4
- Awesome icons are sized by font-size and occupy exactly one em. */
4
+ Awesome icons are sized by font-size and occupy exactly one em.
5
+
6
+ The bundled glyphs are outlines: the `<svg>` carries `fill="none"`, `stroke="currentColor"`,
7
+ round caps and joins, and a stroke width in view-box units (1.75 of 24, never under one CSS
8
+ pixel), and the path inherits all of it. The width therefore scales with the box an icon is
9
+ drawn in and needs no `vector-effect`. Glyphs registered as `[viewBox, path]` pairs stay filled.
10
+ Paint is presentation attributes, so plain CSS on `.zx-icon` overrides it: `fill: currentColor`
11
+ turns an outline into its solid form (a set star, a liked heart). */
5
12
 
6
13
  .zx-icon {
7
14
  flex: none;
@@ -17,6 +24,9 @@ i.zx-icon {
17
24
 
18
25
  svg.zx-icon {
19
26
  vertical-align: middle;
27
+ /* A stroke centred on a path near the view-box edge reaches past it; small icons thicken the
28
+ line to stay at one pixel, so let it draw instead of clipping the outer half. */
29
+ overflow: visible;
20
30
  }
21
31
 
22
32
  /* ZeyOS identity hook. `moduleChip()` now delegates vessel geometry and material entirely to
package/styles/print.css CHANGED
@@ -115,7 +115,7 @@
115
115
 
116
116
  .zx-scope :focus,
117
117
  .zx-scope :focus-visible {
118
- outline: none;
118
+ outline: none; /* lint: outline-ok — printed pages have no focus to show */
119
119
  box-shadow: none;
120
120
  }
121
121
 
@@ -1,49 +1,95 @@
1
1
  /*
2
- * Tier-2 semantic tokens — dark theme: a near-black page, raised neutral surfaces, muted fills,
3
- * translucent white borders (10%) and inputs (15%), and restrained secondary text.
2
+ * Tier-2 semantic tokens — dark theme: a charcoal page lifted off black, a chrome tone and four
3
+ * surface steps above it, translucent white borders (9%) and inputs (14%), text softened to about
4
+ * 90% white, and restrained secondary text.
4
5
  *
5
- * The accent roles take the light end of the `--zx-accent-*` ramp (300/400/500) where the light
6
- * theme takes the dark end, so a preset that repoints the ramp lands correctly in both.
6
+ * The accent roles take the light end of the `--zx-accent-*` ramp (300/400/500) for text, marks,
7
+ * and the focus ring, where the light theme takes the dark end, so a preset that repoints the ramp
8
+ * lands correctly in both. The solid accent is the exception: the primary button keeps the 600 stop
9
+ * with white ink in both themes rather than turning into a bright 400 slab.
10
+ *
11
+ * Every role that mixes another theme-dependent role (hover and current mix the text colour, tones
12
+ * and status fills mix the surface) is restated here, because a custom property resolves where it
13
+ * is declared: inherited from the light block, it would carry light values into a dark region.
7
14
  *
8
15
  * The `[data-zx-theme="auto"]` block below repeats these assignments under a
9
16
  * `prefers-color-scheme` query; CSS has no way to share a declaration block across a media
10
- * boundary, so the two lists must be kept in sync.
17
+ * boundary, so the two lists must be kept in sync — `tests/unit/tokens.test.js` fails if they drift.
11
18
  */
12
19
  [data-zx-theme="dark"] {
13
20
  color-scheme: dark;
14
- --zx-color-bg-page: var(--zx-gray-950);
15
- --zx-color-bg-surface: var(--zx-gray-900);
16
- --zx-color-bg-raised: var(--zx-gray-800);
21
+ /* The ramp is lifted off black: page, chrome, surface, raised, and the overlay base ascend in
22
+ that order, each mixed from two Zinc stops so a tinted neutral ramp carries through. */
23
+ --zx-color-bg-page: color-mix(in srgb, var(--zx-gray-900) 80%, var(--zx-gray-800));
24
+ /* Chrome sits just above the page and below the canvas: as in light, the working area is the
25
+ brightest column and the navigation and inspector recede. */
26
+ --zx-color-bg-chrome: color-mix(in srgb, var(--zx-color-bg-page) 75%, var(--zx-color-bg-surface));
27
+ --zx-color-bg-surface: color-mix(in srgb, var(--zx-gray-900) 40%, var(--zx-gray-800));
28
+ --zx-color-bg-raised: color-mix(in srgb, var(--zx-gray-800) 90%, var(--zx-gray-700));
17
29
  --zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
18
- --zx-color-bg-muted: var(--zx-gray-800);
19
- --zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
20
- --zx-color-bg-selected: color-mix(in srgb, var(--zx-accent-400) 18%, var(--zx-gray-900));
30
+ --zx-color-bg-muted: var(--zx-color-bg-raised);
31
+ --zx-color-bg-hover: color-mix(in srgb, var(--zx-color-text) 5%, transparent);
32
+ --zx-color-bg-current: color-mix(in srgb, var(--zx-color-text) 9%, transparent);
33
+ /* Picked, not current: a tint light enough that muted text on it keeps 4.5:1 under every preset. */
34
+ --zx-color-bg-selected: color-mix(in srgb, var(--zx-accent-400) 13%, var(--zx-color-bg-surface));
21
35
  --zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
22
- --zx-color-overlay-base: color-mix(in srgb, var(--zx-color-bg-raised) 42%, var(--zx-color-bg-page));
36
+ --zx-color-overlay-base: color-mix(in srgb, var(--zx-gray-800) 60%, var(--zx-gray-700));
23
37
  --zx-color-overlay-backdrop: color-mix(in srgb, var(--zx-gray-950) 38%, transparent);
24
- --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
25
- --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
26
- --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
27
- --zx-color-text: var(--zx-gray-50);
38
+ --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 9%, transparent);
39
+ --zx-color-border-subtle: color-mix(in srgb, var(--zx-gray-0) 6%, transparent);
40
+ --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 24%, transparent);
41
+ --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 14%, transparent);
42
+ /* Text is softened off pure white (about 90%), secondary text sits near 63%. */
43
+ --zx-color-text: var(--zx-gray-200);
28
44
  --zx-color-text-muted: var(--zx-gray-400);
45
+ --zx-color-text-subtle: color-mix(in srgb, var(--zx-gray-500) 50%, var(--zx-gray-400));
29
46
  --zx-color-text-placeholder: var(--zx-gray-500);
30
47
  --zx-color-text-invert: var(--zx-gray-950);
31
48
  --zx-color-accent: var(--zx-accent-400);
32
49
  --zx-color-accent-hover: var(--zx-accent-300);
33
50
  --zx-color-accent-active: var(--zx-accent-500);
34
- --zx-color-accent-subtle: color-mix(in srgb, var(--zx-accent-400) 16%, var(--zx-gray-900));
51
+ --zx-color-accent-subtle: color-mix(in srgb, var(--zx-accent-400) 16%, var(--zx-color-bg-surface));
35
52
  --zx-color-on-accent: var(--zx-gray-950);
53
+ /* The primary button does not glow: it keeps the 600 stop and white ink, as in light. */
54
+ --zx-color-accent-solid: var(--zx-accent-600);
55
+ --zx-color-accent-solid-hover: var(--zx-accent-700);
56
+ --zx-color-accent-solid-active: color-mix(in srgb, var(--zx-accent-700) 82%, var(--zx-gray-950));
57
+ --zx-color-on-accent-solid: var(--zx-gray-0);
58
+ /* Danger's tint is a little lighter than the other statuses' so its ink keeps 4.5:1 on it. */
36
59
  --zx-color-danger: var(--zx-red-400);
37
- --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
60
+ --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 13%, var(--zx-color-bg-surface));
38
61
  --zx-color-warning: var(--zx-amber-400);
39
- --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
62
+ --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-color-bg-surface));
40
63
  --zx-color-success: var(--zx-green-400);
41
- --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
64
+ --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-color-bg-surface));
42
65
  --zx-color-info: var(--zx-blue-400);
43
- --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
66
+ --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-color-bg-surface));
67
+ --zx-color-tone-blue-bg: color-mix(in srgb, var(--zx-tone-blue-500) 20%, var(--zx-color-bg-surface));
68
+ --zx-color-tone-blue-fg: var(--zx-tone-blue-300);
69
+ --zx-color-tone-teal-bg: color-mix(in srgb, var(--zx-tone-teal-500) 20%, var(--zx-color-bg-surface));
70
+ --zx-color-tone-teal-fg: var(--zx-tone-teal-300);
71
+ --zx-color-tone-green-bg: color-mix(in srgb, var(--zx-tone-green-500) 20%, var(--zx-color-bg-surface));
72
+ --zx-color-tone-green-fg: var(--zx-tone-green-300);
73
+ --zx-color-tone-amber-bg: color-mix(in srgb, var(--zx-tone-amber-500) 20%, var(--zx-color-bg-surface));
74
+ --zx-color-tone-amber-fg: var(--zx-tone-amber-300);
75
+ --zx-color-tone-orange-bg: color-mix(in srgb, var(--zx-tone-orange-500) 20%, var(--zx-color-bg-surface));
76
+ --zx-color-tone-orange-fg: var(--zx-tone-orange-300);
77
+ --zx-color-tone-red-bg: color-mix(in srgb, var(--zx-tone-red-500) 20%, var(--zx-color-bg-surface));
78
+ --zx-color-tone-red-fg: var(--zx-tone-red-300);
79
+ --zx-color-tone-pink-bg: color-mix(in srgb, var(--zx-tone-pink-500) 20%, var(--zx-color-bg-surface));
80
+ --zx-color-tone-pink-fg: var(--zx-tone-pink-300);
81
+ --zx-color-tone-violet-bg: color-mix(in srgb, var(--zx-tone-violet-500) 20%, var(--zx-color-bg-surface));
82
+ --zx-color-tone-violet-fg: var(--zx-tone-violet-300);
83
+ --zx-color-tone-slate-bg: color-mix(in srgb, var(--zx-tone-slate-500) 20%, var(--zx-color-bg-surface));
84
+ --zx-color-tone-slate-fg: var(--zx-tone-slate-300);
44
85
  --zx-color-ring: var(--zx-color-accent);
45
86
  --zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
87
+ /* The surface contact shadow keeps the light value: on a dark canvas the border, not the shadow,
88
+ separates a resting surface, and a heavier shadow would read as a lifted one. */
89
+ --zx-surface-shadow: var(--zx-shadow-1);
46
90
  --zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
91
+ /* A shadow alone barely reads on a dark canvas, so the lifted item also gets a faint light rim. */
92
+ --zx-drag-shadow: 0 0 0 1px color-mix(in srgb, var(--zx-gray-0) 7%, transparent), 0 2px 6px -1px rgb(0 0 0 / 40%), 0 14px 32px -6px rgb(0 0 0 / 60%);
47
93
  --zx-header-bg: var(--zx-gray-900);
48
94
  --zx-header-text: var(--zx-gray-50);
49
95
  }
@@ -51,39 +97,73 @@
51
97
  @media (prefers-color-scheme: dark) {
52
98
  [data-zx-theme="auto"] {
53
99
  color-scheme: dark;
54
- --zx-color-bg-page: var(--zx-gray-950);
55
- --zx-color-bg-surface: var(--zx-gray-900);
56
- --zx-color-bg-raised: var(--zx-gray-800);
100
+ /* The ramp is lifted off black: page, chrome, surface, raised, and the overlay base ascend in
101
+ that order, each mixed from two Zinc stops so a tinted neutral ramp carries through. */
102
+ --zx-color-bg-page: color-mix(in srgb, var(--zx-gray-900) 80%, var(--zx-gray-800));
103
+ /* Chrome sits just above the page and below the canvas: as in light, the working area is the
104
+ brightest column and the navigation and inspector recede. */
105
+ --zx-color-bg-chrome: color-mix(in srgb, var(--zx-color-bg-page) 75%, var(--zx-color-bg-surface));
106
+ --zx-color-bg-surface: color-mix(in srgb, var(--zx-gray-900) 40%, var(--zx-gray-800));
107
+ --zx-color-bg-raised: color-mix(in srgb, var(--zx-gray-800) 90%, var(--zx-gray-700));
57
108
  --zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
58
- --zx-color-bg-muted: var(--zx-gray-800);
59
- --zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
60
- --zx-color-bg-selected: color-mix(in srgb, var(--zx-accent-400) 18%, var(--zx-gray-900));
109
+ --zx-color-bg-muted: var(--zx-color-bg-raised);
110
+ --zx-color-bg-hover: color-mix(in srgb, var(--zx-color-text) 5%, transparent);
111
+ --zx-color-bg-current: color-mix(in srgb, var(--zx-color-text) 9%, transparent);
112
+ --zx-color-bg-selected: color-mix(in srgb, var(--zx-accent-400) 13%, var(--zx-color-bg-surface));
61
113
  --zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
62
- --zx-color-overlay-base: color-mix(in srgb, var(--zx-color-bg-raised) 42%, var(--zx-color-bg-page));
114
+ --zx-color-overlay-base: color-mix(in srgb, var(--zx-gray-800) 60%, var(--zx-gray-700));
63
115
  --zx-color-overlay-backdrop: color-mix(in srgb, var(--zx-gray-950) 38%, transparent);
64
- --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
65
- --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
66
- --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
67
- --zx-color-text: var(--zx-gray-50);
116
+ --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 9%, transparent);
117
+ --zx-color-border-subtle: color-mix(in srgb, var(--zx-gray-0) 6%, transparent);
118
+ --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 24%, transparent);
119
+ --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 14%, transparent);
120
+ /* Text is softened off pure white (about 90%), secondary text sits near 63%. */
121
+ --zx-color-text: var(--zx-gray-200);
68
122
  --zx-color-text-muted: var(--zx-gray-400);
123
+ --zx-color-text-subtle: color-mix(in srgb, var(--zx-gray-500) 50%, var(--zx-gray-400));
69
124
  --zx-color-text-placeholder: var(--zx-gray-500);
70
125
  --zx-color-text-invert: var(--zx-gray-950);
71
126
  --zx-color-accent: var(--zx-accent-400);
72
127
  --zx-color-accent-hover: var(--zx-accent-300);
73
128
  --zx-color-accent-active: var(--zx-accent-500);
74
- --zx-color-accent-subtle: color-mix(in srgb, var(--zx-accent-400) 16%, var(--zx-gray-900));
129
+ --zx-color-accent-subtle: color-mix(in srgb, var(--zx-accent-400) 16%, var(--zx-color-bg-surface));
75
130
  --zx-color-on-accent: var(--zx-gray-950);
131
+ /* The primary button does not glow: it keeps the 600 stop and white ink, as in light. */
132
+ --zx-color-accent-solid: var(--zx-accent-600);
133
+ --zx-color-accent-solid-hover: var(--zx-accent-700);
134
+ --zx-color-accent-solid-active: color-mix(in srgb, var(--zx-accent-700) 82%, var(--zx-gray-950));
135
+ --zx-color-on-accent-solid: var(--zx-gray-0);
76
136
  --zx-color-danger: var(--zx-red-400);
77
- --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
137
+ --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 13%, var(--zx-color-bg-surface));
78
138
  --zx-color-warning: var(--zx-amber-400);
79
- --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
139
+ --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-color-bg-surface));
80
140
  --zx-color-success: var(--zx-green-400);
81
- --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
141
+ --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-color-bg-surface));
82
142
  --zx-color-info: var(--zx-blue-400);
83
- --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
143
+ --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-color-bg-surface));
144
+ --zx-color-tone-blue-bg: color-mix(in srgb, var(--zx-tone-blue-500) 20%, var(--zx-color-bg-surface));
145
+ --zx-color-tone-blue-fg: var(--zx-tone-blue-300);
146
+ --zx-color-tone-teal-bg: color-mix(in srgb, var(--zx-tone-teal-500) 20%, var(--zx-color-bg-surface));
147
+ --zx-color-tone-teal-fg: var(--zx-tone-teal-300);
148
+ --zx-color-tone-green-bg: color-mix(in srgb, var(--zx-tone-green-500) 20%, var(--zx-color-bg-surface));
149
+ --zx-color-tone-green-fg: var(--zx-tone-green-300);
150
+ --zx-color-tone-amber-bg: color-mix(in srgb, var(--zx-tone-amber-500) 20%, var(--zx-color-bg-surface));
151
+ --zx-color-tone-amber-fg: var(--zx-tone-amber-300);
152
+ --zx-color-tone-orange-bg: color-mix(in srgb, var(--zx-tone-orange-500) 20%, var(--zx-color-bg-surface));
153
+ --zx-color-tone-orange-fg: var(--zx-tone-orange-300);
154
+ --zx-color-tone-red-bg: color-mix(in srgb, var(--zx-tone-red-500) 20%, var(--zx-color-bg-surface));
155
+ --zx-color-tone-red-fg: var(--zx-tone-red-300);
156
+ --zx-color-tone-pink-bg: color-mix(in srgb, var(--zx-tone-pink-500) 20%, var(--zx-color-bg-surface));
157
+ --zx-color-tone-pink-fg: var(--zx-tone-pink-300);
158
+ --zx-color-tone-violet-bg: color-mix(in srgb, var(--zx-tone-violet-500) 20%, var(--zx-color-bg-surface));
159
+ --zx-color-tone-violet-fg: var(--zx-tone-violet-300);
160
+ --zx-color-tone-slate-bg: color-mix(in srgb, var(--zx-tone-slate-500) 20%, var(--zx-color-bg-surface));
161
+ --zx-color-tone-slate-fg: var(--zx-tone-slate-300);
84
162
  --zx-color-ring: var(--zx-color-accent);
85
163
  --zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
164
+ --zx-surface-shadow: var(--zx-shadow-1);
86
165
  --zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
166
+ --zx-drag-shadow: 0 0 0 1px color-mix(in srgb, var(--zx-gray-0) 7%, transparent), 0 2px 6px -1px rgb(0 0 0 / 40%), 0 14px 32px -6px rgb(0 0 0 / 60%);
87
167
  --zx-header-bg: var(--zx-gray-900);
88
168
  --zx-header-text: var(--zx-gray-50);
89
169
  }