@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,198 @@
1
+ import { Http, Select as ZxSelect, zeyosService } from '../../index.js';
2
+ import { GxWrapper } from '../base.js';
3
+ import { LEGACY_EVENT_ARGS, translateSelectOptions } from './options.js';
4
+
5
+ /** Shared Select facade; concrete subclasses choose filtering and warning identity. */
6
+ class SelectBase extends GxWrapper {
7
+ static legacyName = 'gx.zeyos.Select';
8
+ /*
9
+ * Widened deliberately: the subclasses below set `'local' | 'async' | 'priority' | 'rest'`, and
10
+ * a static field annotated with that union would still clash with the `string` each subclass
11
+ * infers from its own literal. The static sides have to agree or the emitted declarations do
12
+ * not type-check for a consumer running without `skipLibCheck`.
13
+ */
14
+ /** @type {string|false} */
15
+ static filterMode = false;
16
+
17
+ /** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
18
+ constructor(display, options = {}) {
19
+ super(options, { data: [], elementIndex: 'ID', elementLabel: 'name', elementSelect: 'name', value: null });
20
+ const translated = translateSelectOptions(options);
21
+ translated.items = initialItems(options);
22
+ translated.valueKey = valueReader(options.elementIndex ?? 'ID');
23
+ translated.labelKey = labelReader(options.elementLabel ?? 'name');
24
+ translated.renderItem = typeof options.elementLabel === 'function' ? options.elementLabel : null;
25
+ translated.renderValue = selectionReader(options.elementSelect ?? options.elementLabel ?? 'name');
26
+ translated.value = options.value ?? null;
27
+ translated.filter = this.constructor.filterMode === 'local' ? 'local' :
28
+ (['async', 'rest'].includes(this.constructor.filterMode) ? (query) => this._load(query) : false);
29
+ translated.debounce = options.debounce ?? 200;
30
+ const component = this.constructor.filterMode === 'priority'
31
+ ? ZxSelect.priority(display, translated)
32
+ : new ZxSelect(display, translated);
33
+ this._attach(component, {
34
+ events: {
35
+ select: {
36
+ type: 'change', filter: (detail) => detail.item != null,
37
+ args: (detail) => LEGACY_EVENT_ARGS.select(detail, this)
38
+ },
39
+ noselect: {
40
+ type: 'change', filter: (detail) => detail.item == null,
41
+ args: (detail) => LEGACY_EVENT_ARGS.noselect(detail, this)
42
+ },
43
+ show: { type: 'open', args: () => [this] },
44
+ hide: { type: 'close', args: () => [this] },
45
+ requestSuccess: { type: 'loaded', args: (detail) => [detail.items] }
46
+ },
47
+ ui: { fieldset: 'control', textbox: 'input', dropdown: 'list', icon: 'toggle' },
48
+ setters: { data: 'setData', value: 'setId', disabled: (value) => value ? this.disable() : this.enable() }
49
+ });
50
+ this._http = null;
51
+ this.data = translated.items;
52
+ }
53
+
54
+ /** @param {unknown} selection @param {boolean} [noEvents=false] @returns {this} */
55
+ set(selection, noEvents = false) { this._zx.set(selection, { silent: Boolean(noEvents) }); return this; }
56
+ /** @param {unknown} id @param {boolean} [noEvents=false] @returns {this} */
57
+ setId(id, noEvents = false) {
58
+ const item = this.data?.find((candidate) => readValue(candidate, this.options.elementIndex ?? 'ID') == id);
59
+ this._zx.set(item ?? id, { silent: Boolean(noEvents) }); return this;
60
+ }
61
+ /** @param {unknown} [item] @returns {unknown} */
62
+ getId(item) { return item == null ? this._zx.value : readValue(item, this.options.elementIndex ?? 'ID'); }
63
+ /** @returns {unknown} */
64
+ getValue() { return this._zx.value; }
65
+ /** @returns {unknown} */
66
+ getSelected() { return this._zx.selected; }
67
+ /** @param {unknown[]} data @returns {this} */
68
+ setData(data) { this.data = Array.isArray(data) ? data.slice() : []; this._zx.setItems(this.data); return this; }
69
+ /** @returns {Element[]} */
70
+ getRows() { return Array.from(this.display('dropdown')?.querySelectorAll?.('[role="option"]') ?? []); }
71
+ /** @param {boolean} [noEvents=false] @returns {this} */
72
+ reset(noEvents = false) { this._zx.set(null, { silent: Boolean(noEvents) }); return this; }
73
+ /** @returns {this} */
74
+ enable() { this._zx.enable(); return this; }
75
+ /** @returns {this} */
76
+ disable() { this._zx.disable(); return this; }
77
+ /** @returns {this} */
78
+ show() { this._zx.open(); return this; }
79
+ /** @returns {this} */
80
+ hide() { this._zx.close(); return this; }
81
+ /** @returns {boolean} */
82
+ isOpen() { return this.toElement().getAttribute('data-state') === 'open'; }
83
+ /** @returns {this} */
84
+ search() { this._zx.open(); return this; }
85
+ /** @returns {this} */
86
+ showLoader() { return this; }
87
+ /** @returns {this} */
88
+ hideLoader() { return this; }
89
+
90
+ /** @param {string} query @returns {Promise<unknown[]>} */
91
+ async _load(query) {
92
+ try {
93
+ const result = this.constructor.filterMode === 'rest'
94
+ ? await this._loadRest(query)
95
+ : await this._loadUrl(query);
96
+ const rows = Array.isArray(result) ? result : [];
97
+ this.data = rows;
98
+ return rows;
99
+ } catch (error) {
100
+ this.fireEvent('requestFailure', [error]);
101
+ throw error;
102
+ }
103
+ }
104
+
105
+ /** @param {string} query @returns {Promise<unknown>} */
106
+ _loadUrl(query) {
107
+ this._http ??= new Http({ headers: this.options.requestHeader ?? {} });
108
+ const requestData = { ...(this.options.requestData ?? {}) };
109
+ const queryData = typeof this.options.queryParam === 'function'
110
+ ? this.options.queryParam(query, requestData)
111
+ : { ...requestData, [this.options.queryParam ?? 'query']: query };
112
+ const method = String(this.options.method ?? 'GET').toUpperCase();
113
+ return this._http.request(String(this.options.url ?? './'), method === 'GET'
114
+ ? { method, query: queryData }
115
+ : { method, data: queryData });
116
+ }
117
+
118
+ /** @param {string} query @returns {Promise<unknown>} */
119
+ _loadRest(query) {
120
+ this._http ??= zeyosService(String(this.options.entity ?? ''), String(this.options.accesskey ?? ''), {
121
+ apiBase: this.options.apiBase ?? '../remotecall/'
122
+ });
123
+ return this._http.get('', { ...(this.options.requestData ?? {}), search: query, limit: this.options.limit ?? 50 });
124
+ }
125
+ }
126
+
127
+ /** Legacy ZeyOS select. */
128
+ export class Select extends SelectBase { static legacyName = 'gx.zeyos.Select'; }
129
+ /** Legacy ZeyOS locally filterable select. */
130
+ export class SelectFilter extends SelectBase { static legacyName = 'gx.zeyos.SelectFilter'; static filterMode = 'local'; }
131
+ /** Legacy ZeyOS HTTP-backed select. */
132
+ export class SelectDyn extends SelectBase { static legacyName = 'gx.zeyos.SelectDyn'; static filterMode = 'async'; }
133
+ /** Legacy ZeyOS priority select. */
134
+ export class SelectPrio extends SelectBase { static legacyName = 'gx.zeyos.SelectPrio'; static filterMode = 'priority'; }
135
+
136
+ /** Legacy bootstrap select. */
137
+ export class BootstrapSelect extends SelectBase { static legacyName = 'gx.bootstrap.Select'; }
138
+ /** Legacy bootstrap locally filterable select. */
139
+ export class BootstrapSelectFilter extends SelectBase { static legacyName = 'gx.bootstrap.SelectFilter'; static filterMode = 'local'; }
140
+ /** Legacy bootstrap HTTP-backed select. */
141
+ export class BootstrapSelectDyn extends SelectBase { static legacyName = 'gx.bootstrap.SelectDyn'; static filterMode = 'async'; }
142
+ /** Legacy bootstrap REST-backed select. */
143
+ export class SelectDynREST extends SelectBase {
144
+ static legacyName = 'gx.bootstrap.SelectDynREST';
145
+ static filterMode = 'rest';
146
+
147
+ /** Loads and selects a REST item by ID when it is not already cached. @param {unknown} id @returns {Promise<void>} */
148
+ async setEntityId(id) {
149
+ const cached = this.data?.find((item) => Object.is(readValue(item, this.options.elementIndex ?? 'ID'), id));
150
+ if (cached) { this.set(cached); return; }
151
+ if (id == null || id === '') return;
152
+ try {
153
+ this._http ??= zeyosService(String(this.options.entity ?? ''), String(this.options.accesskey ?? ''), {
154
+ apiBase: this.options.apiBase ?? '../remotecall/'
155
+ });
156
+ const item = await this._http.get(String(id));
157
+ if (item) this.set(item);
158
+ } catch (error) {
159
+ this.fireEvent('requestFailure', [error]);
160
+ throw error;
161
+ }
162
+ }
163
+ }
164
+ /** Legacy bootstrap priority select. */
165
+ export class BootstrapSelectPrio extends SelectBase { static legacyName = 'gx.bootstrap.SelectPrio'; static filterMode = 'priority'; }
166
+
167
+ /** @param {Record<string, any>} options @returns {unknown[]} */
168
+ function initialItems(options) {
169
+ const items = Array.isArray(options.data) ? options.data.slice() : [];
170
+ return options.elementDefault == null ? items : [options.elementDefault, ...items];
171
+ }
172
+
173
+ /** @param {string|Function} reader @returns {string|Function} */
174
+ function valueReader(reader) {
175
+ return typeof reader === 'function' ? reader : String(reader);
176
+ }
177
+
178
+ /** @param {string|Function} reader @returns {string|Function} */
179
+ function labelReader(reader) {
180
+ if (typeof reader !== 'function') return String(reader);
181
+ return (item) => renderedText(reader(item));
182
+ }
183
+
184
+ /** @param {string|Function} reader @returns {(item: unknown) => string} */
185
+ function selectionReader(reader) {
186
+ return (item) => renderedText(readValue(item, reader));
187
+ }
188
+
189
+ /** @param {unknown} item @param {string|Function} reader @returns {unknown} */
190
+ function readValue(item, reader) {
191
+ return typeof reader === 'function' ? reader(item) : item?.[reader];
192
+ }
193
+
194
+ /** @param {unknown} value @returns {string} */
195
+ function renderedText(value) {
196
+ if (value?.nodeType) return value.textContent ?? '';
197
+ return String(value ?? '');
198
+ }
@@ -0,0 +1,26 @@
1
+ /** Creates a direct-construction stub with an actionable migration error. */
2
+ function migrationStub(legacyName, replacement) {
3
+ return class LegacyMigrationStub {
4
+ /** @throws {Error} Always; this API needs an explicit migration. */
5
+ constructor() {
6
+ throw new Error(`${legacyName} is not emulated by Zx; migrate to ${replacement}`);
7
+ }
8
+ };
9
+ }
10
+
11
+ /** Direct Settings subclassing is intentionally outside the compatibility contract. */
12
+ export const Settings = migrationStub('gx.core.Settings', 'plain option objects');
13
+ /** Direct Container subclassing is intentionally outside the compatibility contract. */
14
+ export const Container = migrationStub('gx.ui.Container', 'zx.Component');
15
+ /** Legacy collapse animation stub. */
16
+ export const Collapse = migrationStub('gx.ui.Collapse', 'CSS transitions');
17
+ /** Legacy blend animation stub. */
18
+ export const Blend = migrationStub('gx.ui.Blend', 'CSS transitions');
19
+ /** Legacy HUD stub. */
20
+ export const Hud = migrationStub('gx.ui.Hud', 'zx.Dialog');
21
+ /** Legacy toggling helper stub. */
22
+ export const Toggling = migrationStub('gx.ui.Toggling', 'zx.Toggle');
23
+ /** Legacy horizontal group stub. */
24
+ export const HGroup = migrationStub('gx.ui.HGroup', 'CSS layout');
25
+ /** Legacy templates stub. */
26
+ export const Templates = migrationStub('gx.ui.Templates', 'native template elements');
@@ -0,0 +1,113 @@
1
+ import { parse } from '../globals.js';
2
+
3
+ /** Legacy utility namespace backed by dependency-free implementations. */
4
+ export const util = Object.freeze({
5
+ initValue,
6
+ initNum,
7
+ formatTime,
8
+ getMinutes,
9
+ formatNum,
10
+ getNumber,
11
+ printf,
12
+ parseResult,
13
+ Parse: parse,
14
+ isArray: Array.isArray,
15
+ isObject: (value) => value !== null && typeof value === 'object' && !Array.isArray(value) &&
16
+ !(typeof Node !== 'undefined' && value instanceof Node) && !(value instanceof Date),
17
+ isFunction: (value) => typeof value === 'function',
18
+ isString: (value) => typeof value === 'string',
19
+ isNumber: (value) => typeof value === 'number' && Number.isFinite(value),
20
+ isElement: (value) => typeof Element !== 'undefined' && value instanceof Element,
21
+ isNode: (value) => typeof Node !== 'undefined' && value instanceof Node,
22
+ Console: (source, message) => {
23
+ if (typeof console === 'undefined') return;
24
+ if (message instanceof Error) console.error(source, message.stack);
25
+ else console.log(`${source}: ${message}`);
26
+ }
27
+ });
28
+
29
+ /** @param {Record<string, unknown>} object @param {string} key @param {unknown} fallback @returns {unknown} */
30
+ export function initValue(object, key, fallback) {
31
+ return object?.[key] == null ? fallback : object[key];
32
+ }
33
+
34
+ /** @param {unknown} value @returns {number} */
35
+ export function initNum(value) {
36
+ if (typeof value === 'number') return value;
37
+ if (typeof value === 'string') return Number.parseFloat(value);
38
+ return 0;
39
+ }
40
+
41
+ /** @param {unknown} value @returns {string} */
42
+ export function formatTime(value) {
43
+ let minutes = value;
44
+ if (typeof minutes === 'string') {
45
+ if (/^[0-9]+:[0-9]{2}$/.test(minutes)) return minutes;
46
+ if (/^[0-9]+:[0-9]{2,}$/.test(minutes)) {
47
+ const digits = minutes.replace(/[^0-9]/g, '');
48
+ return digits.replace(/([0-9]{2})$/, ':$1');
49
+ }
50
+ minutes = Number.parseInt(minutes.replace(/[^0-9]/g, ''), 10);
51
+ }
52
+ if (minutes == null || Number.isNaN(Number(minutes))) return '0:00';
53
+ let number = Number(minutes);
54
+ const prefix = number < 0 ? '-' : '';
55
+ number = Math.abs(number);
56
+ return `${prefix}${Math.floor(number / 60)}:${pad(number % 60)}`;
57
+ }
58
+
59
+ /** @param {unknown} value @returns {number} */
60
+ export function getMinutes(value) {
61
+ const parts = String(value ?? '').replace(/[^0-9:]/, '').split(':');
62
+ if (parts.length === 1) return Number.parseInt(parts[0], 10);
63
+ return Number.parseInt(parts[0], 10) * 60 + Number.parseInt(parts[1], 10);
64
+ }
65
+
66
+ /** @param {unknown} value @param {string} [decimal='.'] @param {string} [thousands=','] @param {number} [decimals=2] @returns {string} */
67
+ export function formatNum(value, decimal = '.', thousands = ',', decimals = 2) {
68
+ let number = value;
69
+ if (typeof number === 'string') {
70
+ number = Number.parseFloat(number.replace(new RegExp(`[^0-9${escapeRegExp(decimal)}]`), '').replace(decimal, '.'));
71
+ }
72
+ if (Number.isNaN(Number(number))) number = 0;
73
+ const precision = typeof decimals === 'number' ? decimals : 2;
74
+ let formatted = Math.round(Number(number) * (10 ** precision)).toString();
75
+ for (let index = formatted.length; index <= precision; index += 1) formatted = `0${formatted}`;
76
+ const position = formatted.length - precision;
77
+ if (precision > 0) formatted = `${formatted.slice(0, position)}${decimal}${formatted.slice(position)}`;
78
+ for (let index = position - 3; index > 0; index -= 3) {
79
+ formatted = `${formatted.slice(0, index)}${thousands}${formatted.slice(index)}`;
80
+ }
81
+ return formatted;
82
+ }
83
+
84
+ /** @param {unknown} value @param {string} [decimal=','] @returns {number} */
85
+ export function getNumber(value, decimal = '.') {
86
+ return Number.parseFloat(String(value ?? '').replace(new RegExp(`[^0-9${escapeRegExp(decimal)}]`), '').replace(decimal, '.'));
87
+ }
88
+
89
+ /** @param {unknown} template @param {unknown|unknown[]} [values=[]] @returns {string} */
90
+ export function printf(template, values = []) {
91
+ const replacements = Array.isArray(values) ? values : [values];
92
+ let index = 0;
93
+ return String(template ?? '').replace(/%arg%/g, (match) => index < replacements.length ? String(replacements[index++]) : match);
94
+ }
95
+
96
+ /** @param {unknown} response @returns {unknown} */
97
+ export function parseResult(response) {
98
+ const data = typeof response === 'string' ? JSON.parse(response) : response;
99
+ if (!data || typeof data !== 'object') throw new Error('Invalid server response');
100
+ if (data.error) throw new Error(String(data.error.message ?? data.error));
101
+ if (!Object.hasOwn(data, 'result') || data.result == null) throw new Error('Undefined result');
102
+ return data.result;
103
+ }
104
+
105
+ /** @param {number} value @returns {string} */
106
+ function pad(value) {
107
+ return String(value).padStart(2, '0');
108
+ }
109
+
110
+ /** @param {string} value @returns {string} */
111
+ function escapeRegExp(value) {
112
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
113
+ }
@@ -0,0 +1,11 @@
1
+ /** Browser entry point for the gx compatibility bundle. */
2
+ import * as zx from './index.js';
3
+ import gx, { install, installElementStorage } from './compat/index.js';
4
+
5
+ const host = typeof window === 'undefined' ? globalThis : window;
6
+ installElementStorage(host);
7
+ install(host);
8
+ host.zx = zx;
9
+
10
+ export { gx, zx };
11
+ export default gx;
@@ -0,0 +1,147 @@
1
+ .zx-badge {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--zx-space-1);
5
+ max-inline-size: 100%;
6
+ border: 1px solid transparent;
7
+ border-radius: var(--zx-radius-full);
8
+ background: var(--zx-color-bg-muted);
9
+ color: var(--zx-color-text-muted);
10
+ padding-block: 2px;
11
+ padding-inline: var(--zx-space-2);
12
+ font-size: var(--zx-text-xs);
13
+ font-weight: 600;
14
+ font-variant-numeric: tabular-nums;
15
+ line-height: 1.35;
16
+ white-space: nowrap;
17
+ vertical-align: middle;
18
+ }
19
+
20
+ .zx-badge__label {
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ }
24
+
25
+ .zx-badge__dot {
26
+ flex: none;
27
+ inline-size: 6px;
28
+ block-size: 6px;
29
+ border-radius: var(--zx-radius-full);
30
+ background: currentColor;
31
+ }
32
+
33
+ .zx-badge .zx-icon {
34
+ flex: none;
35
+ }
36
+
37
+ /* Soft — the default: a tinted fill with the intent colour as text. */
38
+ .zx-badge[data-kind="accent"] {
39
+ background: var(--zx-color-accent-subtle);
40
+ color: var(--zx-color-accent);
41
+ }
42
+
43
+ .zx-badge[data-kind="success"] {
44
+ background: var(--zx-color-success-bg);
45
+ color: var(--zx-color-success);
46
+ }
47
+
48
+ .zx-badge[data-kind="warning"] {
49
+ background: var(--zx-color-warning-bg);
50
+ color: var(--zx-color-warning);
51
+ }
52
+
53
+ .zx-badge[data-kind="danger"] {
54
+ background: var(--zx-color-danger-bg);
55
+ color: var(--zx-color-danger);
56
+ }
57
+
58
+ .zx-badge[data-kind="info"] {
59
+ background: var(--zx-color-info-bg);
60
+ color: var(--zx-color-info);
61
+ }
62
+
63
+ /* Solid — the intent colour as fill, with the on-accent text colour of the active theme. */
64
+ .zx-badge[data-variant="solid"] {
65
+ background: var(--zx-color-text-muted);
66
+ color: var(--zx-color-bg-surface);
67
+ }
68
+
69
+ .zx-badge[data-variant="solid"][data-kind="accent"] {
70
+ background: var(--zx-color-accent);
71
+ color: var(--zx-color-on-accent);
72
+ }
73
+
74
+ .zx-badge[data-variant="solid"][data-kind="success"] {
75
+ background: var(--zx-color-success);
76
+ color: var(--zx-color-on-accent);
77
+ }
78
+
79
+ .zx-badge[data-variant="solid"][data-kind="warning"] {
80
+ background: var(--zx-color-warning);
81
+ color: var(--zx-color-on-accent);
82
+ }
83
+
84
+ .zx-badge[data-variant="solid"][data-kind="danger"] {
85
+ background: var(--zx-color-danger);
86
+ color: var(--zx-color-on-accent);
87
+ }
88
+
89
+ .zx-badge[data-variant="solid"][data-kind="info"] {
90
+ background: var(--zx-color-info);
91
+ color: var(--zx-color-on-accent);
92
+ }
93
+
94
+ /* Outline — no fill, the intent colour on the border and the text. */
95
+ .zx-badge[data-variant="outline"] {
96
+ border-color: var(--zx-color-border-strong);
97
+ background: transparent;
98
+ color: var(--zx-color-text-muted);
99
+ }
100
+
101
+ .zx-badge[data-variant="outline"][data-kind="accent"],
102
+ .zx-badge[data-variant="outline"][data-kind="success"],
103
+ .zx-badge[data-variant="outline"][data-kind="warning"],
104
+ .zx-badge[data-variant="outline"][data-kind="danger"],
105
+ .zx-badge[data-variant="outline"][data-kind="info"] {
106
+ border-color: currentColor;
107
+ background: transparent;
108
+ }
109
+
110
+ .zx-badge[data-variant="outline"][data-kind="accent"] {
111
+ color: var(--zx-color-accent);
112
+ }
113
+
114
+ .zx-badge[data-variant="outline"][data-kind="success"] {
115
+ color: var(--zx-color-success);
116
+ }
117
+
118
+ .zx-badge[data-variant="outline"][data-kind="warning"] {
119
+ color: var(--zx-color-warning);
120
+ }
121
+
122
+ .zx-badge[data-variant="outline"][data-kind="danger"] {
123
+ color: var(--zx-color-danger);
124
+ }
125
+
126
+ .zx-badge[data-variant="outline"][data-kind="info"] {
127
+ color: var(--zx-color-info);
128
+ }
129
+
130
+ .zx-badge[data-size="sm"] {
131
+ gap: calc(var(--zx-space-1) / 2);
132
+ padding-block: 1px;
133
+ padding-inline: var(--zx-space-1);
134
+ font-size: calc(var(--zx-text-xs) - 1px);
135
+ }
136
+
137
+ .zx-badge[data-size="sm"] .zx-badge__dot {
138
+ inline-size: 5px;
139
+ block-size: 5px;
140
+ }
141
+
142
+ .zx-badge-group {
143
+ display: inline-flex;
144
+ flex-wrap: wrap;
145
+ align-items: center;
146
+ gap: var(--zx-space-1);
147
+ }
@@ -0,0 +1,92 @@
1
+ import { h } from '../../core/dom.js';
2
+ import { icon as createIcon } from '../../core/icons.js';
3
+
4
+ /**
5
+ * @typedef {Object} BadgeOptions
6
+ * @property {string} [label=''] Visible badge text.
7
+ * @property {string|null} [icon=null] Icon name from `icons.js`, rendered before the label.
8
+ * @property {'neutral'|'accent'|'success'|'warning'|'danger'|'info'} [kind='neutral'] Semantic intent.
9
+ * @property {'soft'|'solid'|'outline'} [variant='soft'] Fill treatment.
10
+ * @property {'md'|'sm'} [size='md'] Badge size.
11
+ * @property {boolean} [dot=false] Renders a small leading status dot instead of an icon.
12
+ * @property {string} [title] Native title text; also names an icon-only or dot-only badge.
13
+ */
14
+
15
+ /** Badge intents, in the order they are documented. */
16
+ const KINDS = Object.freeze(['neutral', 'accent', 'success', 'warning', 'danger', 'info']);
17
+
18
+ /** Fill treatments. */
19
+ const VARIANTS = Object.freeze(['soft', 'solid', 'outline']);
20
+
21
+ /** @type {Readonly<BadgeOptions>} */
22
+ const defaults = Object.freeze({
23
+ label: '',
24
+ icon: null,
25
+ kind: 'neutral',
26
+ variant: 'soft',
27
+ size: 'md',
28
+ dot: false
29
+ });
30
+
31
+ /**
32
+ * Creates a status pill: a small, non-interactive label carrying a semantic colour.
33
+ *
34
+ * The badge is plain text content, so it needs no ARIA of its own. A badge without a label but
35
+ * with a `title` is named for assistive technology through `role="img"`.
36
+ *
37
+ * @param {BadgeOptions} [opts={}] Badge options.
38
+ * @returns {HTMLSpanElement}
39
+ */
40
+ export function badge(opts = {}) {
41
+ const options = { ...defaults, ...opts };
42
+ const element = /** @type {HTMLSpanElement} */ (h('span', {
43
+ class: 'zx-badge',
44
+ title: options.title,
45
+ dataset: {
46
+ kind: normalizeKind(options.kind),
47
+ variant: normalizeVariant(options.variant),
48
+ size: normalizeSize(options.size)
49
+ }
50
+ }));
51
+
52
+ if (options.dot) {
53
+ element.append(h('span', { class: 'zx-badge__dot', ariaHidden: 'true' }));
54
+ } else if (options.icon) {
55
+ element.append(createIcon(options.icon, { size: 12, class: 'zx-badge__icon' }));
56
+ }
57
+ if (options.label !== '' && options.label != null) {
58
+ element.append(h('span', { class: 'zx-badge__label' }, String(options.label)));
59
+ } else if (options.title) {
60
+ element.setAttribute('role', 'img');
61
+ element.setAttribute('aria-label', options.title);
62
+ }
63
+ return element;
64
+ }
65
+
66
+ /**
67
+ * Groups badges into a wrapping row.
68
+ * @param {HTMLSpanElement[]} badges Badges to group.
69
+ * @returns {HTMLSpanElement}
70
+ */
71
+ export function badgeGroup(badges) {
72
+ const group = /** @type {HTMLSpanElement} */ (h('span', { class: 'zx-badge-group' }));
73
+ group.append(...badges);
74
+ return group;
75
+ }
76
+
77
+ /** @param {unknown} value @returns {'neutral'|'accent'|'success'|'warning'|'danger'|'info'} */
78
+ function normalizeKind(value) {
79
+ return KINDS.includes(/** @type {string} */ (value)) ?
80
+ /** @type {'neutral'|'accent'|'success'|'warning'|'danger'|'info'} */ (value) : 'neutral';
81
+ }
82
+
83
+ /** @param {unknown} value @returns {'soft'|'solid'|'outline'} */
84
+ function normalizeVariant(value) {
85
+ return VARIANTS.includes(/** @type {string} */ (value)) ?
86
+ /** @type {'soft'|'solid'|'outline'} */ (value) : 'soft';
87
+ }
88
+
89
+ /** @param {unknown} value @returns {'md'|'sm'} */
90
+ function normalizeSize(value) {
91
+ return value === 'sm' ? 'sm' : 'md';
92
+ }