@zeyos/zx 2.1.0 → 2.2.1

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 (311) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +15 -0
  3. package/dist/types/compat/base.d.ts +156 -0
  4. package/dist/types/compat/globals.d.ts +20 -0
  5. package/dist/types/compat/index.d.ts +128 -0
  6. package/dist/types/compat/map/basic.d.ts +175 -0
  7. package/dist/types/compat/map/data.d.ts +102 -0
  8. package/dist/types/compat/map/date-time.d.ts +80 -0
  9. package/dist/types/compat/map/factory.d.ts +9 -0
  10. package/dist/types/compat/map/form.d.ts +98 -0
  11. package/dist/types/compat/map/helpers.d.ts +12 -0
  12. package/dist/types/compat/map/http.d.ts +36 -0
  13. package/dist/types/compat/map/layout.d.ts +106 -0
  14. package/dist/types/compat/map/options.d.ts +80 -0
  15. package/dist/types/compat/map/select.d.ts +95 -0
  16. package/dist/types/compat/map/stubs.d.ts +32 -0
  17. package/dist/types/compat/map/utilities.d.ts +37 -0
  18. package/dist/types/compat-entry.d.ts +5 -0
  19. package/dist/types/components/badge/badge.d.ts +46 -0
  20. package/dist/types/components/breadcrumb/breadcrumb.d.ts +200 -0
  21. package/dist/types/components/button/button.d.ts +42 -0
  22. package/dist/types/components/check-button/check-button.d.ts +98 -0
  23. package/dist/types/components/checklist/checklist.d.ts +143 -0
  24. package/dist/types/components/checklist/field-adapter.d.ts +5 -0
  25. package/dist/types/components/context-menu/context-menu.d.ts +130 -0
  26. package/dist/types/components/copy/copy-button.d.ts +48 -0
  27. package/dist/types/components/copy/copy-input.d.ts +91 -0
  28. package/dist/types/components/data-filter/data-filter.d.ts +250 -0
  29. package/dist/types/components/data-filter/filter-core.d.ts +52 -0
  30. package/dist/types/components/date-picker/date-picker.d.ts +137 -0
  31. package/dist/types/components/date-picker/date-range-picker.d.ts +350 -0
  32. package/dist/types/components/date-picker/field-adapter.d.ts +6 -0
  33. package/dist/types/components/date-picker/month-picker.d.ts +75 -0
  34. package/dist/types/components/date-picker/range-field-adapter.d.ts +7 -0
  35. package/dist/types/components/date-picker/time-picker.d.ts +127 -0
  36. package/dist/types/components/datebox/date-range-box.d.ts +218 -0
  37. package/dist/types/components/datebox/datebox.d.ts +160 -0
  38. package/dist/types/components/datebox/field-adapter.d.ts +5 -0
  39. package/dist/types/components/dialog/dialog.d.ts +284 -0
  40. package/dist/types/components/dropdown/dropdown.d.ts +118 -0
  41. package/dist/types/components/empty-state/empty-state.d.ts +38 -0
  42. package/dist/types/components/field/field.d.ts +231 -0
  43. package/dist/types/components/field-upload/field-adapter.d.ts +5 -0
  44. package/dist/types/components/field-upload/field-upload.d.ts +213 -0
  45. package/dist/types/components/fieldset/fieldset.d.ts +125 -0
  46. package/dist/types/components/finder/finder.d.ts +252 -0
  47. package/dist/types/components/form/form.d.ts +194 -0
  48. package/dist/types/components/groupbox/groupbox.d.ts +89 -0
  49. package/dist/types/components/layout/layout.d.ts +132 -0
  50. package/dist/types/components/loading/inline-loading.d.ts +86 -0
  51. package/dist/types/components/loading/progress-bar.d.ts +168 -0
  52. package/dist/types/components/loading/spinner.d.ts +34 -0
  53. package/dist/types/components/master-panel/master-panel.d.ts +112 -0
  54. package/dist/types/components/menu-button/menu-button.d.ts +142 -0
  55. package/dist/types/components/message/message.d.ts +212 -0
  56. package/dist/types/components/modal/modal.d.ts +105 -0
  57. package/dist/types/components/multi-value-editor/field-adapter.d.ts +5 -0
  58. package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +66 -0
  59. package/dist/types/components/navigation-bar/navigation-bar.d.ts +229 -0
  60. package/dist/types/components/number-field/field-adapter.d.ts +5 -0
  61. package/dist/types/components/number-field/number-field.d.ts +292 -0
  62. package/dist/types/components/pagination/pagination.d.ts +267 -0
  63. package/dist/types/components/panel/panel.d.ts +194 -0
  64. package/dist/types/components/permission/permission.d.ts +93 -0
  65. package/dist/types/components/rating/field-adapter.d.ts +5 -0
  66. package/dist/types/components/rating/rating.d.ts +213 -0
  67. package/dist/types/components/search/search.d.ts +98 -0
  68. package/dist/types/components/select/field-adapter.d.ts +5 -0
  69. package/dist/types/components/select/filter.d.ts +11 -0
  70. package/dist/types/components/select/select.d.ts +235 -0
  71. package/dist/types/components/skeleton/skeleton.d.ts +97 -0
  72. package/dist/types/components/slider/field-adapter.d.ts +5 -0
  73. package/dist/types/components/slider/slider.d.ts +216 -0
  74. package/dist/types/components/split-view/split-view.d.ts +335 -0
  75. package/dist/types/components/stepper/stepper.d.ts +314 -0
  76. package/dist/types/components/stepper/steps.d.ts +131 -0
  77. package/dist/types/components/tabbox/tabbox.d.ts +230 -0
  78. package/dist/types/components/table/sort.d.ts +49 -0
  79. package/dist/types/components/table/table.d.ts +872 -0
  80. package/dist/types/components/tag-picker/field-adapter.d.ts +5 -0
  81. package/dist/types/components/tag-picker/tag-picker.d.ts +375 -0
  82. package/dist/types/components/timebox/field-adapter.d.ts +5 -0
  83. package/dist/types/components/timebox/timebox.d.ts +121 -0
  84. package/dist/types/components/toggle/field-adapter.d.ts +5 -0
  85. package/dist/types/components/toggle/toggle.d.ts +94 -0
  86. package/dist/types/components/toolbar/toolbar.d.ts +230 -0
  87. package/dist/types/components/tooltip/tooltip.d.ts +183 -0
  88. package/dist/types/components/tree/hierarchy.d.ts +113 -0
  89. package/dist/types/components/tree/tree.d.ts +383 -0
  90. package/dist/types/components/truncate/truncate.d.ts +61 -0
  91. package/dist/types/components/value-list/field-adapter.d.ts +5 -0
  92. package/dist/types/components/value-list/value-list.d.ts +143 -0
  93. package/dist/types/core/breakpoint.d.ts +68 -0
  94. package/dist/types/core/component.d.ts +115 -0
  95. package/dist/types/core/date.d.ts +50 -0
  96. package/dist/types/core/dom.d.ts +86 -0
  97. package/dist/types/core/export.d.ts +70 -0
  98. package/dist/types/core/fontawesome.d.ts +107 -0
  99. package/dist/types/core/format.d.ts +107 -0
  100. package/dist/types/core/http.d.ts +122 -0
  101. package/dist/types/core/i18n.d.ts +35 -0
  102. package/dist/types/core/icons.d.ts +137 -0
  103. package/dist/types/core/keyboard.d.ts +72 -0
  104. package/dist/types/core/position.d.ts +45 -0
  105. package/dist/types/core/storage.d.ts +46 -0
  106. package/dist/types/core/util.d.ts +117 -0
  107. package/dist/types/elements/define.d.ts +73 -0
  108. package/dist/types/elements/reflect.d.ts +27 -0
  109. package/dist/types/index.d.ts +79 -0
  110. package/dist/types/zeyos/connect.d.ts +65 -0
  111. package/dist/types/zeyos/form.d.ts +140 -0
  112. package/dist/types/zeyos/icons.d.ts +104 -0
  113. package/dist/types/zeyos/index.d.ts +12 -0
  114. package/dist/types/zeyos/modules.d.ts +110 -0
  115. package/dist/types/zeyos/query.d.ts +157 -0
  116. package/dist/types/zeyos/schema.d.ts +79 -0
  117. package/dist/types/zeyos/select.d.ts +167 -0
  118. package/dist/types/zeyos/table.d.ts +205 -0
  119. package/dist/zx-compat.esm.js +375 -39
  120. package/dist/zx-compat.esm.min.js +1 -1
  121. package/dist/zx-compat.global.js +372 -73
  122. package/dist/zx-compat.global.min.js +3 -3
  123. package/dist/zx-zeyos.esm.js +355 -49
  124. package/dist/zx-zeyos.esm.min.js +1 -1
  125. package/dist/zx.css +68 -6
  126. package/dist/zx.esm.js +359 -73
  127. package/dist/zx.esm.min.js +3 -3
  128. package/dist/zx.global.js +359 -73
  129. package/dist/zx.global.min.js +3 -3
  130. package/dist/zx.min.css +1 -1
  131. package/docs/api.json +48 -2
  132. package/docs/llms.md +31 -0
  133. package/package.json +37 -9
  134. package/src/compat/base.js +291 -0
  135. package/src/compat/globals.js +165 -0
  136. package/src/compat/index.js +84 -0
  137. package/src/compat/map/basic.js +464 -0
  138. package/src/compat/map/data.js +232 -0
  139. package/src/compat/map/date-time.js +177 -0
  140. package/src/compat/map/factory.js +45 -0
  141. package/src/compat/map/form.js +330 -0
  142. package/src/compat/map/helpers.js +46 -0
  143. package/src/compat/map/http.js +117 -0
  144. package/src/compat/map/layout.js +256 -0
  145. package/src/compat/map/options.js +267 -0
  146. package/src/compat/map/select.js +198 -0
  147. package/src/compat/map/stubs.js +26 -0
  148. package/src/compat/map/utilities.js +113 -0
  149. package/src/compat-entry.js +11 -0
  150. package/src/components/badge/badge.css +147 -0
  151. package/src/components/badge/badge.js +92 -0
  152. package/src/components/breadcrumb/breadcrumb.css +105 -0
  153. package/src/components/breadcrumb/breadcrumb.js +331 -0
  154. package/src/components/button/button.css +104 -0
  155. package/src/components/button/button.js +76 -0
  156. package/src/components/check-button/check-button.css +66 -0
  157. package/src/components/check-button/check-button.js +167 -0
  158. package/src/components/checklist/checklist.css +65 -0
  159. package/src/components/checklist/checklist.js +282 -0
  160. package/src/components/checklist/field-adapter.js +46 -0
  161. package/src/components/context-menu/context-menu.css +54 -0
  162. package/src/components/context-menu/context-menu.js +334 -0
  163. package/src/components/copy/copy-button.css +27 -0
  164. package/src/components/copy/copy-button.js +78 -0
  165. package/src/components/copy/copy-input.css +59 -0
  166. package/src/components/copy/copy-input.js +123 -0
  167. package/src/components/data-filter/data-filter.css +53 -0
  168. package/src/components/data-filter/data-filter.js +400 -0
  169. package/src/components/data-filter/filter-core.js +128 -0
  170. package/src/components/date-picker/date-picker.css +181 -0
  171. package/src/components/date-picker/date-picker.js +500 -0
  172. package/src/components/date-picker/date-range-picker.css +264 -0
  173. package/src/components/date-picker/date-range-picker.js +990 -0
  174. package/src/components/date-picker/field-adapter.js +36 -0
  175. package/src/components/date-picker/month-picker.js +223 -0
  176. package/src/components/date-picker/range-field-adapter.js +31 -0
  177. package/src/components/date-picker/time-picker.css +191 -0
  178. package/src/components/date-picker/time-picker.js +406 -0
  179. package/src/components/datebox/date-range-box.css +128 -0
  180. package/src/components/datebox/date-range-box.js +492 -0
  181. package/src/components/datebox/datebox.css +108 -0
  182. package/src/components/datebox/datebox.js +358 -0
  183. package/src/components/datebox/field-adapter.js +34 -0
  184. package/src/components/dialog/dialog.css +74 -0
  185. package/src/components/dialog/dialog.js +450 -0
  186. package/src/components/dropdown/dropdown.css +24 -0
  187. package/src/components/dropdown/dropdown.js +288 -0
  188. package/src/components/empty-state/empty-state.css +80 -0
  189. package/src/components/empty-state/empty-state.js +92 -0
  190. package/src/components/field/field.css +127 -0
  191. package/src/components/field/field.js +605 -0
  192. package/src/components/field-upload/field-adapter.js +21 -0
  193. package/src/components/field-upload/field-upload.css +108 -0
  194. package/src/components/field-upload/field-upload.js +475 -0
  195. package/src/components/fieldset/fieldset.css +37 -0
  196. package/src/components/fieldset/fieldset.js +307 -0
  197. package/src/components/finder/finder.css +98 -0
  198. package/src/components/finder/finder.js +509 -0
  199. package/src/components/form/form.css +32 -0
  200. package/src/components/form/form.js +302 -0
  201. package/src/components/groupbox/groupbox.css +51 -0
  202. package/src/components/groupbox/groupbox.js +199 -0
  203. package/src/components/layout/layout.css +117 -0
  204. package/src/components/layout/layout.js +136 -0
  205. package/src/components/loading/inline-loading.css +34 -0
  206. package/src/components/loading/inline-loading.js +140 -0
  207. package/src/components/loading/progress-bar.css +115 -0
  208. package/src/components/loading/progress-bar.js +259 -0
  209. package/src/components/loading/spinner.css +58 -0
  210. package/src/components/loading/spinner.js +57 -0
  211. package/src/components/master-panel/master-panel.css +51 -0
  212. package/src/components/master-panel/master-panel.js +203 -0
  213. package/src/components/menu-button/menu-button.css +49 -0
  214. package/src/components/menu-button/menu-button.js +294 -0
  215. package/src/components/message/message.css +122 -0
  216. package/src/components/message/message.js +499 -0
  217. package/src/components/modal/modal.css +47 -0
  218. package/src/components/modal/modal.js +203 -0
  219. package/src/components/multi-value-editor/field-adapter.js +44 -0
  220. package/src/components/multi-value-editor/multi-value-editor.css +56 -0
  221. package/src/components/multi-value-editor/multi-value-editor.js +170 -0
  222. package/src/components/navigation-bar/navigation-bar.css +130 -0
  223. package/src/components/navigation-bar/navigation-bar.js +450 -0
  224. package/src/components/number-field/field-adapter.js +40 -0
  225. package/src/components/number-field/number-field.css +77 -0
  226. package/src/components/number-field/number-field.js +545 -0
  227. package/src/components/pagination/pagination.css +95 -0
  228. package/src/components/pagination/pagination.js +481 -0
  229. package/src/components/panel/panel.css +123 -0
  230. package/src/components/panel/panel.js +336 -0
  231. package/src/components/permission/permission.css +47 -0
  232. package/src/components/permission/permission.js +198 -0
  233. package/src/components/rating/field-adapter.js +34 -0
  234. package/src/components/rating/rating.css +97 -0
  235. package/src/components/rating/rating.js +395 -0
  236. package/src/components/search/search.css +70 -0
  237. package/src/components/search/search.js +193 -0
  238. package/src/components/select/field-adapter.js +24 -0
  239. package/src/components/select/filter.js +39 -0
  240. package/src/components/select/select.css +180 -0
  241. package/src/components/select/select.js +663 -0
  242. package/src/components/skeleton/skeleton.css +76 -0
  243. package/src/components/skeleton/skeleton.js +139 -0
  244. package/src/components/slider/field-adapter.js +36 -0
  245. package/src/components/slider/slider.css +181 -0
  246. package/src/components/slider/slider.js +399 -0
  247. package/src/components/split-view/split-view.css +139 -0
  248. package/src/components/split-view/split-view.js +806 -0
  249. package/src/components/stepper/stepper.css +234 -0
  250. package/src/components/stepper/stepper.js +459 -0
  251. package/src/components/stepper/steps.js +131 -0
  252. package/src/components/tabbox/tabbox.css +281 -0
  253. package/src/components/tabbox/tabbox.js +484 -0
  254. package/src/components/table/sort.js +85 -0
  255. package/src/components/table/table.css +364 -0
  256. package/src/components/table/table.js +1711 -0
  257. package/src/components/tag-picker/field-adapter.js +35 -0
  258. package/src/components/tag-picker/tag-picker.css +169 -0
  259. package/src/components/tag-picker/tag-picker.js +837 -0
  260. package/src/components/timebox/field-adapter.js +24 -0
  261. package/src/components/timebox/timebox.css +51 -0
  262. package/src/components/timebox/timebox.js +276 -0
  263. package/src/components/toggle/field-adapter.js +24 -0
  264. package/src/components/toggle/toggle.css +66 -0
  265. package/src/components/toggle/toggle.js +150 -0
  266. package/src/components/toolbar/toolbar.css +81 -0
  267. package/src/components/toolbar/toolbar.js +511 -0
  268. package/src/components/tooltip/tooltip.css +36 -0
  269. package/src/components/tooltip/tooltip.js +420 -0
  270. package/src/components/tree/hierarchy.js +151 -0
  271. package/src/components/tree/tree.css +99 -0
  272. package/src/components/tree/tree.js +784 -0
  273. package/src/components/truncate/truncate.css +20 -0
  274. package/src/components/truncate/truncate.js +92 -0
  275. package/src/components/value-list/field-adapter.js +24 -0
  276. package/src/components/value-list/value-list.css +108 -0
  277. package/src/components/value-list/value-list.js +336 -0
  278. package/src/core/breakpoint.js +150 -0
  279. package/src/core/component.js +292 -0
  280. package/src/core/date.js +216 -0
  281. package/src/core/dom.js +260 -0
  282. package/src/core/export.js +204 -0
  283. package/src/core/fontawesome.js +177 -0
  284. package/src/core/format.js +283 -0
  285. package/src/core/http.js +246 -0
  286. package/src/core/i18n.js +83 -0
  287. package/src/core/icons.js +283 -0
  288. package/src/core/keyboard.js +240 -0
  289. package/src/core/position.js +177 -0
  290. package/src/core/storage.js +175 -0
  291. package/src/core/util.js +336 -0
  292. package/src/elements/define.js +715 -0
  293. package/src/elements/reflect.js +79 -0
  294. package/src/index.js +131 -0
  295. package/src/zeyos/connect.js +142 -0
  296. package/src/zeyos/form.js +254 -0
  297. package/src/zeyos/icons.js +92 -0
  298. package/src/zeyos/index.js +21 -0
  299. package/src/zeyos/modules.js +269 -0
  300. package/src/zeyos/query.js +199 -0
  301. package/src/zeyos/schema.js +474 -0
  302. package/src/zeyos/select.js +175 -0
  303. package/src/zeyos/table.js +272 -0
  304. package/styles/base.css +124 -0
  305. package/styles/icons.css +34 -0
  306. package/styles/tokens/dark.css +84 -0
  307. package/styles/tokens/density.css +9 -0
  308. package/styles/tokens/global.css +80 -0
  309. package/styles/tokens/modules.css +109 -0
  310. package/styles/tokens/semantic.css +49 -0
  311. package/styles/zx.css +61 -0
@@ -0,0 +1,272 @@
1
+ import { Table } from '../index.js';
2
+ import { connect } from './connect.js';
3
+ import { buildListQuery } from './query.js';
4
+ import { fieldToZxColumn, resolveFields } from './schema.js';
5
+ import { normalizeZeyosListResult } from './select.js';
6
+
7
+ /**
8
+ * @typedef {Object} ZeyosTableOptions
9
+ * @property {string[]} [fields] Curated ordered field allow-list.
10
+ * @property {Record<string, string>} [labels] Per-field label overrides.
11
+ * @property {string|((row: Record<string, unknown>) => unknown)} [rowId='ID'] Row id accessor.
12
+ * @property {number} [pageSize=50] Server page size.
13
+ * @property {{id: string, dir: 'asc'|'desc'}|null} [sort=null] Initial server sort.
14
+ * @property {Record<string, unknown>} [filters] Initial ZeyOS predicates.
15
+ * @property {string} [search=''] Initial full-text query.
16
+ * @property {false|'single'|'multi'} [selectable=false] Row selection mode.
17
+ * @property {number|string|null} [height=null] Table scroll-region height.
18
+ * @property {(row: Record<string, unknown>, event: CustomEvent<Record<string, unknown>>) => void} [onRowClick] Row activation callback.
19
+ */
20
+
21
+ /**
22
+ * @typedef {Object} ZeyosTableConfig
23
+ * @property {Record<string, any>[]} fieldMeta Ordered normalized schema metadata.
24
+ * @property {Record<string, any>[]} columns Generated Zx columns.
25
+ * @property {Record<string, string>} projection API projection including row ids/entity labels.
26
+ * @property {Record<string, any>} tableOptions Plain Zx Table options.
27
+ */
28
+
29
+ /**
30
+ * @typedef {Object} ZeyosTableLoadOptions
31
+ * @property {string} [search] Replacement full-text query.
32
+ * @property {Record<string, unknown>} [filters] Replacement ZeyOS predicates.
33
+ * @property {number} [page=0] Zero-based page; pages above zero append rows.
34
+ */
35
+
36
+ /**
37
+ * @typedef {Object} ZeyosTableLoadResult
38
+ * @property {Record<string, unknown>[]} data Loaded page rows.
39
+ * @property {number|null} count Server count when supplied.
40
+ * @property {number} page Loaded zero-based page.
41
+ * @property {boolean} hasMore Whether another page is available.
42
+ * @property {Record<string, unknown>} query Request passed to the list operation.
43
+ */
44
+
45
+ /**
46
+ * @typedef {Object} ZeyosTableBinding
47
+ * @property {Table} table Generated Zx table.
48
+ * @property {(options?: ZeyosTableLoadOptions) => Promise<ZeyosTableLoadResult>} load Loads/reloads a server page.
49
+ * @property {(search: string) => Promise<ZeyosTableLoadResult>} setSearch Replaces search and reloads page zero.
50
+ * @property {(filters: Record<string, unknown>) => Promise<ZeyosTableLoadResult>} setFilters Replaces predicates and reloads page zero.
51
+ * @property {() => Promise<ZeyosTableLoadResult>} loadMore Appends the next page when available.
52
+ * @property {number|null} count Current server count.
53
+ * @property {number} page Current zero-based page.
54
+ * @property {boolean} hasMore Whether another page is available.
55
+ * @property {() => void} destroy Destroys the generated table.
56
+ */
57
+
58
+ /**
59
+ * Builds the DOM-free schema-derived columns and Table options used by {@link zeyosTable}. Entity
60
+ * projections include an `<field>_label` alias from a real label field on the referenced resource.
61
+ * Amount fields use each row's real `currency` value for display while retaining the WP14 typed
62
+ * column strategy and right alignment.
63
+ * @param {Record<string, any>} client Injected ZeyOS client instance.
64
+ * @param {string} resource Resource name such as `transactions`.
65
+ * @param {ZeyosTableOptions} [opts={}] Schema, table, and initial query options.
66
+ * @returns {ZeyosTableConfig} Plain columns, projection, and Table options.
67
+ */
68
+ export function buildZeyosTableConfig(client, resource, opts = {}) {
69
+ const fieldMeta = resolveFields(client, resource, {
70
+ fields: opts.fields,
71
+ labels: opts.labels
72
+ });
73
+ const projection = {};
74
+ const columns = fieldMeta.map((sourceMeta) => {
75
+ const meta = { ...sourceMeta };
76
+ const referencedResource = referencedResourceFor(meta);
77
+ if (referencedResource) {
78
+ const labelKey = inferLabelKey(client, referencedResource);
79
+ meta.labelField = `${meta.id}_label`;
80
+ projection[meta.labelField] = `${meta.id}.${labelKey}`;
81
+ }
82
+ projection[meta.id] = meta.id;
83
+
84
+ const monetary = isMonetaryField(meta);
85
+ const column = fieldToZxColumn(monetary ? { ...meta, format: 'money' } : meta);
86
+ if (monetary) {
87
+ column.render = (row) => formatCurrency(row?.[meta.id], row?.currency);
88
+ if (schemaHasField(client, resource, 'currency')) projection.currency = 'currency';
89
+ }
90
+ return column;
91
+ });
92
+
93
+ const rowId = opts.rowId ?? 'ID';
94
+ if (typeof rowId === 'string' && !Object.prototype.hasOwnProperty.call(projection, rowId)) {
95
+ projection[rowId] = rowId;
96
+ }
97
+ return {
98
+ fieldMeta,
99
+ columns,
100
+ projection,
101
+ tableOptions: {
102
+ columns,
103
+ data: [],
104
+ rowId,
105
+ sort: opts.sort ?? null,
106
+ sortMode: 'server',
107
+ selectable: opts.selectable ?? false,
108
+ height: opts.height ?? null,
109
+ onrowclick: typeof opts.onRowClick === 'function'
110
+ ? (event) => opts.onRowClick(event.detail.row, event)
111
+ : undefined
112
+ }
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Generates a server-backed Zx Table. Sorting automatically reloads page zero. `load({page: 0})`
118
+ * replaces data, higher pages append it, and `loadMore()` uses `limit`/`offset` plus the returned
119
+ * count. DataFilter callers can map state with `dataFilterStateToFilters` before `setFilters()`.
120
+ * @param {Record<string, any>} client Injected ZeyOS client instance.
121
+ * @param {string} resource Resource name such as `transactions`.
122
+ * @param {ZeyosTableOptions} [opts={}] Schema, table, and initial query options.
123
+ * @returns {ZeyosTableBinding} Generated table and server-state methods/getters.
124
+ */
125
+ export function zeyosTable(client, resource, opts = {}) {
126
+ const config = buildZeyosTableConfig(client, resource, opts);
127
+ const facade = connect(client);
128
+ const table = new Table(null, config.tableOptions);
129
+ const pageSize = normalizePageSize(opts.pageSize);
130
+ let currentSort = opts.sort ?? null;
131
+ let currentFilters = copyFilters(opts.filters ?? {});
132
+ let currentSearch = String(opts.search ?? '');
133
+ let currentPage = 0;
134
+ let totalCount = null;
135
+ let more = false;
136
+ let requestSequence = 0;
137
+
138
+ const load = async (options = {}) => {
139
+ if (Object.prototype.hasOwnProperty.call(options, 'search')) currentSearch = String(options.search ?? '');
140
+ if (Object.prototype.hasOwnProperty.call(options, 'filters')) currentFilters = copyFilters(options.filters ?? {});
141
+ const page = normalizePage(options.page ?? 0);
142
+ const query = buildListQuery({
143
+ fields: config.projection,
144
+ sort: currentSort,
145
+ filters: currentFilters,
146
+ search: currentSearch,
147
+ limit: pageSize,
148
+ offset: page * pageSize,
149
+ count: true
150
+ });
151
+ const sequence = ++requestSequence;
152
+ table.setLoading(true);
153
+ try {
154
+ const normalized = normalizeZeyosListResult(client, await facade.list(resource, query));
155
+ const count = normalized.count ?? null;
156
+ const hasMore = count == null
157
+ ? normalized.data.length === pageSize
158
+ : (page * pageSize + normalized.data.length) < count;
159
+ if (sequence === requestSequence) {
160
+ currentPage = page;
161
+ totalCount = count;
162
+ more = hasMore;
163
+ if (page === 0) table.setData(normalized.data);
164
+ else table.addData(normalized.data);
165
+ }
166
+ return { data: normalized.data, count, page, hasMore, query };
167
+ } finally {
168
+ if (sequence === requestSequence) table.setLoading(false);
169
+ }
170
+ };
171
+
172
+ const binding = {
173
+ table,
174
+ load,
175
+ setSearch: (search) => load({ search, page: 0 }),
176
+ setFilters: (filters) => load({ filters, page: 0 }),
177
+ loadMore: () => more ? load({ page: currentPage + 1 }) : Promise.resolve({
178
+ data: [],
179
+ count: totalCount,
180
+ page: currentPage,
181
+ hasMore: false,
182
+ query: buildListQuery({
183
+ fields: config.projection,
184
+ sort: currentSort,
185
+ filters: currentFilters,
186
+ search: currentSearch,
187
+ limit: pageSize,
188
+ offset: currentPage * pageSize,
189
+ count: true
190
+ })
191
+ }),
192
+ get count() { return totalCount; },
193
+ get page() { return currentPage; },
194
+ get hasMore() { return more; },
195
+ destroy: () => table.destroy()
196
+ };
197
+
198
+ table.on('sort', (event) => {
199
+ currentSort = { id: String(event.detail.id), dir: event.detail.dir === 'desc' ? 'desc' : 'asc' };
200
+ void load({ page: 0 }).catch(() => { /* The connection facade already reported the failure. */ });
201
+ });
202
+ return binding;
203
+ }
204
+
205
+ /** @param {Record<string, any>} meta @returns {string|null} */
206
+ function referencedResourceFor(meta) {
207
+ for (const value of [meta.entity, meta.fk, meta.relation, meta.reference, meta.references]) {
208
+ if (typeof value === 'string' && value) return value;
209
+ if (value && typeof value === 'object') {
210
+ const resource = value.resource ?? value.target ?? value.table ?? value.entity;
211
+ if (typeof resource === 'string' && resource) return resource;
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+
217
+ /** @param {Record<string, any>} client @param {string} resource @returns {string} */
218
+ function inferLabelKey(client, resource) {
219
+ const fields = client?.schema?.fields?.(resource);
220
+ const names = Array.isArray(fields) ? fields.map(String) : Object.keys(fields ?? {});
221
+ for (const candidate of ['name', 'lastname', 'customernum', 'transactionnum', 'number', 'title', 'ID']) {
222
+ if (names.includes(candidate)) return candidate;
223
+ }
224
+ return names[0] ?? 'ID';
225
+ }
226
+
227
+ /** @param {Record<string, any>} meta @returns {boolean} */
228
+ function isMonetaryField(meta) {
229
+ const format = String(meta.format ?? '').toLowerCase();
230
+ return /money|currency|price/.test(format) || /(?:amount|price)$/.test(String(meta.id).toLowerCase());
231
+ }
232
+
233
+ /** @param {unknown} value @param {unknown} currency @returns {string} */
234
+ function formatCurrency(value, currency) {
235
+ if (value == null || value === '') return '';
236
+ const number = Number(value);
237
+ if (!Number.isFinite(number)) return '';
238
+ const code = typeof currency === 'string' && /^[A-Z]{3}$/.test(currency) ? currency : null;
239
+ try {
240
+ return new Intl.NumberFormat(undefined, code ? { style: 'currency', currency: code } : {}).format(number);
241
+ } catch {
242
+ return new Intl.NumberFormat().format(number);
243
+ }
244
+ }
245
+
246
+ /** @param {Record<string, any>} client @param {string} resource @param {string} id @returns {boolean} */
247
+ function schemaHasField(client, resource, id) {
248
+ const fields = client?.schema?.fields?.(resource);
249
+ if (Array.isArray(fields)) return fields.includes(id);
250
+ return Boolean(fields && typeof fields === 'object' && Object.prototype.hasOwnProperty.call(fields, id));
251
+ }
252
+
253
+ /** @param {unknown} value @returns {number} */
254
+ function normalizePageSize(value) {
255
+ const number = Number(value ?? 50);
256
+ return Number.isInteger(number) && number > 0 ? number : 50;
257
+ }
258
+
259
+ /** @param {unknown} value @returns {number} */
260
+ function normalizePage(value) {
261
+ const number = Number(value);
262
+ if (!Number.isInteger(number) || number < 0) throw new RangeError('ZeyOS table page must be a non-negative integer');
263
+ return number;
264
+ }
265
+
266
+ /** @param {Record<string, unknown>} filters @returns {Record<string, unknown>} */
267
+ function copyFilters(filters) {
268
+ if (!filters || typeof filters !== 'object' || Array.isArray(filters)) {
269
+ throw new TypeError('ZeyOS table filters must be an object');
270
+ }
271
+ return { ...filters };
272
+ }
@@ -0,0 +1,124 @@
1
+ .zx-scope,
2
+ .zx-scope *,
3
+ .zx-scope *::before,
4
+ .zx-scope *::after {
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ .zx-scope {
9
+ min-block-size: 100%;
10
+ margin: 0;
11
+ background: var(--zx-color-bg-page);
12
+ color: var(--zx-color-text);
13
+ font-family: var(--zx-font-sans);
14
+ font-size: var(--zx-text-md);
15
+ line-height: 1.5;
16
+ -webkit-font-smoothing: antialiased;
17
+ scrollbar-gutter: stable;
18
+ }
19
+
20
+ /* One focus ring only — ours. Without this the browser keeps painting its own ring (a blue
21
+ outline in Chrome/Safari) at the border edge, so a focused control showed a blue border inside
22
+ our accent glow. The replacement outline is transparent rather than removed: forced-colors mode
23
+ drops box-shadows but forces outline-color to a system colour, so focus stays visible there. */
24
+ .zx-scope :focus-visible {
25
+ outline: 2px solid transparent;
26
+ outline-offset: 2px;
27
+ box-shadow: var(--zx-focus-ring);
28
+ }
29
+
30
+ .zx-scope ::selection {
31
+ background: var(--zx-color-accent);
32
+ color: var(--zx-color-on-accent);
33
+ }
34
+
35
+ /* Native-control defaults are wrapped in :where() so they contribute ZERO specificity:
36
+ any component class (.zx-tabbox__tab, .zx-message__close, …) overrides them without a
37
+ specificity fight. This is the default chrome for otherwise-unstyled controls. */
38
+ :where(.zx-scope button:not(.zx-icon-btn)),
39
+ :where(.zx-scope input, .zx-scope select, .zx-scope textarea) {
40
+ min-block-size: var(--zx-control-height);
41
+ border: 1px solid var(--zx-color-border-control);
42
+ border-radius: var(--zx-control-radius);
43
+ background: var(--zx-color-bg-control);
44
+ color: var(--zx-color-text);
45
+ font: inherit;
46
+ font-size: var(--zx-control-font-size);
47
+ transition: color var(--zx-dur-fast) var(--zx-ease),
48
+ background-color var(--zx-dur-fast) var(--zx-ease),
49
+ border-color var(--zx-dur-fast) var(--zx-ease),
50
+ box-shadow var(--zx-dur-fast) var(--zx-ease);
51
+ }
52
+
53
+ :where(.zx-scope button:not(.zx-icon-btn)) {
54
+ font-weight: var(--zx-control-font-weight);
55
+ }
56
+
57
+ :where(.zx-scope button:not(.zx-icon-btn), .zx-scope select, .zx-scope textarea),
58
+ :where(.zx-scope input:not([type="checkbox"]):not([type="radio"])) {
59
+ padding-inline: var(--zx-control-pad-x);
60
+ }
61
+
62
+ :where(.zx-scope button) {
63
+ cursor: pointer;
64
+ }
65
+
66
+ :where(.zx-scope button:not(.zx-icon-btn)):hover {
67
+ background: var(--zx-color-bg-hover);
68
+ }
69
+
70
+ /* Ghost icon button: a borderless, transparent hit target for small glyph actions
71
+ (notification close, closable tab ×, field clear). Square, no chrome until hovered. */
72
+ .zx-scope .zx-icon-btn {
73
+ display: inline-grid;
74
+ place-items: center;
75
+ flex: 0 0 auto;
76
+ inline-size: var(--zx-control-height);
77
+ block-size: var(--zx-control-height);
78
+ padding: 0;
79
+ border: 0;
80
+ border-radius: var(--zx-radius-sm);
81
+ background: none;
82
+ color: var(--zx-color-text-muted);
83
+ cursor: pointer;
84
+ }
85
+
86
+ .zx-scope .zx-icon-btn:hover {
87
+ background: var(--zx-color-bg-hover);
88
+ color: var(--zx-color-text);
89
+ }
90
+
91
+ .zx-scope .zx-icon-btn:focus-visible {
92
+ outline: 0;
93
+ box-shadow: inset var(--zx-focus-ring);
94
+ }
95
+
96
+ .zx-scope .zx-icon-btn:disabled {
97
+ color: var(--zx-color-text-placeholder);
98
+ cursor: not-allowed;
99
+ }
100
+
101
+ /* Search-term highlight produced by highlightMatch(). No padding and no border, so marking a run
102
+ of text never shifts the line it sits in. */
103
+ .zx-scope .zx-mark {
104
+ padding: 0;
105
+ border-radius: var(--zx-radius-sm);
106
+ background: var(--zx-color-accent-subtle);
107
+ color: var(--zx-color-text);
108
+ }
109
+
110
+ .zx-scope input::placeholder,
111
+ .zx-scope textarea::placeholder {
112
+ color: var(--zx-color-text-placeholder);
113
+ }
114
+
115
+ @media (prefers-reduced-motion: reduce) {
116
+ .zx-scope *,
117
+ .zx-scope *::before,
118
+ .zx-scope *::after {
119
+ scroll-behavior: auto !important;
120
+ animation-duration: 0.01ms !important;
121
+ animation-iteration-count: 1 !important;
122
+ transition-duration: 0.01ms !important;
123
+ }
124
+ }
@@ -0,0 +1,34 @@
1
+ /* Icons.
2
+ Every icon `icon()` builds carries `.zx-icon`, whether it is one of the bundled inline SVG
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. */
5
+
6
+ .zx-icon {
7
+ flex: none;
8
+ }
9
+
10
+ i.zx-icon {
11
+ display: inline-block;
12
+ inline-size: 1em;
13
+ block-size: 1em;
14
+ line-height: 1;
15
+ text-align: center;
16
+ }
17
+
18
+ svg.zx-icon {
19
+ vertical-align: middle;
20
+ }
21
+
22
+ /* ZeyOS module icon chip: the module glyph on its identity colour. `moduleChip()` sets the three
23
+ custom properties per module; the glyph is whichever ZeyOS foreground contrasts better. */
24
+ .zx-module-icon {
25
+ display: inline-grid;
26
+ place-items: center;
27
+ flex: none;
28
+ inline-size: var(--zx-module-icon-size, 1.5rem);
29
+ block-size: var(--zx-module-icon-size, 1.5rem);
30
+ border-radius: var(--zx-radius-sm);
31
+ background: var(--zx-module-color, var(--zx-module-default));
32
+ color: var(--zx-module-glyph, var(--zx-module-fg-light));
33
+ font-size: calc(var(--zx-module-icon-size, 1.5rem) * 0.6);
34
+ }
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Tier-2 semantic tokens — dark theme, from the shadcn/ui preset `b2BVl11e4` (Zinc):
3
+ * Zinc-950 page, Zinc-900 cards and popovers, Zinc-800 muted fills, translucent white borders
4
+ * (10%) and inputs (15%), Zinc-400 muted text.
5
+ *
6
+ * The `[data-zx-theme="auto"]` block below repeats these assignments under a
7
+ * `prefers-color-scheme` query; CSS has no way to share a declaration block across a media
8
+ * boundary, so the two lists must be kept in sync.
9
+ */
10
+ [data-zx-theme="dark"] {
11
+ color-scheme: dark;
12
+ --zx-color-bg-page: var(--zx-gray-950);
13
+ --zx-color-bg-surface: var(--zx-gray-900);
14
+ --zx-color-bg-raised: var(--zx-gray-800);
15
+ --zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
16
+ --zx-color-bg-muted: var(--zx-gray-800);
17
+ --zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
18
+ --zx-color-bg-selected: color-mix(in srgb, var(--zx-green-400) 18%, var(--zx-gray-900));
19
+ --zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
20
+ --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
21
+ --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
22
+ --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
23
+ --zx-color-text: var(--zx-gray-50);
24
+ --zx-color-text-muted: var(--zx-gray-400);
25
+ --zx-color-text-placeholder: var(--zx-gray-500);
26
+ --zx-color-text-invert: var(--zx-gray-950);
27
+ --zx-color-accent: var(--zx-green-400);
28
+ --zx-color-accent-hover: var(--zx-green-300);
29
+ --zx-color-accent-active: var(--zx-green-500);
30
+ --zx-color-accent-subtle: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
31
+ --zx-color-on-accent: var(--zx-gray-950);
32
+ --zx-color-danger: var(--zx-red-400);
33
+ --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
34
+ --zx-color-warning: var(--zx-amber-400);
35
+ --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
36
+ --zx-color-success: var(--zx-green-400);
37
+ --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
38
+ --zx-color-info: var(--zx-blue-400);
39
+ --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
40
+ --zx-color-ring: var(--zx-color-accent);
41
+ --zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
42
+ --zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
43
+ --zx-header-bg: var(--zx-gray-900);
44
+ --zx-header-text: var(--zx-gray-50);
45
+ }
46
+
47
+ @media (prefers-color-scheme: dark) {
48
+ [data-zx-theme="auto"] {
49
+ color-scheme: dark;
50
+ --zx-color-bg-page: var(--zx-gray-950);
51
+ --zx-color-bg-surface: var(--zx-gray-900);
52
+ --zx-color-bg-raised: var(--zx-gray-800);
53
+ --zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
54
+ --zx-color-bg-muted: var(--zx-gray-800);
55
+ --zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
56
+ --zx-color-bg-selected: color-mix(in srgb, var(--zx-green-400) 18%, var(--zx-gray-900));
57
+ --zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
58
+ --zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
59
+ --zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
60
+ --zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
61
+ --zx-color-text: var(--zx-gray-50);
62
+ --zx-color-text-muted: var(--zx-gray-400);
63
+ --zx-color-text-placeholder: var(--zx-gray-500);
64
+ --zx-color-text-invert: var(--zx-gray-950);
65
+ --zx-color-accent: var(--zx-green-400);
66
+ --zx-color-accent-hover: var(--zx-green-300);
67
+ --zx-color-accent-active: var(--zx-green-500);
68
+ --zx-color-accent-subtle: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
69
+ --zx-color-on-accent: var(--zx-gray-950);
70
+ --zx-color-danger: var(--zx-red-400);
71
+ --zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
72
+ --zx-color-warning: var(--zx-amber-400);
73
+ --zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
74
+ --zx-color-success: var(--zx-green-400);
75
+ --zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
76
+ --zx-color-info: var(--zx-blue-400);
77
+ --zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
78
+ --zx-color-ring: var(--zx-color-accent);
79
+ --zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
80
+ --zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
81
+ --zx-header-bg: var(--zx-gray-900);
82
+ --zx-header-text: var(--zx-gray-50);
83
+ }
84
+ }
@@ -0,0 +1,9 @@
1
+ [data-zx-density="compact"] {
2
+ --zx-control-height: 28px;
3
+ --zx-control-pad-x: var(--zx-space-2);
4
+ --zx-text-md: 13px;
5
+ --zx-space-1: 3px;
6
+ --zx-space-2: 6px;
7
+ --zx-space-3: 10px;
8
+ --zx-space-4: 14px;
9
+ }
@@ -0,0 +1,80 @@
1
+ /*
2
+ * Tier-1 palette and primitives.
3
+ *
4
+ * Derived from the shadcn/ui preset `b2BVl11e4` (style Nova · base colour Zinc · theme Zinc ·
5
+ * chart colour Emerald · Inter · radius small). The neutral ramp is Tailwind Zinc; the accent
6
+ * ramp is the preset's Emerald chart ramp, anchored at 400 to the ZeyOS brand green #21cc75.
7
+ *
8
+ * Only tier-2 semantic tokens (tokens/semantic.css, tokens/dark.css) may reference these.
9
+ * Component CSS must never use them directly — tests/lint-tokens.js enforces that.
10
+ */
11
+ :root {
12
+ /* Neutrals — Tailwind Zinc */
13
+ --zx-gray-0: #ffffff;
14
+ --zx-gray-50: #fafafa;
15
+ --zx-gray-100: #f4f4f5;
16
+ --zx-gray-150: #ececee;
17
+ --zx-gray-200: #e4e4e7;
18
+ --zx-gray-300: #d4d4d8;
19
+ --zx-gray-400: #9f9fa9;
20
+ --zx-gray-500: #71717b;
21
+ --zx-gray-600: #52525c;
22
+ --zx-gray-700: #3f3f47;
23
+ --zx-gray-800: #27272a;
24
+ --zx-gray-900: #18181b;
25
+ --zx-gray-950: #09090b;
26
+
27
+ /* Accent — the preset's Emerald chart ramp, with the ZeyOS brand green at 400 */
28
+ --zx-green-300: #5ee9b5;
29
+ --zx-green-400: #21cc75;
30
+ --zx-green-500: #009966;
31
+ --zx-green-600: #007a55;
32
+ --zx-green-700: #006045;
33
+
34
+ /* Status */
35
+ --zx-red-400: #ff6467;
36
+ --zx-red-500: #e7000b;
37
+ --zx-red-600: #c10007;
38
+ --zx-amber-400: #ffb900;
39
+ --zx-amber-500: #fe9a00;
40
+ --zx-amber-600: #bb4d00;
41
+ --zx-blue-400: #51a2ff;
42
+ --zx-blue-500: #2b7fff;
43
+ --zx-blue-600: #155dfc;
44
+
45
+ --zx-space-1: 4px;
46
+ --zx-space-2: 8px;
47
+ --zx-space-3: 12px;
48
+ --zx-space-4: 16px;
49
+ --zx-space-5: 20px;
50
+ --zx-space-6: 24px;
51
+ --zx-space-7: 32px;
52
+ --zx-space-8: 40px;
53
+
54
+ /* Radius — the preset's `--radius: 0.45rem`, with shadcn's derived steps */
55
+ --zx-radius: 0.45rem;
56
+ --zx-radius-sm: calc(var(--zx-radius) - 4px);
57
+ --zx-radius-md: calc(var(--zx-radius) - 2px);
58
+ --zx-radius-lg: var(--zx-radius);
59
+ --zx-radius-xl: calc(var(--zx-radius) + 4px);
60
+ --zx-radius-full: 999px;
61
+
62
+ --zx-font-sans: Inter, "Inter Variable", ui-sans-serif, system-ui, -apple-system,
63
+ "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
64
+ --zx-font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco,
65
+ Consolas, monospace;
66
+ --zx-text-xs: 12px;
67
+ --zx-text-sm: 13px;
68
+ --zx-text-md: 14px;
69
+ --zx-text-lg: 16px;
70
+ --zx-text-xl: 18px;
71
+ --zx-text-2xl: 24px;
72
+
73
+ --zx-shadow-1: 0 1px 2px 0 rgb(9 9 11 / 5%);
74
+ --zx-shadow-2: 0 1px 3px 0 rgb(9 9 11 / 10%), 0 1px 2px -1px rgb(9 9 11 / 10%);
75
+ --zx-shadow-3: 0 10px 15px -3px rgb(9 9 11 / 10%), 0 4px 6px -4px rgb(9 9 11 / 10%);
76
+
77
+ --zx-dur-fast: 120ms;
78
+ --zx-dur-base: 180ms;
79
+ --zx-ease: cubic-bezier(.2, .6, .3, 1);
80
+ }