@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,76 @@
1
+ .zx-skeleton {
2
+ display: block;
3
+ background: var(--zx-color-bg-muted);
4
+ border-radius: var(--zx-radius-sm);
5
+ }
6
+
7
+ .zx-skeleton[data-radius="md"] {
8
+ border-radius: var(--zx-radius-md);
9
+ }
10
+
11
+ .zx-skeleton[data-radius="full"] {
12
+ border-radius: var(--zx-radius-full);
13
+ }
14
+
15
+ .zx-skeleton-text {
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: var(--zx-space-2);
19
+ }
20
+
21
+ .zx-skeleton-table {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: var(--zx-space-1);
25
+ inline-size: 100%;
26
+ }
27
+
28
+ .zx-skeleton-table__row {
29
+ display: grid;
30
+ grid-template-columns: repeat(var(--zx-skeleton-columns, 4), minmax(0, 1fr));
31
+ gap: var(--zx-space-4);
32
+ align-items: center;
33
+ padding-block: var(--zx-space-3);
34
+ padding-inline: var(--zx-space-3);
35
+ border-block-end: 1px solid var(--zx-color-border);
36
+ }
37
+
38
+ /*
39
+ * The header reads through its blocks, not through a filled band: a muted row behind muted
40
+ * placeholders is one solid bar with no cells visible in it.
41
+ */
42
+ .zx-skeleton-table__row[data-kind="header"] {
43
+ border-block-end-color: var(--zx-color-border-strong);
44
+ }
45
+
46
+ .zx-skeleton-table__row[data-kind="header"] .zx-skeleton {
47
+ background: var(--zx-color-border);
48
+ }
49
+
50
+ .zx-skeleton-table__row:last-child {
51
+ border-block-end: 0;
52
+ }
53
+
54
+ /*
55
+ * The pulse is the whole animation: a gradient sweep would need colours the token layer does not
56
+ * define, and reduced motion has to leave a legible static block behind either way.
57
+ */
58
+ @media (prefers-reduced-motion: no-preference) {
59
+ .zx-skeleton {
60
+ animation: zx-skeleton-pulse 1400ms var(--zx-ease) infinite;
61
+ }
62
+
63
+ .zx-skeleton-text .zx-skeleton:nth-child(2n) {
64
+ animation-delay: 120ms;
65
+ }
66
+
67
+ .zx-skeleton-table__row:nth-child(2n) .zx-skeleton {
68
+ animation-delay: 120ms;
69
+ }
70
+ }
71
+
72
+ @keyframes zx-skeleton-pulse {
73
+ 50% {
74
+ opacity: 0.5;
75
+ }
76
+ }
@@ -0,0 +1,139 @@
1
+ import { h } from '../../core/dom.js';
2
+ import { clamp } from '../../core/util.js';
3
+
4
+ /**
5
+ * @typedef {Object} SkeletonOptions
6
+ * @property {string|number} [width='100%'] Block width; a number is read as pixels.
7
+ * @property {string|number} [height='1rem'] Block height; a number is read as pixels.
8
+ * @property {'sm'|'md'|'full'} [radius='sm'] Corner rounding. `full` with equal width and height
9
+ * gives the circle an avatar or icon placeholder needs.
10
+ */
11
+
12
+ /**
13
+ * @typedef {Object} SkeletonTextOptions
14
+ * @property {number} [lines=3] Number of text lines.
15
+ * @property {string|number} [width='100%'] Width of the block as a whole.
16
+ * @property {boolean} [heading=false] Whether the first line is drawn taller, as a title.
17
+ * @property {string|number} [lastLineWidth='60%'] Width of the final line, which reads as prose
18
+ * rather than as a filled rectangle.
19
+ */
20
+
21
+ /**
22
+ * @typedef {Object} SkeletonTableOptions
23
+ * @property {number} [rows=5] Number of body rows.
24
+ * @property {number} [columns=4] Number of columns.
25
+ * @property {boolean} [header=true] Whether a header row is drawn.
26
+ */
27
+
28
+ /**
29
+ * Creates one placeholder block.
30
+ *
31
+ * Skeletons stand in for content whose shape is already known, which is what makes them worth
32
+ * more than a spinner: the layout does not jump when the data arrives. Every skeleton is
33
+ * `aria-hidden`, because a screen reader gains nothing from an announced grey box — set
34
+ * `aria-busy="true"` on the region being filled instead, and remove it with the skeleton.
35
+ *
36
+ * @param {SkeletonOptions} [opts={}] Block options.
37
+ * @returns {HTMLSpanElement}
38
+ */
39
+ export function skeleton(opts = {}) {
40
+ const options = { width: '100%', height: '1rem', radius: 'sm', ...opts };
41
+ return /** @type {HTMLSpanElement} */ (h('span', {
42
+ class: 'zx-skeleton',
43
+ ariaHidden: 'true',
44
+ dataset: { radius: RADII.has(options.radius) ? options.radius : 'sm' },
45
+ style: { 'inline-size': size(options.width), 'block-size': size(options.height) }
46
+ }));
47
+ }
48
+
49
+ /**
50
+ * Creates a stack of placeholder lines standing in for a paragraph or a labelled value.
51
+ * @param {SkeletonTextOptions} [opts={}] Text options.
52
+ * @returns {HTMLDivElement}
53
+ */
54
+ export function skeletonText(opts = {}) {
55
+ const options = { lines: 3, width: '100%', heading: false, lastLineWidth: '60%', ...opts };
56
+ const lines = clamp(Math.trunc(Number(options.lines) || 0), 1, 20);
57
+ const element = /** @type {HTMLDivElement} */ (h('div', {
58
+ class: 'zx-skeleton-text',
59
+ ariaHidden: 'true',
60
+ style: { 'inline-size': size(options.width) }
61
+ }));
62
+
63
+ for (let index = 0; index < lines; index += 1) {
64
+ const heading = options.heading && index === 0;
65
+ const last = index === lines - 1 && lines > 1;
66
+ element.append(skeleton({
67
+ width: last ? options.lastLineWidth : '100%',
68
+ height: heading ? '1.5rem' : '0.75rem'
69
+ }));
70
+ }
71
+ return element;
72
+ }
73
+
74
+ /**
75
+ * Creates a placeholder grid the shape of a table that has not loaded yet.
76
+ *
77
+ * Rendered as plain elements rather than a `<table>`: there is no data to expose, and a table
78
+ * whose cells are all empty is worse for assistive technology than no table at all.
79
+ *
80
+ * @param {SkeletonTableOptions} [opts={}] Table options.
81
+ * @returns {HTMLDivElement}
82
+ */
83
+ export function skeletonTable(opts = {}) {
84
+ const options = { rows: 5, columns: 4, header: true, ...opts };
85
+ const rows = clamp(Math.trunc(Number(options.rows) || 0), 1, 50);
86
+ const columns = clamp(Math.trunc(Number(options.columns) || 0), 1, 20);
87
+ const element = /** @type {HTMLDivElement} */ (h('div', {
88
+ class: 'zx-skeleton-table',
89
+ ariaHidden: 'true',
90
+ style: { '--zx-skeleton-columns': String(columns) }
91
+ }));
92
+
93
+ if (options.header !== false) {
94
+ element.append(row(columns, 'header'));
95
+ }
96
+ for (let index = 0; index < rows; index += 1) element.append(row(columns, 'body'));
97
+ return element;
98
+ }
99
+
100
+ const RADII = new Set(['sm', 'md', 'full']);
101
+
102
+ /**
103
+ * Builds one placeholder row.
104
+ * @param {number} columns Number of cells.
105
+ * @param {'header'|'body'} kind Row kind.
106
+ * @returns {HTMLDivElement}
107
+ */
108
+ function row(columns, kind) {
109
+ const element = /** @type {HTMLDivElement} */ (h('div', {
110
+ class: 'zx-skeleton-table__row',
111
+ dataset: { kind }
112
+ }));
113
+ for (let index = 0; index < columns; index += 1) {
114
+ element.append(h('span', { class: 'zx-skeleton-table__cell' },
115
+ skeleton({ width: cellWidth(index, columns), height: '0.75rem' })));
116
+ }
117
+ return element;
118
+ }
119
+
120
+ /**
121
+ * Cell widths that vary a little, so the placeholder reads as a table of values rather than as a
122
+ * bar chart of identical blocks.
123
+ * @param {number} index Column index.
124
+ * @param {number} columns Column count.
125
+ * @returns {string}
126
+ */
127
+ function cellWidth(index, columns) {
128
+ if (index === columns - 1) return '55%';
129
+ return index % 2 === 0 ? '80%' : '65%';
130
+ }
131
+
132
+ /**
133
+ * Normalizes a CSS length, reading a bare number as pixels.
134
+ * @param {string|number} value Width or height.
135
+ * @returns {string}
136
+ */
137
+ function size(value) {
138
+ return typeof value === 'number' ? `${value}px` : String(value ?? '');
139
+ }
@@ -0,0 +1,36 @@
1
+ import { Field } from '../field/field.js';
2
+ import { Slider } from './slider.js';
3
+
4
+ /**
5
+ * Registers the Slider-backed `slider` field type.
6
+ * @returns {void}
7
+ */
8
+ export function registerSliderFieldAdapter() {
9
+ Field.register('slider', (field, options) => {
10
+ const slider = field.own(new Slider(null, {
11
+ // The Field already renders the label, so the slider keeps it only for its own control.
12
+ label: options.label ? String(options.label) : undefined,
13
+ hideLabel: true,
14
+ disabled: Boolean(options.disabled),
15
+ ...(options.props ?? {})
16
+ }));
17
+ let setting = false;
18
+ slider.on('change', (event) => {
19
+ if (!setting) field.emit('change', { value: event.detail.value });
20
+ });
21
+ return {
22
+ el: slider.el,
23
+ get: () => slider.get(),
24
+ set: (value) => {
25
+ setting = true;
26
+ try {
27
+ slider.set(Number(value) || 0, { silent: true });
28
+ } finally {
29
+ setting = false;
30
+ }
31
+ },
32
+ focus: () => slider.focus(),
33
+ setDisabled: (value) => (value ? slider.disable() : slider.enable())
34
+ };
35
+ });
36
+ }
@@ -0,0 +1,181 @@
1
+ .zx-slider {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--zx-space-2);
5
+ inline-size: 100%;
6
+ --zx-slider-thumb: 16px;
7
+ --zx-slider-rail: 4px;
8
+ }
9
+
10
+ .zx-slider[data-size="sm"] {
11
+ --zx-slider-thumb: 12px;
12
+ --zx-slider-rail: 3px;
13
+ }
14
+
15
+ .zx-slider__head {
16
+ display: flex;
17
+ align-items: baseline;
18
+ justify-content: space-between;
19
+ gap: var(--zx-space-3);
20
+ font-size: var(--zx-control-font-size);
21
+ }
22
+
23
+ .zx-slider__label {
24
+ color: var(--zx-color-text);
25
+ font-weight: 500;
26
+ }
27
+
28
+ .zx-slider__value {
29
+ color: var(--zx-color-text-muted);
30
+ font-variant-numeric: tabular-nums;
31
+ }
32
+
33
+ .zx-slider__value:empty {
34
+ display: none;
35
+ }
36
+
37
+ .zx-slider[data-hide-label] .zx-slider__label {
38
+ position: absolute;
39
+ clip-path: inset(50%);
40
+ inline-size: 1px;
41
+ block-size: 1px;
42
+ overflow: hidden;
43
+ white-space: nowrap;
44
+ }
45
+
46
+ .zx-slider__control {
47
+ display: flex;
48
+ align-items: start;
49
+ gap: var(--zx-space-3);
50
+ }
51
+
52
+ /*
53
+ * The bounds centre on the RAIL, not on the control: with marks below it the track grows taller,
54
+ * and centring on the whole box would float `0` up beside the first mark label instead of beside
55
+ * the value it bounds. The offset is half the difference between the rail row and this line box.
56
+ */
57
+ .zx-slider__bound {
58
+ flex: none;
59
+ align-self: start;
60
+ margin-block-start: calc((var(--zx-slider-thumb) - 1.5em) / 2);
61
+ color: var(--zx-color-text-muted);
62
+ font-size: var(--zx-text-sm);
63
+ font-variant-numeric: tabular-nums;
64
+ }
65
+
66
+ .zx-slider__track {
67
+ position: relative;
68
+ flex: 1 1 auto;
69
+ min-inline-size: 0;
70
+ }
71
+
72
+ /*
73
+ * base.css gives every bare input the control box — a minimum height, a border, a radius, and
74
+ * inline padding. A range input wants none of them: the element IS the rail, so all four are
75
+ * cleared here rather than fought with later.
76
+ */
77
+ .zx-slider__input {
78
+ display: block;
79
+ appearance: none;
80
+ inline-size: 100%;
81
+ min-block-size: 0;
82
+ block-size: var(--zx-slider-thumb);
83
+ margin: 0;
84
+ padding: 0;
85
+ border: 0;
86
+ border-radius: 0;
87
+ background: none;
88
+ cursor: pointer;
89
+ }
90
+
91
+ .zx-slider__input::-webkit-slider-runnable-track {
92
+ block-size: var(--zx-slider-rail);
93
+ border-radius: var(--zx-radius-full);
94
+ background: linear-gradient(
95
+ to right,
96
+ var(--zx-color-accent) 0 var(--zx-slider-fill, 0%),
97
+ var(--zx-color-bg-muted) var(--zx-slider-fill, 0%) 100%
98
+ );
99
+ }
100
+
101
+ .zx-slider__input::-moz-range-track {
102
+ block-size: var(--zx-slider-rail);
103
+ border-radius: var(--zx-radius-full);
104
+ background: var(--zx-color-bg-muted);
105
+ }
106
+
107
+ .zx-slider__input::-moz-range-progress {
108
+ block-size: var(--zx-slider-rail);
109
+ border-radius: var(--zx-radius-full);
110
+ background: var(--zx-color-accent);
111
+ }
112
+
113
+ .zx-slider__input::-webkit-slider-thumb {
114
+ appearance: none;
115
+ inline-size: var(--zx-slider-thumb);
116
+ block-size: var(--zx-slider-thumb);
117
+ /* Centres the thumb on the rail: half the difference between the two heights. */
118
+ margin-block-start: calc((var(--zx-slider-rail) - var(--zx-slider-thumb)) / 2);
119
+ border: 2px solid var(--zx-color-bg-surface);
120
+ border-radius: var(--zx-radius-full);
121
+ background: var(--zx-color-accent);
122
+ box-shadow: var(--zx-shadow-1);
123
+ }
124
+
125
+ .zx-slider__input::-moz-range-thumb {
126
+ inline-size: var(--zx-slider-thumb);
127
+ block-size: var(--zx-slider-thumb);
128
+ border: 2px solid var(--zx-color-bg-surface);
129
+ border-radius: var(--zx-radius-full);
130
+ background: var(--zx-color-accent);
131
+ box-shadow: var(--zx-shadow-1);
132
+ }
133
+
134
+ .zx-slider__input:focus-visible {
135
+ outline: 2px solid transparent;
136
+ outline-offset: 2px;
137
+ box-shadow: var(--zx-focus-ring);
138
+ border-radius: var(--zx-radius-full);
139
+ }
140
+
141
+ /* Wide enough for five digits beside the native spin buttons, which eat more room than they look. */
142
+ .zx-slider__number {
143
+ flex: none;
144
+ align-self: start;
145
+ inline-size: 10ch;
146
+ text-align: end;
147
+ font-variant-numeric: tabular-nums;
148
+ }
149
+
150
+ .zx-slider__marks {
151
+ position: relative;
152
+ block-size: var(--zx-space-5);
153
+ margin-block-start: var(--zx-space-1);
154
+ }
155
+
156
+ .zx-slider__mark {
157
+ position: absolute;
158
+ inset-block-start: 0;
159
+ inset-inline-start: var(--zx-slider-mark, 0%);
160
+ transform: translateX(-50%);
161
+ color: var(--zx-color-text-muted);
162
+ font-size: var(--zx-text-xs);
163
+ white-space: nowrap;
164
+ }
165
+
166
+ .zx-slider[data-disabled] {
167
+ opacity: 0.55;
168
+ }
169
+
170
+ .zx-slider[data-disabled] .zx-slider__input,
171
+ .zx-slider[data-readonly] .zx-slider__input {
172
+ cursor: not-allowed;
173
+ }
174
+
175
+ .zx-slider[data-readonly] .zx-slider__input::-webkit-slider-thumb {
176
+ background: var(--zx-color-text-muted);
177
+ }
178
+
179
+ .zx-slider[data-readonly] .zx-slider__input::-moz-range-thumb {
180
+ background: var(--zx-color-text-muted);
181
+ }