@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
@@ -497,7 +497,8 @@ function deepMerge(a, b) {
497
497
  );
498
498
  }
499
499
  function isElement(value) {
500
- return Boolean(value && typeof value === "object" && value.nodeType === 1);
500
+ return Boolean(value && typeof value === "object" && /** @type {{nodeType?: unknown}} */
501
+ value.nodeType === 1);
501
502
  }
502
503
  function clamp(n, min, max) {
503
504
  return Math.min(max, Math.max(min, n));
@@ -577,8 +578,12 @@ function resolveElement(target) {
577
578
  }
578
579
  function isPropsObject(value) {
579
580
  if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
580
- if (typeof value.nodeType === "number") return false;
581
- return typeof value.toElement !== "function";
581
+ const candidate = (
582
+ /** @type {Record<string, unknown>} */
583
+ value
584
+ );
585
+ if (typeof candidate.nodeType === "number") return false;
586
+ return typeof candidate.toElement !== "function";
582
587
  }
583
588
  function applyProperty(element, key, value) {
584
589
  if (key === "ref") {
@@ -636,15 +641,33 @@ function ariaAttribute(key) {
636
641
  return "aria-" + key.slice(4).toLowerCase();
637
642
  }
638
643
  function appendChildren(parent, children) {
639
- for (const child of children.flat(Infinity)) {
640
- if (child == null) continue;
641
- if (typeof child === "string" || typeof child === "number") {
642
- parent.append(document.createTextNode(String(child)));
643
- } else if (child && typeof child === "object" && typeof child.nodeType === "number") {
644
- parent.append(child);
645
- } else if (typeof child === "object" && typeof child.toElement === "function") {
644
+ const host = (
645
+ /** @type {ParentNode} */
646
+ parent
647
+ );
648
+ for (
649
+ const raw2 of
650
+ /** @type {any[]} */
651
+ children.flat(Infinity)
652
+ ) {
653
+ if (raw2 == null) continue;
654
+ if (typeof raw2 === "string" || typeof raw2 === "number") {
655
+ host.append(document.createTextNode(String(raw2)));
656
+ continue;
657
+ }
658
+ if (typeof raw2 !== "object") continue;
659
+ const child = (
660
+ /** @type {{nodeType?: number, toElement?: () => Node|null}} */
661
+ raw2
662
+ );
663
+ if (typeof child.nodeType === "number") {
664
+ host.append(
665
+ /** @type {Node} */
666
+ raw2
667
+ );
668
+ } else if (typeof child.toElement === "function") {
646
669
  const element = child.toElement();
647
- if (element) parent.append(element);
670
+ if (element) host.append(element);
648
671
  }
649
672
  }
650
673
  }
@@ -693,11 +716,18 @@ var registry = /* @__PURE__ */ new WeakMap();
693
716
  var Component = class extends EventTarget {
694
717
  /** @type {ComponentOptions} */
695
718
  static defaults = {};
719
+ /**
720
+ * BEM block a subclass wants on its root, without the `zx-` prefix. Empty on the base, which is
721
+ * the same falsy answer the undeclared property gave — declared so the statics are visible to
722
+ * `this.constructor` and to the generated declarations.
723
+ * @type {string}
724
+ */
725
+ static cssName = "";
696
726
  /** @type {Element} Root element. */
697
727
  el;
698
728
  /** @type {Record<string, Element>} Elements captured by `h()` ref properties. */
699
729
  refs;
700
- /** @type {Readonly<ComponentOptions>} Merged component options. */
730
+ /** @type {Readonly<TOptions>} Merged component options. */
701
731
  options;
702
732
  #abort = new AbortController();
703
733
  #created = false;
@@ -706,17 +736,27 @@ var Component = class extends EventTarget {
706
736
  /**
707
737
  * Creates a component around an existing target, or asks `render()` to create its root.
708
738
  * @param {Element|string|null} target Existing element, selector, or null.
709
- * @param {ComponentOptions} [options={}] Component options.
739
+ * @param {TOptions} [options={}] Component options.
710
740
  */
711
- constructor(target, options = {}) {
741
+ constructor(target, options = (
742
+ /** @type {TOptions} */
743
+ {}
744
+ )) {
712
745
  super();
746
+ const self = (
747
+ /** @type {typeof Component} */
748
+ this.constructor
749
+ );
713
750
  this.#created = target === null;
714
751
  const resolved = resolveElement(target);
715
752
  if (target !== null && !resolved) throw new TypeError("Component target could not be resolved");
716
753
  this.el = /** @type {Element} */
717
754
  resolved;
718
755
  this.refs = {};
719
- const merged = mergeOptions(this.constructor, options);
756
+ const merged = (
757
+ /** @type {TOptions} */
758
+ mergeOptions(self, options)
759
+ );
720
760
  const eventOptions = [];
721
761
  for (const [key, value] of Object.entries(merged)) {
722
762
  if (/^on[a-z]/.test(key) && typeof value === "function") {
@@ -746,7 +786,7 @@ var Component = class extends EventTarget {
746
786
  this.#abort.abort();
747
787
  throw new TypeError("Component requires a root Element");
748
788
  }
749
- const cssName = this.constructor.cssName;
789
+ const cssName = self.cssName;
750
790
  if (typeof cssName === "string" && cssName) {
751
791
  const className = `zx-${cssName}`;
752
792
  this.#addedRootClass = !this.el.classList.contains(className);
@@ -867,7 +907,10 @@ var Component = class extends EventTarget {
867
907
  this.#destroyed = true;
868
908
  this.#abort.abort();
869
909
  if (registry.get(this.el) === this) registry.delete(this.el);
870
- const cssName = this.constructor.cssName;
910
+ const cssName = (
911
+ /** @type {typeof Component} */
912
+ this.constructor.cssName
913
+ );
871
914
  if (this.#addedRootClass && typeof cssName === "string" && this.el) {
872
915
  this.el.classList.remove(`zx-${cssName}`);
873
916
  }
@@ -1851,7 +1894,10 @@ function getWeekStart(lang = getLanguage()) {
1851
1894
  if (!lang) return 1;
1852
1895
  if (lang.toLowerCase() === "en") return 1;
1853
1896
  try {
1854
- const locale = new Intl.Locale(lang);
1897
+ const locale = (
1898
+ /** @type {Intl.Locale & {getWeekInfo?: () => {firstDay?: number}, weekInfo?: {firstDay?: number}}} */
1899
+ new Intl.Locale(lang)
1900
+ );
1855
1901
  const weekInfo = locale.getWeekInfo?.() ?? locale.weekInfo;
1856
1902
  if (weekInfo?.firstDay) return weekInfo.firstDay % 7;
1857
1903
  } catch {
@@ -1979,25 +2025,28 @@ function loadFontAwesomeKit(kit) {
1979
2025
  const url = kitUrl(kit);
1980
2026
  const pending = kitLoads.get(url);
1981
2027
  if (pending) return pending;
1982
- const promise = new Promise((resolve, reject) => {
1983
- const absolute = new URL(url, document.baseURI).href;
1984
- const existing = [...document.scripts].find((script2) => script2.src === absolute);
1985
- if (existing && globalThis.FontAwesomeKitConfig) {
1986
- resolve();
1987
- return;
1988
- }
1989
- const script = existing ?? document.createElement("script");
1990
- script.addEventListener("load", () => resolve(), { once: true });
1991
- script.addEventListener("error", () => {
1992
- kitLoads.delete(url);
1993
- reject(new Error(`Font Awesome kit failed to load: ${url}`));
1994
- }, { once: true });
1995
- if (existing) return;
1996
- script.src = url;
1997
- script.async = true;
1998
- script.crossOrigin = "anonymous";
1999
- document.head.append(script);
2000
- });
2028
+ const promise = (
2029
+ /** @type {Promise<void>} */
2030
+ new Promise((resolve, reject) => {
2031
+ const absolute = new URL(url, document.baseURI).href;
2032
+ const existing = [...document.scripts].find((script2) => script2.src === absolute);
2033
+ if (existing && globalThis.FontAwesomeKitConfig) {
2034
+ resolve();
2035
+ return;
2036
+ }
2037
+ const script = existing ?? document.createElement("script");
2038
+ script.addEventListener("load", () => resolve(), { once: true });
2039
+ script.addEventListener("error", () => {
2040
+ kitLoads.delete(url);
2041
+ reject(new Error(`Font Awesome kit failed to load: ${url}`));
2042
+ }, { once: true });
2043
+ if (existing) return;
2044
+ script.src = url;
2045
+ script.async = true;
2046
+ script.crossOrigin = "anonymous";
2047
+ document.head.append(script);
2048
+ })
2049
+ );
2001
2050
  kitLoads.set(url, promise);
2002
2051
  return promise;
2003
2052
  }
@@ -3240,9 +3289,11 @@ function updateFallback(anchor, floating, { placement, offset, flip, matchWidth
3240
3289
  const topY = anchorRect.top - offset - floatingRect.height;
3241
3290
  if (flip) {
3242
3291
  if (prefersBottom && bottomY + floatingRect.height > viewportHeight && topY >= 0) {
3243
- actualPlacement = placement.replace("bottom", "top");
3292
+ actualPlacement = /** @type {typeof placement} */
3293
+ placement.replace("bottom", "top");
3244
3294
  } else if (!prefersBottom && topY < 0 && bottomY + floatingRect.height <= viewportHeight) {
3245
- actualPlacement = placement.replace("top", "bottom");
3295
+ actualPlacement = /** @type {typeof placement} */
3296
+ placement.replace("top", "bottom");
3246
3297
  }
3247
3298
  }
3248
3299
  let left;
@@ -6236,7 +6287,11 @@ function itemText(item) {
6236
6287
  return String(item.textContent ?? "").trim().toLocaleLowerCase();
6237
6288
  }
6238
6289
  if (item && typeof item === "object") {
6239
- const value = item.label ?? item.text ?? item.value;
6290
+ const shape = (
6291
+ /** @type {{label?: unknown, text?: unknown, value?: unknown}} */
6292
+ item
6293
+ );
6294
+ const value = shape.label ?? shape.text ?? shape.value;
6240
6295
  if (value != null) return String(value).trim().toLocaleLowerCase();
6241
6296
  }
6242
6297
  return String(item ?? "").trim().toLocaleLowerCase();
@@ -8697,6 +8752,75 @@ function registerValueListFieldAdapter() {
8697
8752
  });
8698
8753
  }
8699
8754
 
8755
+ // src/core/breakpoint.js
8756
+ var breakpoints = Object.freeze({ sm: 480, md: 768, lg: 1024, xl: 1280 });
8757
+ var ORDER = (
8758
+ /** @type {const} */
8759
+ ["xl", "lg", "md", "sm"]
8760
+ );
8761
+ function breakpointOf(width) {
8762
+ const value = Number(width);
8763
+ if (!Number.isFinite(value)) return "xs";
8764
+ for (const name of ORDER) {
8765
+ if (value >= breakpoints[name]) return name;
8766
+ }
8767
+ return "xs";
8768
+ }
8769
+ function onBreakpoint(handler, options = {}) {
8770
+ if (typeof handler !== "function") throw new TypeError("onBreakpoint requires a handler");
8771
+ if ("target" in options && !isElement(options.target) && /** @type {unknown} */
8772
+ options.target !== /** @type {unknown} */
8773
+ globalThis) {
8774
+ throw new TypeError("onBreakpoint target must be an Element or the window");
8775
+ }
8776
+ const target = options.target ?? globalThis;
8777
+ const element = isElement(target) ? (
8778
+ /** @type {Element} */
8779
+ target
8780
+ ) : null;
8781
+ let name = (
8782
+ /** @type {BreakpointName|null} */
8783
+ null
8784
+ );
8785
+ let destroyed = false;
8786
+ let observer = null;
8787
+ const measure = () => element ? element.getBoundingClientRect().width : Number(globalThis.innerWidth) || 0;
8788
+ const update = () => {
8789
+ if (destroyed) return;
8790
+ const width = measure();
8791
+ if (element && width === 0) return;
8792
+ const next = breakpointOf(width);
8793
+ if (next === name) return;
8794
+ name = next;
8795
+ handler(name, width);
8796
+ };
8797
+ update();
8798
+ let frame = 0;
8799
+ const schedule = () => {
8800
+ if (frame || destroyed) return;
8801
+ frame = requestAnimationFrame(() => {
8802
+ frame = 0;
8803
+ update();
8804
+ });
8805
+ };
8806
+ if (element && typeof ResizeObserver === "function") {
8807
+ observer = new ResizeObserver(schedule);
8808
+ observer.observe(element);
8809
+ } else {
8810
+ globalThis.addEventListener?.("resize", update, { passive: true });
8811
+ }
8812
+ return {
8813
+ current: () => name ?? breakpointOf(measure()),
8814
+ destroy: () => {
8815
+ if (destroyed) return;
8816
+ destroyed = true;
8817
+ if (frame) cancelAnimationFrame(frame);
8818
+ observer?.disconnect();
8819
+ globalThis.removeEventListener?.("resize", update);
8820
+ }
8821
+ };
8822
+ }
8823
+
8700
8824
  // src/components/table/sort.js
8701
8825
  function compareStrings(left, right) {
8702
8826
  return String(left).localeCompare(String(right));
@@ -8746,6 +8870,8 @@ var Table = class extends Component {
8746
8870
  sortMode: "local",
8747
8871
  selectable: false,
8748
8872
  stickyHeader: true,
8873
+ responsive: false,
8874
+ growing: false,
8749
8875
  height: null,
8750
8876
  emptyText: null,
8751
8877
  rowClass: null,
@@ -8766,6 +8892,7 @@ var Table = class extends Component {
8766
8892
  /** @type {HTMLElement} */
8767
8893
  this.el ?? h("div")
8768
8894
  );
8895
+ this.el = root;
8769
8896
  this._originalChildren = this.el ? Array.from(this.el.childNodes) : null;
8770
8897
  this._columns = Array.isArray(this.options.columns) ? this.options.columns.map((column) => ({ ...column })) : [];
8771
8898
  this._data = Array.isArray(this.options.data) ? [...this.options.data] : [];
@@ -8778,6 +8905,11 @@ var Table = class extends Component {
8778
8905
  this._editMode = normalizeEditMode(this.options.editMode);
8779
8906
  this._edit = null;
8780
8907
  this._editMessage = null;
8908
+ this._stacked = false;
8909
+ this._width = null;
8910
+ this._growStep = growStep(this.options.growing);
8911
+ this._rendered = this._growStep ?? Infinity;
8912
+ this._more = null;
8781
8913
  this._rovingKey = null;
8782
8914
  this._rovingCell = null;
8783
8915
  this._rovingMatched = false;
@@ -8812,6 +8944,7 @@ var Table = class extends Component {
8812
8944
  this._renderColumns();
8813
8945
  this._renderHeader();
8814
8946
  this._renderBody();
8947
+ this._watchWidth();
8815
8948
  this.listen(this._tbody, "click", (event) => this._handleBodyClick(event));
8816
8949
  this.listen(this._tbody, "dblclick", (event) => this._handleBodyDoubleClick(event));
8817
8950
  if (this._editMode !== false) {
@@ -8845,6 +8978,7 @@ var Table = class extends Component {
8845
8978
  * @fires Table#editcancel
8846
8979
  */
8847
8980
  setData(rows) {
8981
+ this._rendered = this._growStep ?? Infinity;
8848
8982
  this.setLoading(false);
8849
8983
  assertRows(rows);
8850
8984
  this._data = [...rows];
@@ -9119,9 +9253,150 @@ var Table = class extends Component {
9119
9253
  getEditing() {
9120
9254
  return this._edit ? { id: this._edit.id, columnId: this._edit.columnId } : null;
9121
9255
  }
9256
+ /**
9257
+ * The rows currently rendered — all of them unless `growing` is on.
9258
+ * @returns {TableRow[]}
9259
+ */
9260
+ _visibleData() {
9261
+ return this._rendered === Infinity ? this._data : this._data.slice(0, this._rendered);
9262
+ }
9263
+ /**
9264
+ * Renders the next batch of rows.
9265
+ * @param {number} [count] How many to add; defaults to the configured batch size.
9266
+ * @returns {this}
9267
+ * @fires Table#grow
9268
+ */
9269
+ growBy(count) {
9270
+ if (!this._growStep) return this;
9271
+ const step = Number(count) > 0 ? Math.trunc(Number(count)) : this._growStep;
9272
+ const before = this._rendered;
9273
+ this._rendered = Math.min(this._data.length, this._rendered + step);
9274
+ if (this._rendered === before) return this;
9275
+ this._renderBody();
9276
+ this.emit("grow", { rendered: this._rendered, total: this._data.length });
9277
+ return this;
9278
+ }
9279
+ /**
9280
+ * Renders every remaining row.
9281
+ * @returns {this}
9282
+ * @fires Table#grow
9283
+ */
9284
+ showAll() {
9285
+ return this.growBy(this._data.length);
9286
+ }
9287
+ /**
9288
+ * How many rows are currently rendered.
9289
+ * @returns {number}
9290
+ */
9291
+ getRenderedCount() {
9292
+ return Math.min(this._rendered, this._data.length);
9293
+ }
9294
+ /**
9295
+ * Keeps the "show more" control in step with what is rendered.
9296
+ *
9297
+ * The control sits outside the table rather than in a `<tfoot>` row spanning every column: it is
9298
+ * a command, not data, and a button inside the grid would be reachable by the row navigation
9299
+ * keys as though it were a cell.
9300
+ * @returns {void}
9301
+ */
9302
+ _syncGrowing() {
9303
+ if (!this._growStep) return;
9304
+ const remaining = this._data.length - this.getRenderedCount();
9305
+ if (remaining <= 0) {
9306
+ this._more?.remove();
9307
+ this._more = null;
9308
+ return;
9309
+ }
9310
+ const label = this._message("table.more", "Show %1 more", [remaining]);
9311
+ if (!this._more) {
9312
+ this._more = h("button", {
9313
+ class: "zx-table__more",
9314
+ type: "button",
9315
+ onclick: () => this.growBy()
9316
+ });
9317
+ this.el.append(this._more);
9318
+ }
9319
+ this._more.textContent = label;
9320
+ this._more.setAttribute("aria-label", label);
9321
+ }
9322
+ /**
9323
+ * Resolves a localized message, falling back to a built-in template.
9324
+ * @param {string} key Message key.
9325
+ * @param {string} fallback Template used when the host has no translation.
9326
+ * @param {unknown[]} args Positional interpolation values.
9327
+ * @returns {string}
9328
+ */
9329
+ _message(key, fallback, args) {
9330
+ const message = this.msg(key, ...args);
9331
+ return message === key ? printf(fallback, args) : message;
9332
+ }
9333
+ /**
9334
+ * Watches the table's own width and stacks the rows below `responsive`.
9335
+ *
9336
+ * The width comes from `onBreakpoint` observing this element rather than the window, which is the
9337
+ * whole point of the option: a table inside a split pane or a modal has no idea how wide the
9338
+ * viewport is, and a media query would stack it on a phone while leaving it unreadable in a
9339
+ * 320px pane on a desktop.
9340
+ * @returns {void}
9341
+ */
9342
+ _watchWidth() {
9343
+ this._width?.destroy();
9344
+ this._width = null;
9345
+ const threshold = this.options.responsive;
9346
+ if (!threshold || !(threshold in breakpoints)) return;
9347
+ this._width = onBreakpoint(
9348
+ (_name, width) => this._setStacked(width > 0 && width < breakpoints[threshold]),
9349
+ { target: this.el }
9350
+ );
9351
+ }
9352
+ /**
9353
+ * Enters or leaves stacked mode.
9354
+ * @param {boolean} stacked Whether rows should stack.
9355
+ * @returns {void}
9356
+ * @fires Table#stackedchange
9357
+ */
9358
+ _setStacked(stacked) {
9359
+ if (this._stacked === stacked) return;
9360
+ this._stacked = stacked;
9361
+ this.el.toggleAttribute("data-stacked", stacked);
9362
+ this._applyStackedRoles(stacked);
9363
+ this.emit("stackedchange", { stacked });
9364
+ }
9365
+ /**
9366
+ * States the table roles explicitly while stacked, and removes them again on the way out.
9367
+ *
9368
+ * Stacking works by changing `display` on the table elements, and a table whose display is not
9369
+ * `table` loses its implicit ARIA roles — leaving a screen reader with a pile of generic blocks
9370
+ * where a table used to be. The roles are only asserted while the layout has taken them away.
9371
+ * @param {boolean} stacked Whether the roles should be present.
9372
+ * @returns {void}
9373
+ */
9374
+ _applyStackedRoles(stacked) {
9375
+ const parts = [[this._table, "table"], [this._thead, "rowgroup"], [this._tbody, "rowgroup"]];
9376
+ for (const [element, role] of parts) {
9377
+ if (!element) continue;
9378
+ if (stacked) element.setAttribute("role", role);
9379
+ else element.removeAttribute("role");
9380
+ }
9381
+ for (const [selector, role] of [["tr", "row"], ["td", "cell"], ["th", "columnheader"]]) {
9382
+ for (const element of this._table.querySelectorAll(selector)) {
9383
+ if (stacked) element.setAttribute("role", role);
9384
+ else element.removeAttribute("role");
9385
+ }
9386
+ }
9387
+ }
9388
+ /**
9389
+ * Reports whether the rows are currently stacked.
9390
+ * @returns {boolean}
9391
+ */
9392
+ isStacked() {
9393
+ return Boolean(this._stacked);
9394
+ }
9122
9395
  /** Restores an enhanced target and releases all component listeners. @returns {void} */
9123
9396
  destroy() {
9124
9397
  this._teardownEdit();
9398
+ this._width?.destroy();
9399
+ this._width = null;
9125
9400
  if (this.el) delete this.el.dataset.editMode;
9126
9401
  if (!this._restored && this._originalChildren) {
9127
9402
  this.el.replaceChildren(...this._originalChildren);
@@ -9149,6 +9424,7 @@ var Table = class extends Component {
9149
9424
  /** @returns {void} */
9150
9425
  _renderHeader() {
9151
9426
  const row = h("tr", { class: "zx-table__header-row" });
9427
+ if (this._growStep) row.setAttribute("aria-rowindex", "1");
9152
9428
  if (this.options.selectable === "multi") {
9153
9429
  this._selectAll = h("input", {
9154
9430
  class: "zx-table__checkbox zx-table__select-all",
@@ -9162,9 +9438,9 @@ var Table = class extends Component {
9162
9438
  row.append(selectionHeader);
9163
9439
  this.listen(this._selectAll, "click", () => {
9164
9440
  if (this._selectAll.checked) {
9165
- for (const dataRow of this._data) this._selected.add(this._idFor(dataRow));
9441
+ for (const dataRow of this._visibleData()) this._selected.add(this._idFor(dataRow));
9166
9442
  } else {
9167
- this._selected.clear();
9443
+ for (const dataRow of this._visibleData()) this._selected.delete(this._idFor(dataRow));
9168
9444
  }
9169
9445
  this._selectionAnchorId = null;
9170
9446
  this._syncSelection();
@@ -9206,17 +9482,36 @@ var Table = class extends Component {
9206
9482
  this._rovingCell = null;
9207
9483
  this._rovingMatched = false;
9208
9484
  if (this._data.length === 0) {
9209
- const text3 = this.options.emptyText == null ? this.msg("table.empty") : String(this.options.emptyText);
9210
9485
  fragment.append(h(
9211
9486
  "tr",
9212
9487
  { class: "zx-table__empty-row" },
9213
- h("td", { class: "zx-table__empty", colspan: this._columns.length + (this.options.selectable === "multi" ? 1 : 0) }, text3)
9488
+ h("td", {
9489
+ class: "zx-table__empty",
9490
+ colspan: this._columns.length + (this.options.selectable === "multi" ? 1 : 0)
9491
+ }, this._emptyContent())
9214
9492
  ));
9215
9493
  } else {
9216
- this._data.forEach((row, index) => fragment.append(this._createRow(row, index)));
9494
+ this._visibleData().forEach((row, index) => fragment.append(this._createRow(row, index)));
9217
9495
  }
9218
9496
  this._tbody.replaceChildren(fragment);
9497
+ if (this._growStep) this._table.setAttribute("aria-rowcount", String(this._data.length + 1));
9219
9498
  this._syncSelectAll();
9499
+ this._syncGrowing();
9500
+ if (this._stacked) this._applyStackedRoles(true);
9501
+ }
9502
+ /**
9503
+ * What to put in the empty row.
9504
+ *
9505
+ * An empty table is a screen in its own right — the place to say why there is nothing and what to
9506
+ * do about it — so this takes a node as readily as a string. A function is re-called on every
9507
+ * render, which matters when the placeholder contains a button: reusing one node would move the
9508
+ * same element between renders and quietly share its listeners.
9509
+ * @returns {Node|string}
9510
+ */
9511
+ _emptyContent() {
9512
+ const empty = this.options.emptyText;
9513
+ if (empty == null) return this.msg("table.empty");
9514
+ return typeof empty === "function" ? empty() : empty;
9220
9515
  }
9221
9516
  /** @param {TableRow} row @param {number} index @returns {HTMLTableRowElement} */
9222
9517
  _createRow(row, index) {
@@ -9225,6 +9520,7 @@ var Table = class extends Component {
9225
9520
  /** @type {HTMLTableRowElement} */
9226
9521
  h("tr", { dataset: { row: "" } })
9227
9522
  );
9523
+ if (this._growStep) tr.setAttribute("aria-rowindex", String(index + 2));
9228
9524
  const rowClass = typeof this.options.rowClass === "function" ? this.options.rowClass(row) : "";
9229
9525
  if (rowClass) tr.classList.add(...String(rowClass).split(/\s+/).filter(Boolean));
9230
9526
  if (this.options.selectable !== false) tr.setAttribute("aria-selected", String(this._selected.has(id)));
@@ -9247,6 +9543,8 @@ var Table = class extends Component {
9247
9543
  h("td")
9248
9544
  );
9249
9545
  if (column.align) cell.dataset.align = column.align;
9546
+ cell.dataset.label = column.label;
9547
+ if (column.popin === false) cell.dataset.popin = "false";
9250
9548
  if (this._editMode !== false) {
9251
9549
  cell.dataset.column = column.id;
9252
9550
  if (resolveEditable(column, row) !== false) {
@@ -9730,10 +10028,14 @@ var Table = class extends Component {
9730
10028
  /** @returns {void} */
9731
10029
  _syncSelectAll() {
9732
10030
  if (!this._selectAll) return;
9733
- const selectedRows = this._data.reduce((count, row) => count + Number(this._selected.has(this._idFor(row))), 0);
9734
- this._selectAll.disabled = this._data.length === 0;
9735
- this._selectAll.checked = this._data.length > 0 && selectedRows === this._data.length;
9736
- this._selectAll.indeterminate = selectedRows > 0 && selectedRows < this._data.length;
10031
+ const visible = this._visibleData();
10032
+ const selectedRows = visible.reduce(
10033
+ (count, row) => count + Number(this._selected.has(this._idFor(row))),
10034
+ 0
10035
+ );
10036
+ this._selectAll.disabled = visible.length === 0;
10037
+ this._selectAll.checked = visible.length > 0 && selectedRows === visible.length;
10038
+ this._selectAll.indeterminate = selectedRows > 0 && selectedRows < visible.length;
9737
10039
  }
9738
10040
  /** @returns {void} */
9739
10041
  _syncSortHeader() {
@@ -9865,6 +10167,10 @@ function assertRows(rows) {
9865
10167
  function sameSet(left, right) {
9866
10168
  return left.size === right.size && [...left].every((value) => right.has(value));
9867
10169
  }
10170
+ function growStep(growing) {
10171
+ const step = Math.trunc(Number(growing));
10172
+ return Number.isFinite(step) && step > 0 ? step : null;
10173
+ }
9868
10174
 
9869
10175
  // src/components/message/message.js
9870
10176
  var MessageQueue = class {