@zeyos/zx 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/DESIGN-SYSTEM.md +136 -0
  3. package/MIGRATION.md +155 -4
  4. package/README.md +24 -13
  5. package/dist/types/compat/map/data.d.ts +3 -2
  6. package/dist/types/components/account-menu/account-menu.d.ts +144 -0
  7. package/dist/types/components/app-rail/app-rail.d.ts +250 -0
  8. package/dist/types/components/app-sidebar/app-sidebar.d.ts +169 -0
  9. package/dist/types/components/avatar/avatar.d.ts +100 -0
  10. package/dist/types/components/chart/chart.d.ts +321 -0
  11. package/dist/types/components/date-picker/month-picker.d.ts +6 -0
  12. package/dist/types/components/dialog/dialog.d.ts +9 -0
  13. package/dist/types/components/dock/dock.d.ts +495 -0
  14. package/dist/types/components/dropdown/dropdown.d.ts +2 -2
  15. package/dist/types/components/field/field.d.ts +14 -0
  16. package/dist/types/components/field-upload/field-upload.d.ts +37 -4
  17. package/dist/types/components/form/form.d.ts +25 -3
  18. package/dist/types/components/grid/grid.d.ts +172 -0
  19. package/dist/types/components/launcher/launcher.d.ts +300 -0
  20. package/dist/types/components/layout/layout.d.ts +4 -4
  21. package/dist/types/components/menu-button/menu-button.d.ts +10 -2
  22. package/dist/types/components/modal/modal.d.ts +25 -0
  23. package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +7 -1
  24. package/dist/types/components/questionnaire/items.d.ts +327 -0
  25. package/dist/types/components/questionnaire/questionnaire.d.ts +449 -0
  26. package/dist/types/components/sheet/sheet-stack.d.ts +167 -0
  27. package/dist/types/components/sheet/sheet.d.ts +294 -0
  28. package/dist/types/components/split-view/split-view.d.ts +2 -21
  29. package/dist/types/components/table/table.d.ts +219 -12
  30. package/dist/types/components/tooltip/tooltip.d.ts +2 -2
  31. package/dist/types/components/value-list/value-list.d.ts +24 -3
  32. package/dist/types/core/dom.d.ts +114 -0
  33. package/dist/types/core/drag-axis.d.ts +111 -0
  34. package/dist/types/core/position.d.ts +4 -2
  35. package/dist/types/index.d.ts +12 -2
  36. package/dist/zx-compat.esm.js +641 -277
  37. package/dist/zx-compat.esm.min.js +1 -1
  38. package/dist/zx-compat.global.js +7609 -2236
  39. package/dist/zx-compat.global.min.js +3 -3
  40. package/dist/zx-zeyos.esm.js +546 -87
  41. package/dist/zx-zeyos.esm.min.js +1 -1
  42. package/dist/zx.css +1452 -101
  43. package/dist/zx.esm.js +7952 -2592
  44. package/dist/zx.esm.min.js +3 -3
  45. package/dist/zx.global.js +7952 -2592
  46. package/dist/zx.global.min.js +3 -3
  47. package/dist/zx.min.css +1 -1
  48. package/docs/api.json +2276 -337
  49. package/docs/llms.md +426 -30
  50. package/docs/llms.txt +21 -9
  51. package/package.json +4 -2
  52. package/src/compat/globals.js +3 -1
  53. package/src/compat/map/data.js +31 -9
  54. package/src/components/account-menu/account-menu.css +70 -0
  55. package/src/components/account-menu/account-menu.js +208 -0
  56. package/src/components/app-rail/app-rail.css +107 -0
  57. package/src/components/app-rail/app-rail.js +668 -0
  58. package/src/components/app-sidebar/app-sidebar.css +68 -0
  59. package/src/components/app-sidebar/app-sidebar.js +388 -0
  60. package/src/components/avatar/avatar.css +61 -0
  61. package/src/components/avatar/avatar.js +222 -0
  62. package/src/components/button/button.css +0 -1
  63. package/src/components/chart/chart.css +61 -0
  64. package/src/components/chart/chart.js +518 -0
  65. package/src/components/date-picker/month-picker.js +9 -0
  66. package/src/components/dialog/dialog.js +11 -4
  67. package/src/components/dock/dock.css +228 -0
  68. package/src/components/dock/dock.js +977 -0
  69. package/src/components/dropdown/dropdown.js +1 -1
  70. package/src/components/field/field.js +2 -0
  71. package/src/components/field-upload/field-upload.js +9 -4
  72. package/src/components/form/form.js +6 -3
  73. package/src/components/grid/grid.css +6 -0
  74. package/src/components/grid/grid.js +213 -0
  75. package/src/components/launcher/launcher.css +100 -0
  76. package/src/components/launcher/launcher.js +557 -0
  77. package/src/components/layout/layout.js +2 -2
  78. package/src/components/menu-button/menu-button.js +27 -2
  79. package/src/components/modal/modal.css +5 -1
  80. package/src/components/modal/modal.js +37 -2
  81. package/src/components/multi-value-editor/multi-value-editor.js +2 -1
  82. package/src/components/questionnaire/items.js +370 -0
  83. package/src/components/questionnaire/questionnaire.css +387 -0
  84. package/src/components/questionnaire/questionnaire.js +1033 -0
  85. package/src/components/select/select.css +0 -1
  86. package/src/components/sheet/sheet-stack.js +304 -0
  87. package/src/components/sheet/sheet.css +351 -0
  88. package/src/components/sheet/sheet.js +551 -0
  89. package/src/components/split-view/split-view.js +76 -161
  90. package/src/components/table/table.css +43 -0
  91. package/src/components/table/table.js +523 -45
  92. package/src/components/tooltip/tooltip.js +5 -2
  93. package/src/components/value-list/value-list.js +6 -3
  94. package/src/core/dom.js +302 -0
  95. package/src/core/drag-axis.js +203 -0
  96. package/src/core/position.js +68 -22
  97. package/src/index.js +19 -2
  98. package/styles/tokens/dark.css +2 -3
  99. package/styles/tokens/global.css +5 -5
  100. package/styles/tokens/semantic.css +5 -3
  101. package/styles/tokens/themes.css +1 -1
  102. package/styles/zx.css +10 -1
  103. package/dist/types/components/permission/permission.d.ts +0 -96
  104. package/src/components/permission/permission.css +0 -47
  105. package/src/components/permission/permission.js +0 -201
@@ -347,7 +347,7 @@ function parse(source) {
347
347
  }
348
348
  function installGlobals(host = globalThis) {
349
349
  installElementStorage(host);
350
- host.__ = parse;
350
+ if (host.__ === void 0) host.__ = parse;
351
351
  const stringPrototype = host.String?.prototype;
352
352
  if (stringPrototype && typeof stringPrototype.htmlSpecialChars !== "function") {
353
353
  Object.defineProperty(stringPrototype, "htmlSpecialChars", {
@@ -2838,6 +2838,14 @@ var MonthPicker = class extends DatePicker {
2838
2838
  static cssName = "month-picker";
2839
2839
  /** @type {MonthPickerOptions} */
2840
2840
  static defaults = { value: null, min: null, max: null };
2841
+ /**
2842
+ * Creates a month picker with its narrower month-based option contract.
2843
+ * @param {Element|string|null} target Existing element, selector, or null.
2844
+ * @param {MonthPickerOptions} [options={}] Month-picker options.
2845
+ */
2846
+ constructor(target, options = {}) {
2847
+ super(target, options);
2848
+ }
2841
2849
  /** @returns {HTMLElement} */
2842
2850
  render() {
2843
2851
  const root = (
@@ -3057,7 +3065,13 @@ var PLACEMENTS = /* @__PURE__ */ new Set([
3057
3065
  "top-start",
3058
3066
  "top-end",
3059
3067
  "bottom",
3060
- "top"
3068
+ "top",
3069
+ "right-start",
3070
+ "right-end",
3071
+ "left-start",
3072
+ "left-end",
3073
+ "right",
3074
+ "left"
3061
3075
  ]);
3062
3076
  function position(anchor, floating, options = {}) {
3063
3077
  if (!(anchor instanceof Element) || !(floating instanceof HTMLElement)) {
@@ -3085,13 +3099,15 @@ function position(anchor, floating, options = {}) {
3085
3099
  floating.style.inset = "auto";
3086
3100
  floating.style.margin = "0";
3087
3101
  floating.style.setProperty("position-anchor", anchorName);
3088
- floating.style.setProperty("position-area", positionArea(placement));
3089
- floating.style.setProperty("inset-area", positionArea(placement));
3102
+ const area = positionArea(placement, getComputedStyle(anchor).direction === "rtl");
3103
+ floating.style.setProperty("position-area", area);
3104
+ floating.style.setProperty("inset-area", area);
3090
3105
  floating.style.setProperty(
3091
3106
  "position-try-fallbacks",
3092
3107
  flip ? "flip-block, flip-inline, flip-block flip-inline" : "none"
3093
3108
  );
3094
- floating.style.setProperty(placement.startsWith("top") ? "margin-block-end" : "margin-block-start", `${offset}px`);
3109
+ const margin = placement.startsWith("top") ? "margin-bottom" : placement.startsWith("bottom") ? "margin-top" : placement.startsWith("left") ? "margin-right" : "margin-left";
3110
+ floating.style.setProperty(margin, `${offset}px`);
3095
3111
  update = () => {
3096
3112
  if (matchWidth) floating.style.minWidth = `${anchor.getBoundingClientRect().width}px`;
3097
3113
  };
@@ -3135,14 +3151,20 @@ function position(anchor, floating, options = {}) {
3135
3151
  }
3136
3152
  };
3137
3153
  }
3138
- function positionArea(placement) {
3154
+ function positionArea(placement, rtl) {
3139
3155
  return {
3140
- "bottom-start": "block-end span-inline-end",
3141
- "bottom-end": "block-end span-inline-start",
3142
- "top-start": "block-start span-inline-end",
3143
- "top-end": "block-start span-inline-start",
3144
- bottom: "block-end",
3145
- top: "block-start"
3156
+ "bottom-start": rtl ? "bottom span-left" : "bottom span-right",
3157
+ "bottom-end": rtl ? "bottom span-right" : "bottom span-left",
3158
+ "top-start": rtl ? "top span-left" : "top span-right",
3159
+ "top-end": rtl ? "top span-right" : "top span-left",
3160
+ "right-start": "right span-bottom",
3161
+ "right-end": "right span-top",
3162
+ "left-start": "left span-bottom",
3163
+ "left-end": "left span-top",
3164
+ bottom: "bottom",
3165
+ top: "top",
3166
+ right: "right",
3167
+ left: "left"
3146
3168
  }[placement];
3147
3169
  }
3148
3170
  function updateFallback(anchor, floating, { placement, offset, flip, matchWidth }) {
@@ -3152,26 +3174,54 @@ function updateFallback(anchor, floating, { placement, offset, flip, matchWidth
3152
3174
  const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
3153
3175
  const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
3154
3176
  let actualPlacement = placement;
3155
- const prefersBottom = placement.startsWith("bottom");
3177
+ const side = placementSide(placement);
3156
3178
  const bottomY = anchorRect.bottom + offset;
3157
3179
  const topY = anchorRect.top - offset - floatingRect.height;
3180
+ const rightX = anchorRect.right + offset;
3181
+ const leftX = anchorRect.left - offset - floatingRect.width;
3158
3182
  if (flip) {
3159
- if (prefersBottom && bottomY + floatingRect.height > viewportHeight && topY >= 0) {
3160
- actualPlacement = /** @type {typeof placement} */
3161
- placement.replace("bottom", "top");
3162
- } else if (!prefersBottom && topY < 0 && bottomY + floatingRect.height <= viewportHeight) {
3163
- actualPlacement = /** @type {typeof placement} */
3164
- placement.replace("top", "bottom");
3183
+ if (side === "bottom" && bottomY + floatingRect.height > viewportHeight && topY >= 0) {
3184
+ actualPlacement = flipPlacement(placement, "bottom", "top");
3185
+ } else if (side === "top" && topY < 0 && bottomY + floatingRect.height <= viewportHeight) {
3186
+ actualPlacement = flipPlacement(placement, "top", "bottom");
3187
+ } else if (side === "right" && rightX + floatingRect.width > viewportWidth && leftX >= 0) {
3188
+ actualPlacement = flipPlacement(placement, "right", "left");
3189
+ } else if (side === "left" && leftX < 0 && rightX + floatingRect.width <= viewportWidth) {
3190
+ actualPlacement = flipPlacement(placement, "left", "right");
3165
3191
  }
3166
3192
  }
3193
+ const actualSide = placementSide(actualPlacement);
3167
3194
  let left;
3168
- if (actualPlacement.endsWith("-end")) left = anchorRect.right - floatingRect.width;
3169
- else if (actualPlacement.endsWith("-start")) left = anchorRect.left;
3170
- else left = anchorRect.left + (anchorRect.width - floatingRect.width) / 2;
3171
- const top = actualPlacement.startsWith("bottom") ? bottomY : topY;
3195
+ let top;
3196
+ if (actualSide === "bottom" || actualSide === "top") {
3197
+ const rtl = getComputedStyle(anchor).direction === "rtl";
3198
+ if (actualPlacement.endsWith("-end")) {
3199
+ left = rtl ? anchorRect.left : anchorRect.right - floatingRect.width;
3200
+ } else if (actualPlacement.endsWith("-start")) {
3201
+ left = rtl ? anchorRect.right - floatingRect.width : anchorRect.left;
3202
+ } else left = anchorRect.left + (anchorRect.width - floatingRect.width) / 2;
3203
+ top = actualSide === "bottom" ? bottomY : topY;
3204
+ } else {
3205
+ left = actualSide === "right" ? rightX : leftX;
3206
+ if (actualPlacement.endsWith("-end")) top = anchorRect.bottom - floatingRect.height;
3207
+ else if (actualPlacement.endsWith("-start")) top = anchorRect.top;
3208
+ else top = anchorRect.top + (anchorRect.height - floatingRect.height) / 2;
3209
+ }
3172
3210
  floating.style.left = `${Math.round(clamp(left, 0, Math.max(0, viewportWidth - floatingRect.width)))}px`;
3173
3211
  floating.style.top = `${Math.round(clamp(top, 0, Math.max(0, viewportHeight - floatingRect.height)))}px`;
3174
3212
  }
3213
+ function placementSide(placement) {
3214
+ return (
3215
+ /** @type {'top'|'bottom'|'left'|'right'} */
3216
+ placement.split("-")[0]
3217
+ );
3218
+ }
3219
+ function flipPlacement(placement, from, to) {
3220
+ return (
3221
+ /** @type {Placement} */
3222
+ placement.replace(from, to)
3223
+ );
3224
+ }
3175
3225
  function showPopover(element) {
3176
3226
  if (typeof element.showPopover !== "function") return;
3177
3227
  try {
@@ -4004,31 +4054,31 @@ var PLACEHOLDER_TOKENS = {
4004
4054
  "%Y": "YYYY",
4005
4055
  "%y": "YY"
4006
4056
  };
4007
- function parseRangeText(text3, format, separator) {
4057
+ function parseRangeText(text3, format2, separator) {
4008
4058
  const source = String(text3 ?? "").trim();
4009
4059
  if (source === "") return { start: null, end: null };
4010
4060
  const raw2 = String(separator ?? " \u2013 ");
4011
4061
  const core = raw2.trim();
4012
- const strict = core !== "" && String(format).includes(core) && /^\s|\s$/.test(raw2);
4062
+ const strict = core !== "" && String(format2).includes(core) && /^\s|\s$/.test(raw2);
4013
4063
  const lead = strict ? "\\s+" : "\\s*";
4014
4064
  const tail = strict ? "(?:\\s+|$)" : "\\s*";
4015
4065
  const parts = core === "" ? [source] : source.split(new RegExp(`${lead}${escapeRegExp(core)}${tail}`));
4016
4066
  if (parts.length > 2) return null;
4017
- const first = parseDate(parts[0].trim(), format);
4067
+ const first = parseDate(parts[0].trim(), format2);
4018
4068
  if (!first) return null;
4019
4069
  if (parts.length === 1) return { start: first, end: new Date(first.getTime()) };
4020
4070
  if (parts[1].trim() === "") return { start: first, end: null };
4021
- const second = parseDate(parts[1].trim(), format);
4071
+ const second = parseDate(parts[1].trim(), format2);
4022
4072
  if (!second) return null;
4023
4073
  return normalizeRange(first, second);
4024
4074
  }
4025
- function formatRangeText(range, format, separator) {
4075
+ function formatRangeText(range, format2, separator) {
4026
4076
  const start = range?.start ?? null;
4027
4077
  const end = range?.end ?? null;
4028
4078
  if (!start && !end) return "";
4029
- if (!end) return formatDate(start, format);
4030
- if (!start) return formatDate(end, format);
4031
- return `${formatDate(start, format)}${separator}${formatDate(end, format)}`;
4079
+ if (!end) return formatDate(start, format2);
4080
+ if (!start) return formatDate(end, format2);
4081
+ return `${formatDate(start, format2)}${separator}${formatDate(end, format2)}`;
4032
4082
  }
4033
4083
  var DateRangeBox = class extends Component {
4034
4084
  static cssName = "date-range-box";
@@ -4686,12 +4736,12 @@ var DateTimeBox = function DateTimeBox2(target, options = {}) {
4686
4736
  function validDate4(value) {
4687
4737
  return value instanceof Date && !Number.isNaN(value.getTime()) ? new Date(value.getTime()) : null;
4688
4738
  }
4689
- function effectiveFormat(format, time) {
4690
- const value = String(format || "%d.%m.%Y");
4739
+ function effectiveFormat(format2, time) {
4740
+ const value = String(format2 || "%d.%m.%Y");
4691
4741
  return time && !/%[HM]/.test(value) ? `${value} %H:%M` : value;
4692
4742
  }
4693
- function placeholderFromFormat(format) {
4694
- return format.replace(/%[demYyHMS]/g, (token) => ({
4743
+ function placeholderFromFormat(format2) {
4744
+ return format2.replace(/%[demYyHMS]/g, (token) => ({
4695
4745
  "%d": "DD",
4696
4746
  "%e": "D",
4697
4747
  "%m": "MM",
@@ -8263,9 +8313,9 @@ var TagPicker = class extends Component {
8263
8313
  function normalizeLabel(value) {
8264
8314
  return String(value ?? "").trim().toLocaleLowerCase();
8265
8315
  }
8266
- function sameSelection(a, b, read2) {
8316
+ function sameSelection(a, b, read) {
8267
8317
  if (a.length !== b.length) return false;
8268
- return a.every((item, index) => Object.is(read2(item), read2(b[index])));
8318
+ return a.every((item, index) => Object.is(read(item), read(b[index])));
8269
8319
  }
8270
8320
 
8271
8321
  // src/components/tag-picker/field-adapter.js
@@ -9235,6 +9285,82 @@ function isFileList(value) {
9235
9285
  return typeof FileList === "function" && value instanceof FileList;
9236
9286
  }
9237
9287
 
9288
+ // src/core/format.js
9289
+ var MIN_DIGITS = 0;
9290
+ var MAX_DIGITS = 20;
9291
+ var DEFAULT_MAX_DIGITS = 3;
9292
+ var numberFormatters = /* @__PURE__ */ new Map();
9293
+ function formatNumber(value, options = {}) {
9294
+ const number = toFiniteNumber(value);
9295
+ if (number === null) return "";
9296
+ const { locale = getLanguage(), decimals, minDecimals, maxDecimals, group = true } = options;
9297
+ return format(locale, digitOptions({ decimals, minDecimals, maxDecimals, group }), number);
9298
+ }
9299
+ function formatCurrency(value, currency, options = {}) {
9300
+ const number = toFiniteNumber(value);
9301
+ if (number === null) return "";
9302
+ const { locale = getLanguage(), decimals } = options;
9303
+ const code = currencyCode(currency);
9304
+ if (code === null) return formatNumber(number, { locale, decimals });
9305
+ const digits = digitOptions({ decimals, group: true });
9306
+ return format(locale, { ...digits, style: "currency", currency: code }, number);
9307
+ }
9308
+ function formatPercent(value, options = {}) {
9309
+ const number = toFiniteNumber(value);
9310
+ if (number === null) return "";
9311
+ const { locale = getLanguage(), decimals = 0 } = options;
9312
+ return format(locale, { ...digitOptions({ decimals, group: true }), style: "percent" }, number);
9313
+ }
9314
+ function format(locale, options, value) {
9315
+ const key = `${locale}\0${JSON.stringify(options)}`;
9316
+ let formatter = numberFormatters.get(key);
9317
+ if (formatter === void 0) {
9318
+ formatter = createNumberFormat(locale, options);
9319
+ numberFormatters.set(key, formatter);
9320
+ }
9321
+ return formatter.format(value);
9322
+ }
9323
+ function createNumberFormat(locale, options) {
9324
+ try {
9325
+ return new Intl.NumberFormat(locale, options);
9326
+ } catch {
9327
+ try {
9328
+ return new Intl.NumberFormat(void 0, options);
9329
+ } catch {
9330
+ return new Intl.NumberFormat();
9331
+ }
9332
+ }
9333
+ }
9334
+ function digitOptions({ decimals, minDecimals, maxDecimals, group = true }) {
9335
+ const result = { useGrouping: group !== false };
9336
+ const min = digitCount(minDecimals ?? decimals);
9337
+ const max = digitCount(maxDecimals ?? decimals);
9338
+ if (min !== null) result.minimumFractionDigits = min;
9339
+ if (max !== null) {
9340
+ result.maximumFractionDigits = max;
9341
+ if (min !== null && min > max) result.minimumFractionDigits = max;
9342
+ } else if (min !== null) {
9343
+ result.maximumFractionDigits = Math.max(min, DEFAULT_MAX_DIGITS);
9344
+ }
9345
+ return result;
9346
+ }
9347
+ function digitCount(value) {
9348
+ if (value == null) return null;
9349
+ const number = Number(value);
9350
+ if (!Number.isFinite(number)) return null;
9351
+ return Math.min(MAX_DIGITS, Math.max(MIN_DIGITS, Math.round(number)));
9352
+ }
9353
+ function toFiniteNumber(value) {
9354
+ if (value === null || value === void 0 || value === "") return null;
9355
+ const number = typeof value === "number" ? value : Number(value);
9356
+ return Number.isFinite(number) ? number : null;
9357
+ }
9358
+ function currencyCode(value) {
9359
+ if (typeof value !== "string") return null;
9360
+ const code = value.trim().toUpperCase();
9361
+ return /^[A-Z]{3}$/.test(code) ? code : null;
9362
+ }
9363
+
9238
9364
  // src/components/check-button/check-button.js
9239
9365
  var CheckButton = class extends Component {
9240
9366
  static cssName = "check-button";
@@ -9395,6 +9521,7 @@ var Modal = class extends Component {
9395
9521
  if (!this.options.closable || cancelEvent.defaultPrevented) event.preventDefault();
9396
9522
  });
9397
9523
  this.listen(this.el, "close", () => {
9524
+ if (!this._isRealClose()) return;
9398
9525
  this.el.dataset.state = "closed";
9399
9526
  delete this.el.dataset.zxOverlayOrder;
9400
9527
  const result = this.#hasPendingResult ? this.#pendingResult : this.el.returnValue || void 0;
@@ -9408,6 +9535,37 @@ var Modal = class extends Component {
9408
9535
  this.close();
9409
9536
  });
9410
9537
  }
9538
+ /**
9539
+ * Element the owned dialog is appended to. Overridden by subclasses that live inside a host
9540
+ * rather than at the document level.
9541
+ *
9542
+ * Called from `render()`, which the base constructor runs before any subclass field
9543
+ * initializers, so an override may read `this.options` but must not touch instance state.
9544
+ * @returns {Element}
9545
+ */
9546
+ mountTarget() {
9547
+ return document.body;
9548
+ }
9549
+ /**
9550
+ * Puts the dialog on screen. Overridden by subclasses that open non-modally.
9551
+ * @returns {void}
9552
+ */
9553
+ _show() {
9554
+ this.el.showModal();
9555
+ }
9556
+ /**
9557
+ * Whether an incoming `close` event is a real dismissal.
9558
+ *
9559
+ * A dialog cannot move between the top layer and the page flow while it is open, so a subclass
9560
+ * that re-hosts itself has to close and immediately reopen. `close` is dispatched in a queued
9561
+ * task, not synchronously, so that stale event arrives once the dialog is already open again —
9562
+ * late enough to clobber `data-state`, fire a `close` nobody asked for, and trip
9563
+ * `destroyOnClose`. Returning false from an override drops it at the source instead.
9564
+ * @returns {boolean}
9565
+ */
9566
+ _isRealClose() {
9567
+ return true;
9568
+ }
9411
9569
  /**
9412
9570
  * Creates the owned native dialog.
9413
9571
  * @returns {HTMLDialogElement}
@@ -9420,7 +9578,7 @@ var Modal = class extends Component {
9420
9578
  }, h("div", { class: "zx-modal__content", ref: "content" }))
9421
9579
  );
9422
9580
  dialog.dataset.state = "closed";
9423
- document.body.append(dialog);
9581
+ this.mountTarget().append(dialog);
9424
9582
  return dialog;
9425
9583
  }
9426
9584
  /**
@@ -9433,7 +9591,7 @@ var Modal = class extends Component {
9433
9591
  this.el.dataset.zxOverlayOrder = String(nextOverlayOrder());
9434
9592
  this.el.returnValue = "";
9435
9593
  try {
9436
- this.el.showModal();
9594
+ this._show();
9437
9595
  } catch (error) {
9438
9596
  delete this.el.dataset.zxOverlayOrder;
9439
9597
  throw error;
@@ -9548,7 +9706,7 @@ var Dialog = class _Dialog extends Modal {
9548
9706
  */
9549
9707
  constructor(_target = null, options = {}) {
9550
9708
  super(null, options);
9551
- this.#setSize(this.options.size);
9709
+ this._applySize(this.options.size);
9552
9710
  this.#baseTitle = String(this.options.title ?? "");
9553
9711
  this.#applyTitle(this.#baseTitle);
9554
9712
  this.#baseButtons = copyButtons(this.options.buttons);
@@ -9598,7 +9756,7 @@ var Dialog = class _Dialog extends Modal {
9598
9756
  )
9599
9757
  );
9600
9758
  dialog.dataset.state = "closed";
9601
- document.body.append(dialog);
9759
+ this.mountTarget().append(dialog);
9602
9760
  return dialog;
9603
9761
  }
9604
9762
  /**
@@ -9820,8 +9978,15 @@ var Dialog = class _Dialog extends Modal {
9820
9978
  dialog.open();
9821
9979
  });
9822
9980
  }
9823
- /** @param {'sm'|'md'|'lg'|number} size @returns {void} */
9824
- #setSize(size) {
9981
+ /**
9982
+ * Applies the dialog width. Subclasses that size themselves on a different axis override this.
9983
+ *
9984
+ * Called from the constructor before any subclass field initializers have run, so an override
9985
+ * may only touch the DOM — reading an uninitialized private field here throws.
9986
+ * @param {'sm'|'md'|'lg'|number} size Preset or pixel width.
9987
+ * @returns {void}
9988
+ */
9989
+ _applySize(size) {
9825
9990
  const presets = { sm: 400, md: 600, lg: 840 };
9826
9991
  const width = typeof size === "number" && Number.isFinite(size) ? size : presets[size] ?? presets.md;
9827
9992
  this.el.style.inlineSize = `${Math.max(0, width)}px`;
@@ -10641,7 +10806,8 @@ var Table = class extends Component {
10641
10806
  emptyText: null,
10642
10807
  rowClass: null,
10643
10808
  zebra: true,
10644
- editMode: false
10809
+ editMode: false,
10810
+ hierarchy: false
10645
10811
  };
10646
10812
  /**
10647
10813
  * Creates a table around a target or creates a new root when target is null.
@@ -10678,8 +10844,17 @@ var Table = class extends Component {
10678
10844
  this._rovingKey = null;
10679
10845
  this._rovingCell = null;
10680
10846
  this._rovingMatched = false;
10847
+ this._hierarchy = normalizeHierarchy(this.options.hierarchy, this._columns);
10848
+ this._expanded = initialExpanded(this._hierarchy?.expanded);
10681
10849
  if (this._sort && this.options.sortMode === "local") this._sortData();
10850
+ if (this._hierarchy?.expanded === true) {
10851
+ for (const id of hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId)) {
10852
+ this._expanded.add(id);
10853
+ }
10854
+ }
10855
+ this._reconcileExpanded();
10682
10856
  this._table = h("table", { class: "zx-table__table" });
10857
+ if (this._hierarchy) this._table.setAttribute("role", "treegrid");
10683
10858
  this._colgroup = h("colgroup", { class: "zx-table__columns" });
10684
10859
  this._thead = h("thead", { class: "zx-table__head" });
10685
10860
  this._tbody = h("tbody", { class: "zx-table__body" });
@@ -10748,6 +10923,7 @@ var Table = class extends Component {
10748
10923
  assertRows(rows);
10749
10924
  this._data = [...rows];
10750
10925
  if (this._sort && this.options.sortMode === "local") this._sortData();
10926
+ this._reconcileExpanded();
10751
10927
  const selectionChanged = this._pruneSelection();
10752
10928
  this._renderBody();
10753
10929
  if (selectionChanged) this._emitSelectionChange();
@@ -10765,6 +10941,7 @@ var Table = class extends Component {
10765
10941
  assertRows(rows);
10766
10942
  this._data.push(...rows);
10767
10943
  if (this._sort && this.options.sortMode === "local") this._sortData();
10944
+ this._reconcileExpanded();
10768
10945
  this._renderBody();
10769
10946
  this._emitDataChange();
10770
10947
  return this;
@@ -10784,6 +10961,7 @@ var Table = class extends Component {
10784
10961
  this._data[index] = row;
10785
10962
  if (wasSelected) this._selected.add(this._idFor(row));
10786
10963
  if (this._sort && this.options.sortMode === "local") this._sortData();
10964
+ this._reconcileExpanded();
10787
10965
  this._renderBody();
10788
10966
  if (wasSelected && !Object.is(id, this._idFor(row))) this._emitSelectionChange();
10789
10967
  this._emitDataChange();
@@ -10801,6 +10979,7 @@ var Table = class extends Component {
10801
10979
  const index = this._data.findIndex((candidate) => Object.is(this._idFor(candidate), id));
10802
10980
  if (index < 0) return this;
10803
10981
  this._data.splice(index, 1);
10982
+ this._reconcileExpanded();
10804
10983
  const selectionChanged = this._selected.delete(id);
10805
10984
  if (Object.is(this._selectionAnchorId, id)) this._selectionAnchorId = null;
10806
10985
  this._renderBody();
@@ -10816,7 +10995,10 @@ var Table = class extends Component {
10816
10995
  getRow(id) {
10817
10996
  return this._data.find((row) => Object.is(this._idFor(row), id)) ?? null;
10818
10997
  }
10819
- /** @returns {TableRow[]} Shallow copy of current rows in display order. */
10998
+ /**
10999
+ * Returns a shallow copy of the current rows in display order.
11000
+ * @returns {TableRow[]} Current table rows.
11001
+ */
10820
11002
  getData() {
10821
11003
  return [...this._data];
10822
11004
  }
@@ -10830,6 +11012,7 @@ var Table = class extends Component {
10830
11012
  empty() {
10831
11013
  const selectionChanged = this._selected.size > 0;
10832
11014
  this._data = [];
11015
+ this._expanded.clear();
10833
11016
  this._selected.clear();
10834
11017
  this._selectionAnchorId = null;
10835
11018
  this._renderBody();
@@ -10864,7 +11047,10 @@ var Table = class extends Component {
10864
11047
  if (!options.silent) this.emit("sort", { id, dir: direction });
10865
11048
  return this;
10866
11049
  }
10867
- /** @returns {TableRow[]} Selected rows in current display order. */
11050
+ /**
11051
+ * Returns selected rows in current display order.
11052
+ * @returns {TableRow[]} Selected rows.
11053
+ */
10868
11054
  getSelection() {
10869
11055
  return this._data.filter((row) => this._selected.has(this._idFor(row)));
10870
11056
  }
@@ -10903,6 +11089,75 @@ var Table = class extends Component {
10903
11089
  this._emitSelectionChange();
10904
11090
  return this;
10905
11091
  }
11092
+ /**
11093
+ * Toggles one hierarchy branch. A leaf or an id absent from the table is a no-op.
11094
+ * @param {unknown} id Row id.
11095
+ * @param {{silent?: boolean}} [options={}] Event behavior.
11096
+ * @returns {this}
11097
+ * @fires Table#rowtoggle
11098
+ */
11099
+ toggleRow(id, options = {}) {
11100
+ return this._expanded.has(id) ? this.collapseRow(id, options) : this.expandRow(id, options);
11101
+ }
11102
+ /**
11103
+ * Expands one hierarchy branch.
11104
+ * @param {unknown} id Row id.
11105
+ * @param {{silent?: boolean}} [options={}] Event behavior.
11106
+ * @returns {this}
11107
+ * @fires Table#rowtoggle
11108
+ */
11109
+ expandRow(id, options = {}) {
11110
+ return this._setRowExpanded(id, true, options);
11111
+ }
11112
+ /**
11113
+ * Collapses one hierarchy branch without discarding its descendants or their expansion state.
11114
+ * @param {unknown} id Row id.
11115
+ * @param {{silent?: boolean}} [options={}] Event behavior.
11116
+ * @returns {this}
11117
+ * @fires Table#rowtoggle
11118
+ */
11119
+ collapseRow(id, options = {}) {
11120
+ return this._setRowExpanded(id, false, options);
11121
+ }
11122
+ /**
11123
+ * Expands every row that currently has children.
11124
+ * @param {{silent?: boolean}} [options={}] Event behavior. When not silent, one `rowtoggle`
11125
+ * event is emitted per branch whose state changed.
11126
+ * @returns {this}
11127
+ */
11128
+ expandAll(options = {}) {
11129
+ if (!this._hierarchy) return this;
11130
+ const branchIds = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
11131
+ const changed = branchIds.filter((id) => !this._expanded.has(id));
11132
+ for (const id of changed) this._expanded.add(id);
11133
+ if (changed.length) this._renderBody();
11134
+ if (!options.silent) {
11135
+ for (const id of changed) this._emitRowToggle(id, true);
11136
+ }
11137
+ return this;
11138
+ }
11139
+ /**
11140
+ * Collapses every hierarchy branch.
11141
+ * @param {{silent?: boolean}} [options={}] Event behavior.
11142
+ * @returns {this}
11143
+ */
11144
+ collapseAll(options = {}) {
11145
+ if (!this._hierarchy || this._expanded.size === 0) return this;
11146
+ const changed = [...this._expanded];
11147
+ this._expanded.clear();
11148
+ this._renderBody();
11149
+ if (!options.silent) {
11150
+ for (const id of changed) this._emitRowToggle(id, false);
11151
+ }
11152
+ return this;
11153
+ }
11154
+ /**
11155
+ * Returns expanded branch ids in current flat-data order.
11156
+ * @returns {unknown[]} Expanded branch ids.
11157
+ */
11158
+ getExpanded() {
11159
+ return this._data.map((row) => this._idFor(row)).filter((id) => this._expanded.has(id));
11160
+ }
10906
11161
  /**
10907
11162
  * Opens the editor for a cell. No-op unless the table runs with `editMode` and the column
10908
11163
  * resolves to an editable type for that row. In `'row'` mode every editable cell of the row is
@@ -11010,11 +11265,17 @@ var Table = class extends Component {
11010
11265
  this._abortEdit({ focus: true });
11011
11266
  return this;
11012
11267
  }
11013
- /** @returns {boolean} Whether a cell or row is currently open for editing. */
11268
+ /**
11269
+ * Reports whether a cell or row is currently open for editing.
11270
+ * @returns {boolean} Whether an edit is open.
11271
+ */
11014
11272
  isEditing() {
11015
11273
  return this._edit !== null;
11016
11274
  }
11017
- /** @returns {{id: unknown, columnId: string}|null} Row id and focused column id, or null. */
11275
+ /**
11276
+ * Returns the row id and focused column id for the open edit.
11277
+ * @returns {{id: unknown, columnId: string}|null} Editing location, or null.
11278
+ */
11018
11279
  getEditing() {
11019
11280
  return this._edit ? { id: this._edit.id, columnId: this._edit.columnId } : null;
11020
11281
  }
@@ -11023,7 +11284,31 @@ var Table = class extends Component {
11023
11284
  * @returns {TableRow[]}
11024
11285
  */
11025
11286
  _visibleData() {
11026
- return this._rendered === Infinity ? this._data : this._data.slice(0, this._rendered);
11287
+ return this._visibleEntries().map((entry) => entry.row);
11288
+ }
11289
+ /** @returns {TableHierarchyEntry[]} Rows visible after hierarchy expansion, before growing. */
11290
+ _projectedData() {
11291
+ if (!this._hierarchy) {
11292
+ return this._data.map((row, index) => ({
11293
+ row,
11294
+ id: this._idFor(row),
11295
+ index,
11296
+ depth: 0,
11297
+ hasChildren: false,
11298
+ parentId: null
11299
+ }));
11300
+ }
11301
+ return projectHierarchyRows(
11302
+ this._data,
11303
+ this.options.rowId,
11304
+ this._hierarchy.parentId,
11305
+ this._expanded
11306
+ );
11307
+ }
11308
+ /** @returns {TableHierarchyEntry[]} Rows that currently have DOM entries. */
11309
+ _visibleEntries() {
11310
+ const projected = this._projectedData();
11311
+ return this._rendered === Infinity ? projected : projected.slice(0, this._rendered);
11027
11312
  }
11028
11313
  /**
11029
11314
  * Renders the next batch of rows.
@@ -11035,10 +11320,11 @@ var Table = class extends Component {
11035
11320
  if (!this._growStep) return this;
11036
11321
  const step = Number(count) > 0 ? Math.trunc(Number(count)) : this._growStep;
11037
11322
  const before = this._rendered;
11038
- this._rendered = Math.min(this._data.length, this._rendered + step);
11323
+ const total = this._projectedData().length;
11324
+ this._rendered = Math.min(total, this._rendered + step);
11039
11325
  if (this._rendered === before) return this;
11040
11326
  this._renderBody();
11041
- this.emit("grow", { rendered: this._rendered, total: this._data.length });
11327
+ this.emit("grow", { rendered: this._rendered, total });
11042
11328
  return this;
11043
11329
  }
11044
11330
  /**
@@ -11047,14 +11333,14 @@ var Table = class extends Component {
11047
11333
  * @fires Table#grow
11048
11334
  */
11049
11335
  showAll() {
11050
- return this.growBy(this._data.length);
11336
+ return this.growBy(this._projectedData().length);
11051
11337
  }
11052
11338
  /**
11053
11339
  * How many rows are currently rendered.
11054
11340
  * @returns {number}
11055
11341
  */
11056
11342
  getRenderedCount() {
11057
- return Math.min(this._rendered, this._data.length);
11343
+ return Math.min(this._rendered, this._projectedData().length);
11058
11344
  }
11059
11345
  /**
11060
11346
  * Keeps the "show more" control in step with what is rendered.
@@ -11066,7 +11352,7 @@ var Table = class extends Component {
11066
11352
  */
11067
11353
  _syncGrowing() {
11068
11354
  if (!this._growStep) return;
11069
- const remaining = this._data.length - this.getRenderedCount();
11355
+ const remaining = this._projectedData().length - this.getRenderedCount();
11070
11356
  if (remaining <= 0) {
11071
11357
  this._more?.remove();
11072
11358
  this._more = null;
@@ -11137,10 +11423,11 @@ var Table = class extends Component {
11137
11423
  * @returns {void}
11138
11424
  */
11139
11425
  _applyStackedRoles(stacked) {
11140
- const parts = [[this._table, "table"], [this._thead, "rowgroup"], [this._tbody, "rowgroup"]];
11426
+ const parts = [[this._table, this._hierarchy ? "treegrid" : "table"], [this._thead, "rowgroup"], [this._tbody, "rowgroup"]];
11141
11427
  for (const [element, role] of parts) {
11142
11428
  if (!element) continue;
11143
11429
  if (stacked) element.setAttribute("role", role);
11430
+ else if (element === this._table && this._hierarchy) element.setAttribute("role", "treegrid");
11144
11431
  else element.removeAttribute("role");
11145
11432
  }
11146
11433
  for (const [selector, role] of [["tr", "row"], ["td", "cell"], ["th", "columnheader"]]) {
@@ -11217,7 +11504,8 @@ var Table = class extends Component {
11217
11504
  this._headers = /* @__PURE__ */ new Map();
11218
11505
  for (const column of this._columns) {
11219
11506
  const th = h("th", { scope: "col" });
11220
- if (column.align) th.dataset.align = column.align;
11507
+ const align = column.align ?? (isNumericColumn(column) ? "end" : null);
11508
+ if (align) th.dataset.align = align;
11221
11509
  if (column.headerTitle) th.title = column.headerTitle;
11222
11510
  if (column.sortable) {
11223
11511
  const button2 = h("button", {
@@ -11246,6 +11534,8 @@ var Table = class extends Component {
11246
11534
  this._rowElements = /* @__PURE__ */ new Map();
11247
11535
  this._rovingCell = null;
11248
11536
  this._rovingMatched = false;
11537
+ const projected = this._projectedData();
11538
+ this._hierarchyMeta = new Map(projected.map((entry) => [entry.id, entry]));
11249
11539
  if (this._data.length === 0) {
11250
11540
  fragment.append(h(
11251
11541
  "tr",
@@ -11256,10 +11546,12 @@ var Table = class extends Component {
11256
11546
  }, this._emptyContent())
11257
11547
  ));
11258
11548
  } else {
11259
- this._visibleData().forEach((row, index) => fragment.append(this._createRow(row, index)));
11549
+ this._visibleEntries().forEach((entry, visibleIndex) => {
11550
+ fragment.append(this._createRow(entry.row, entry.index, { ...entry, visibleIndex }));
11551
+ });
11260
11552
  }
11261
11553
  this._tbody.replaceChildren(fragment);
11262
- if (this._growStep) this._table.setAttribute("aria-rowcount", String(this._data.length + 1));
11554
+ if (this._growStep) this._table.setAttribute("aria-rowcount", String(projected.length + 1));
11263
11555
  this._syncSelectAll();
11264
11556
  this._syncGrowing();
11265
11557
  if (this._stacked) this._applyStackedRoles(true);
@@ -11278,18 +11570,27 @@ var Table = class extends Component {
11278
11570
  if (empty == null) return this.msg("table.empty");
11279
11571
  return typeof empty === "function" ? empty() : empty;
11280
11572
  }
11281
- /** @param {TableRow} row @param {number} index @returns {HTMLTableRowElement} */
11282
- _createRow(row, index) {
11573
+ /**
11574
+ * @param {TableRow} row
11575
+ * @param {number} index
11576
+ * @param {TableHierarchyEntry & {visibleIndex: number}} tree
11577
+ * @returns {HTMLTableRowElement}
11578
+ */
11579
+ _createRow(row, index, tree) {
11283
11580
  const id = this._idFor(row);
11284
11581
  const tr = (
11285
11582
  /** @type {HTMLTableRowElement} */
11286
11583
  h("tr", { dataset: { row: "" } })
11287
11584
  );
11288
- if (this._growStep) tr.setAttribute("aria-rowindex", String(index + 2));
11585
+ if (this._growStep) tr.setAttribute("aria-rowindex", String(tree.visibleIndex + 2));
11289
11586
  const rowClass = typeof this.options.rowClass === "function" ? this.options.rowClass(row) : "";
11290
11587
  if (rowClass) tr.classList.add(...String(rowClass).split(/\s+/).filter(Boolean));
11291
11588
  if (this.options.selectable !== false) tr.setAttribute("aria-selected", String(this._selected.has(id)));
11292
- this._rowMeta.set(tr, { row, id, index });
11589
+ if (this._hierarchy) {
11590
+ tr.setAttribute("aria-level", String(tree.depth + 1));
11591
+ if (tree.hasChildren) tr.setAttribute("aria-expanded", String(this._expanded.has(id)));
11592
+ }
11593
+ this._rowMeta.set(tr, { row, id, index, visibleIndex: tree.visibleIndex });
11293
11594
  const elements = this._rowElements.get(id) ?? [];
11294
11595
  elements.push(tr);
11295
11596
  this._rowElements.set(id, elements);
@@ -11307,7 +11608,8 @@ var Table = class extends Component {
11307
11608
  /** @type {HTMLTableCellElement} */
11308
11609
  h("td")
11309
11610
  );
11310
- if (column.align) cell.dataset.align = column.align;
11611
+ const align = column.align ?? (isNumericColumn(column) ? "end" : null);
11612
+ if (align) cell.dataset.align = align;
11311
11613
  cell.dataset.label = column.label;
11312
11614
  if (column.popin === false) cell.dataset.popin = "false";
11313
11615
  if (this._editMode !== false) {
@@ -11318,7 +11620,7 @@ var Table = class extends Component {
11318
11620
  this._offerRovingCell(cell, id, column.id);
11319
11621
  }
11320
11622
  }
11321
- this._renderCellContent(cell, column, row, index);
11623
+ this._renderCellContent(cell, column, row, index, tree);
11322
11624
  tr.append(cell);
11323
11625
  });
11324
11626
  return tr;
@@ -11329,13 +11631,33 @@ var Table = class extends Component {
11329
11631
  * @param {TableColumn} column Column definition.
11330
11632
  * @param {TableRow} row Row data.
11331
11633
  * @param {number} index Row index.
11634
+ * @param {TableHierarchyEntry} [tree] Hierarchy metadata for the row.
11332
11635
  * @returns {void}
11333
11636
  */
11334
- _renderCellContent(cell, column, row, index) {
11335
- const value = typeof column.render === "function" ? column.render(row, index) : row?.[column.id];
11336
- if (value && typeof value === "object" && typeof value.nodeType === "number") cell.replaceChildren(value);
11337
- else if (value != null) cell.replaceChildren(document.createTextNode(String(value)));
11338
- else cell.replaceChildren();
11637
+ _renderCellContent(cell, column, row, index, tree = this._hierarchyMeta?.get(this._idFor(row))) {
11638
+ const value = formatTableCell(column, row, index);
11639
+ const content = h("span", { class: "zx-table__cell-content" });
11640
+ if (value && typeof value === "object" && typeof value.nodeType === "number") content.append(value);
11641
+ else if (value != null) content.append(document.createTextNode(String(value)));
11642
+ if (!this._hierarchy || column.id !== this._hierarchy.column || !tree) {
11643
+ cell.replaceChildren(...content.childNodes);
11644
+ return;
11645
+ }
11646
+ const branch = h("span", { class: "zx-table__tree-cell" });
11647
+ branch.style.setProperty("--zx-table-depth", String(tree.depth));
11648
+ if (tree.hasChildren) {
11649
+ const expanded = this._expanded.has(tree.id);
11650
+ branch.append(h("button", {
11651
+ class: "zx-table__tree-toggle",
11652
+ type: "button",
11653
+ ariaExpanded: String(expanded),
11654
+ ariaLabel: `${expanded ? "Collapse" : "Expand"} row ${index + 1}`
11655
+ }, icon(expanded ? "chevron-down" : "chevron-right", { size: 14 })));
11656
+ } else {
11657
+ branch.append(h("span", { class: "zx-table__tree-spacer", ariaHidden: "true" }));
11658
+ }
11659
+ branch.append(content);
11660
+ cell.replaceChildren(branch);
11339
11661
  }
11340
11662
  /** @param {MouseEvent} event @returns {void} */
11341
11663
  _handleBodyClick(event) {
@@ -11348,7 +11670,15 @@ var Table = class extends Component {
11348
11670
  if (!rowElement || !this._tbody.contains(rowElement)) return;
11349
11671
  const meta = this._rowMeta.get(rowElement);
11350
11672
  if (!meta) return;
11351
- if (this._edit) this.commitEdit();
11673
+ if (this._edit) {
11674
+ this.commitEdit();
11675
+ if (this._edit) return;
11676
+ }
11677
+ const disclosure = target.closest(".zx-table__tree-toggle");
11678
+ if (disclosure) {
11679
+ this.toggleRow(meta.id);
11680
+ return;
11681
+ }
11352
11682
  const checkbox = target.closest(".zx-table__row-checkbox");
11353
11683
  if (checkbox && this.options.selectable === "multi") {
11354
11684
  this._toggleMultiSelection(
@@ -11444,7 +11774,15 @@ var Table = class extends Component {
11444
11774
  return entry;
11445
11775
  }
11446
11776
  if (type === "number") {
11447
- const field = new NumberField(null, { ...props, value: value ?? null });
11777
+ const locale = resolveColumnOption(column.locale, row);
11778
+ const decimals = resolveColumnDecimals(column, row);
11779
+ const suffix = column.type === "currency" ? resolveColumnOption(column.currency, row) : column.type === "unit" ? resolveColumnOption(column.unit, row) : null;
11780
+ const inferred = {
11781
+ ...locale != null && !Object.prototype.hasOwnProperty.call(props, "locale") ? { locale } : {},
11782
+ ...decimals != null && !Object.prototype.hasOwnProperty.call(props, "precision") ? { precision: decimals } : {},
11783
+ ...suffix != null && !Object.prototype.hasOwnProperty.call(props, "unit") ? { unit: String(suffix) } : {}
11784
+ };
11785
+ const field = new NumberField(null, { ...inferred, ...props, value: value ?? null });
11448
11786
  host.append(field.el);
11449
11787
  entry.component = field;
11450
11788
  entry.control = field.getInput();
@@ -11675,9 +12013,12 @@ var Table = class extends Component {
11675
12013
  _nextEditableCell(rowIndex, columnId, direction) {
11676
12014
  const columnCount = this._columns.length;
11677
12015
  if (rowIndex < 0 || columnCount === 0) return null;
11678
- let row = rowIndex;
12016
+ const visible = this._visibleData();
12017
+ const startingId = this._idFor(this._data[rowIndex]);
12018
+ let row = visible.findIndex((candidate) => Object.is(this._idFor(candidate), startingId));
12019
+ if (row < 0) return null;
11679
12020
  let column = this._columns.findIndex((candidate) => candidate.id === columnId);
11680
- const limit = this._data.length * columnCount + columnCount;
12021
+ const limit = visible.length * columnCount + columnCount;
11681
12022
  for (let step = 0; step < limit; step += 1) {
11682
12023
  column += direction;
11683
12024
  if (column >= columnCount) {
@@ -11687,11 +12028,15 @@ var Table = class extends Component {
11687
12028
  row -= 1;
11688
12029
  column = columnCount - 1;
11689
12030
  }
11690
- if (row < 0 || row >= this._data.length) return null;
11691
- const candidateRow = this._data[row];
12031
+ if (row < 0 || row >= visible.length) return null;
12032
+ const candidateRow = visible[row];
11692
12033
  const candidateColumn = this._columns[column];
11693
12034
  if (resolveEditable(candidateColumn, candidateRow) !== false) {
11694
- return { id: this._idFor(candidateRow), columnId: candidateColumn.id, index: row };
12035
+ return {
12036
+ id: this._idFor(candidateRow),
12037
+ columnId: candidateColumn.id,
12038
+ index: this._data.indexOf(candidateRow)
12039
+ };
11695
12040
  }
11696
12041
  }
11697
12042
  return null;
@@ -11758,14 +12103,16 @@ var Table = class extends Component {
11758
12103
  const message = this.msg(key);
11759
12104
  return message === key ? fallback : message;
11760
12105
  }
11761
- /** @param {{row: TableRow, id: unknown, index: number}} meta @param {boolean} checked @param {boolean} shiftKey @returns {void} */
12106
+ /** @param {{row: TableRow, id: unknown, index: number, visibleIndex?: number}} meta @param {boolean} checked @param {boolean} shiftKey @returns {void} */
11762
12107
  _toggleMultiSelection(meta, checked, shiftKey) {
11763
- const anchorIndex = this._data.findIndex((row) => Object.is(this._idFor(row), this._selectionAnchorId));
12108
+ const visible = this._visibleData();
12109
+ const anchorIndex = visible.findIndex((row) => Object.is(this._idFor(row), this._selectionAnchorId));
11764
12110
  if (shiftKey && anchorIndex >= 0) {
11765
- const start = Math.min(anchorIndex, meta.index);
11766
- const end = Math.max(anchorIndex, meta.index);
12111
+ const currentIndex = meta.visibleIndex ?? visible.findIndex((row) => Object.is(this._idFor(row), meta.id));
12112
+ const start = Math.min(anchorIndex, currentIndex);
12113
+ const end = Math.max(anchorIndex, currentIndex);
11767
12114
  for (let index = start; index <= end; index += 1) {
11768
- const id = this._idFor(this._data[index]);
12115
+ const id = this._idFor(visible[index]);
11769
12116
  if (checked) this._selected.add(id);
11770
12117
  else this._selected.delete(id);
11771
12118
  }
@@ -11816,7 +12163,34 @@ var Table = class extends Component {
11816
12163
  const column = this._columns.find((candidate) => candidate.id === this._sort.id);
11817
12164
  if (!column) return;
11818
12165
  const getValue = typeof column.sortValue === "function" ? column.sortValue : (row) => row?.[column.id];
11819
- this._data = sortRows(this._data, getValue, this._sort.dir);
12166
+ this._data = this._hierarchy ? sortHierarchyRows(this._data, this.options.rowId, this._hierarchy.parentId, getValue, this._sort.dir) : sortRows(this._data, getValue, this._sort.dir);
12167
+ }
12168
+ /** @param {unknown} id @param {boolean} expanded @param {{silent?: boolean}} options @returns {this} */
12169
+ _setRowExpanded(id, expanded, options) {
12170
+ if (!this._hierarchy) return this;
12171
+ const branchIds = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
12172
+ if (!branchIds.some((candidate) => Object.is(candidate, id))) return this;
12173
+ if (this._expanded.has(id) === expanded) return this;
12174
+ if (expanded) this._expanded.add(id);
12175
+ else this._expanded.delete(id);
12176
+ this._renderBody();
12177
+ if (!options.silent) this._emitRowToggle(id, expanded);
12178
+ return this;
12179
+ }
12180
+ /** @param {unknown} id @param {boolean} expanded @returns {void} */
12181
+ _emitRowToggle(id, expanded) {
12182
+ const row = this.getRow(id);
12183
+ if (row) this.emit("rowtoggle", { row, id, expanded });
12184
+ }
12185
+ /** Keeps the reader's current expansion state limited to branches still present in the data. */
12186
+ _reconcileExpanded() {
12187
+ if (!this._hierarchy) {
12188
+ this._expanded.clear();
12189
+ return;
12190
+ }
12191
+ const branches = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
12192
+ const valid = new Set(branches);
12193
+ for (const id of this._expanded) if (!valid.has(id)) this._expanded.delete(id);
11820
12194
  }
11821
12195
  /** @returns {boolean} Whether selection changed. */
11822
12196
  _pruneSelection() {
@@ -11840,6 +12214,65 @@ var Table = class extends Component {
11840
12214
  this.emit("datachange", { rows: this.getData() });
11841
12215
  }
11842
12216
  };
12217
+ function formatTableCell(column, row, index = 0) {
12218
+ if (typeof column?.render === "function") return column.render(row, index);
12219
+ const value = row?.[column?.id];
12220
+ const type = column?.type ?? "text";
12221
+ if (type === "text") return value;
12222
+ const locale = resolveColumnOption(column.locale, row);
12223
+ const decimals = resolveColumnDecimals(column, row);
12224
+ const options = {
12225
+ ...locale != null ? { locale: String(locale) } : {},
12226
+ ...decimals != null ? { decimals } : {}
12227
+ };
12228
+ if (type === "number") return formatNumber(value, options);
12229
+ if (type === "currency") {
12230
+ const currency = resolveColumnOption(column.currency, row);
12231
+ return formatCurrency(value, currency == null ? null : String(currency), options);
12232
+ }
12233
+ if (type === "percent") return formatPercent(value, options);
12234
+ if (type === "unit") {
12235
+ const number = formatNumber(value, options);
12236
+ const unit = resolveColumnOption(column.unit, row);
12237
+ return number && unit != null && String(unit) !== "" ? `${number}\xA0${unit}` : number;
12238
+ }
12239
+ return value;
12240
+ }
12241
+ function projectHierarchyRows(rows, rowId, parentId, expanded = []) {
12242
+ const forest = hierarchyForest(rows, rowId, parentId);
12243
+ const open = expanded instanceof Set ? expanded : new Set(expanded);
12244
+ const result = [];
12245
+ const stack = forest.roots.slice().reverse().map((node) => ({ node, depth: 0 }));
12246
+ while (stack.length) {
12247
+ const { node, depth } = stack.pop();
12248
+ result.push({
12249
+ row: node.row,
12250
+ id: node.id,
12251
+ index: node.index,
12252
+ depth,
12253
+ hasChildren: node.children.length > 0,
12254
+ parentId: node.parent?.id ?? null
12255
+ });
12256
+ if (!open.has(node.id)) continue;
12257
+ for (let index = node.children.length - 1; index >= 0; index -= 1) {
12258
+ stack.push({ node: node.children[index], depth: depth + 1 });
12259
+ }
12260
+ }
12261
+ return result;
12262
+ }
12263
+ function sortHierarchyRows(rows, rowId, parentId, getValue, direction) {
12264
+ const forest = hierarchyForest(rows, rowId, parentId);
12265
+ const sorted = (nodes) => sortRows(nodes, (node) => getValue(node.row), direction);
12266
+ const result = [];
12267
+ const stack = sorted(forest.roots).reverse();
12268
+ while (stack.length) {
12269
+ const node = stack.pop();
12270
+ result.push(node.row);
12271
+ const children = sorted(node.children);
12272
+ for (let index = children.length - 1; index >= 0; index -= 1) stack.push(children[index]);
12273
+ }
12274
+ return result;
12275
+ }
11843
12276
  function resolveEditable(column, row) {
11844
12277
  if (!column || typeof column !== "object") return false;
11845
12278
  if (typeof column.editor === "function") {
@@ -11847,7 +12280,7 @@ function resolveEditable(column, row) {
11847
12280
  return "custom";
11848
12281
  }
11849
12282
  const declared = typeof column.editable === "function" ? column.editable(row) : column.editable;
11850
- if (declared === true) return "text";
12283
+ if (declared === true) return isNumericColumn(column) ? "number" : "text";
11851
12284
  if (typeof declared === "string" && EDITOR_TYPES.has(declared)) return (
11852
12285
  /** @type {TableEditorType} */
11853
12286
  declared
@@ -11896,6 +12329,71 @@ function firstValidationError(values, columns, row, fallbackMessage = "Invalid v
11896
12329
  }
11897
12330
  return null;
11898
12331
  }
12332
+ function resolveColumnOption(option, row) {
12333
+ return typeof option === "function" ? option(row) : option;
12334
+ }
12335
+ function resolveColumnDecimals(column, row) {
12336
+ const value = resolveColumnOption(column?.decimals, row);
12337
+ if (value == null) return null;
12338
+ const number = Number(value);
12339
+ return Number.isFinite(number) ? Math.max(0, Math.trunc(number)) : null;
12340
+ }
12341
+ function isNumericColumn(column) {
12342
+ return ["number", "currency", "percent", "unit"].includes(column?.type);
12343
+ }
12344
+ function hierarchyForest(rows, rowId, parentId) {
12345
+ const nodes = (Array.isArray(rows) ? rows : []).map((row, index) => ({
12346
+ row,
12347
+ id: readRowValue(rowId, row),
12348
+ index,
12349
+ parent: null,
12350
+ children: []
12351
+ }));
12352
+ const byId = /* @__PURE__ */ new Map();
12353
+ for (const node of nodes) if (!byId.has(node.id)) byId.set(node.id, node);
12354
+ const parentOf = /* @__PURE__ */ new Map();
12355
+ for (const node of nodes) {
12356
+ const parent = byId.get(readRowValue(parentId, node.row)) ?? null;
12357
+ parentOf.set(node, parent === node ? null : parent);
12358
+ }
12359
+ for (const node of nodes) {
12360
+ const seen = /* @__PURE__ */ new Set([node]);
12361
+ let cursor = parentOf.get(node) ?? null;
12362
+ while (cursor) {
12363
+ if (seen.has(cursor)) {
12364
+ parentOf.set(cursor, null);
12365
+ break;
12366
+ }
12367
+ seen.add(cursor);
12368
+ cursor = parentOf.get(cursor) ?? null;
12369
+ }
12370
+ }
12371
+ const roots = [];
12372
+ for (const node of nodes) {
12373
+ node.parent = parentOf.get(node) ?? null;
12374
+ if (node.parent) node.parent.children.push(node);
12375
+ else roots.push(node);
12376
+ }
12377
+ return { roots, nodes };
12378
+ }
12379
+ function hierarchyBranchIds(rows, rowId, parentId) {
12380
+ return hierarchyForest(rows, rowId, parentId).nodes.filter((node) => node.children.length > 0).map((node) => node.id);
12381
+ }
12382
+ function readRowValue(accessor, row) {
12383
+ return typeof accessor === "function" ? accessor(row) : row?.[accessor];
12384
+ }
12385
+ function normalizeHierarchy(option, columns) {
12386
+ if (!option || typeof option !== "object") return null;
12387
+ const parentId = option.parentId;
12388
+ if (typeof parentId !== "string" && typeof parentId !== "function") return null;
12389
+ const requested = typeof option.column === "string" ? option.column : null;
12390
+ const column = columns.some((candidate) => candidate.id === requested) ? requested : columns[0]?.id;
12391
+ if (!column) return null;
12392
+ return { ...option, parentId, column };
12393
+ }
12394
+ function initialExpanded(option) {
12395
+ return new Set(Array.isArray(option) ? option : []);
12396
+ }
11899
12397
  function normalizeEditMode(mode) {
11900
12398
  if (mode === "cell" || mode === "row") return mode;
11901
12399
  return mode === true ? "cell" : false;
@@ -12362,6 +12860,29 @@ var MenuButton = class extends Component {
12362
12860
  isOpen() {
12363
12861
  return this.#dropdown.isOpen();
12364
12862
  }
12863
+ /** Returns the trigger button. @returns {HTMLElement} */
12864
+ getTrigger() {
12865
+ return (
12866
+ /** @type {HTMLElement} */
12867
+ this.el
12868
+ );
12869
+ }
12870
+ /** Returns the owned menu panel. @returns {HTMLElement} */
12871
+ getPanel() {
12872
+ return this.#panel;
12873
+ }
12874
+ /** Opens the menu and focuses its first enabled item. @returns {this} */
12875
+ focusFirst() {
12876
+ this.open();
12877
+ this.#roving.focusFirst();
12878
+ return this;
12879
+ }
12880
+ /** Opens the menu and focuses its last enabled item. @returns {this} */
12881
+ focusLast() {
12882
+ this.open();
12883
+ this.#roving.focusLast();
12884
+ return this;
12885
+ }
12365
12886
  /**
12366
12887
  * Sets the visible trigger label.
12367
12888
  * @param {string} label Trigger label.
@@ -12421,7 +12942,8 @@ var MenuButton = class extends Component {
12421
12942
  const index = Number(element.getAttribute("data-menu-item"));
12422
12943
  const item = this.#items[index];
12423
12944
  if (!item || item === "-" || item.disabled) return;
12424
- this.emit("select", { value: item.value, item });
12945
+ const selected = this.emit("select", { value: item.value, item });
12946
+ if (selected.defaultPrevented) return;
12425
12947
  try {
12426
12948
  item.onselect?.(item.value, item, this);
12427
12949
  } finally {
@@ -13671,177 +14193,6 @@ function restore9(element, state) {
13671
14193
  element.replaceChildren(...state.children);
13672
14194
  }
13673
14195
 
13674
- // src/components/permission/permission.js
13675
- var Permission = class extends Component {
13676
- static cssName = "permission";
13677
- /** @type {PermissionOptions} */
13678
- static defaults = {
13679
- value: true,
13680
- groups: [],
13681
- groupsValueKey: "ID",
13682
- groupsLabelKey: "name"
13683
- };
13684
- /** @returns {HTMLElement} */
13685
- render() {
13686
- this._mode = "public";
13687
- this._groupValue = null;
13688
- this._groupSelect = null;
13689
- this._createdRoot = false;
13690
- this._originalChildren = [];
13691
- this._root = null;
13692
- this._originalState = null;
13693
- this._createdRoot = this.el === null;
13694
- const root = (
13695
- /** @type {HTMLElement} */
13696
- this.el ?? h("div")
13697
- );
13698
- this.el = root;
13699
- this._root = root;
13700
- if (!this._createdRoot) {
13701
- this._originalChildren = Array.from(root.childNodes);
13702
- this._originalState = root.getAttribute("data-state");
13703
- }
13704
- const name = uid("zx-permission");
13705
- const choices = h("div", {
13706
- class: "zx-permission__choices",
13707
- role: "radiogroup",
13708
- ariaLabel: this._message("permission.label", "Permission")
13709
- });
13710
- const privateChoice = this._choice(name, "private", this._message("permission.private", "Private"));
13711
- const publicChoice = this._choice(name, "public", this._message("permission.public", "Public"));
13712
- const groupChoice = this._choice(name, "group", this._message("permission.group", "Group"));
13713
- const groupHost = h("div", { ref: "groupHost", class: "zx-permission__groups" });
13714
- choices.append(privateChoice.label, publicChoice.label, groupChoice.label, groupHost);
13715
- root.replaceChildren(choices);
13716
- this.refs.private = privateChoice.input;
13717
- this.refs.public = publicChoice.input;
13718
- this.refs.group = groupChoice.input;
13719
- this._groupSelect = new Select(groupHost, {
13720
- items: Array.isArray(this.options.groups) ? this.options.groups : [],
13721
- valueKey: this.options.groupsValueKey,
13722
- labelKey: this.options.groupsLabelKey,
13723
- placeholder: this._message("permission.group", "Group")
13724
- });
13725
- this._groupSelect.refs.input.setAttribute(
13726
- "aria-label",
13727
- this._message("permission.group", "Group")
13728
- );
13729
- for (const input of [privateChoice.input, publicChoice.input, groupChoice.input]) {
13730
- this.listen(input, "change", () => {
13731
- if (!input.checked) return;
13732
- if (input.value === "group") this._selectGroupMode();
13733
- else this.set(input.value);
13734
- });
13735
- }
13736
- this.listen(groupHost, "zx-change", (event) => {
13737
- event.stopPropagation();
13738
- if (this._mode !== "group") return;
13739
- const previous = this.get();
13740
- this._groupValue = /** @type {CustomEvent} */
13741
- event.detail.value;
13742
- const value = this.get();
13743
- if (!Object.is(previous, value)) this.emit("change", { value });
13744
- });
13745
- this.set(this.options.value, { silent: true });
13746
- return root;
13747
- }
13748
- /** Returns the normalized permission value. @returns {'private'|'public'|unknown} */
13749
- get() {
13750
- if (this._mode === "private") return "private";
13751
- if (this._mode === "public") return "public";
13752
- return this._groupValue;
13753
- }
13754
- /**
13755
- * Sets a public, private, or group permission.
13756
- * @param {boolean|string|number|symbol|bigint|null} value Permission value.
13757
- * @param {{silent?: boolean}} [options={}] Update behavior.
13758
- * @returns {this}
13759
- * @fires Permission#change
13760
- */
13761
- set(value, { silent = false } = {}) {
13762
- const previous = this.get();
13763
- if (value === true || value === "public") {
13764
- this._mode = "public";
13765
- } else if (value === false || value === "private") {
13766
- this._mode = "private";
13767
- } else {
13768
- this._mode = "group";
13769
- this._groupValue = value;
13770
- this._groupSelect?.set(value, { silent: true });
13771
- }
13772
- this._sync();
13773
- const next = this.get();
13774
- if (!silent && !Object.is(previous, next)) this.emit("change", { value: next });
13775
- return this;
13776
- }
13777
- /** Destroys the embedded Select and restores an enhanced target. @returns {void} */
13778
- destroy() {
13779
- this._groupSelect?.destroy();
13780
- this._groupSelect = null;
13781
- if (!this._createdRoot && this.el) {
13782
- this.el.replaceChildren(...this._originalChildren);
13783
- if (this._originalState === null) this.el.removeAttribute("data-state");
13784
- else this.el.setAttribute("data-state", this._originalState);
13785
- }
13786
- super.destroy();
13787
- }
13788
- /** @returns {void} */
13789
- _selectGroupMode() {
13790
- const previous = this.get();
13791
- this._mode = "group";
13792
- if (this._groupValue == null) {
13793
- const first = Array.isArray(this.options.groups) ? this.options.groups[0] : null;
13794
- this._groupValue = first == null ? null : read(first, this.options.groupsValueKey);
13795
- }
13796
- this._groupSelect?.set(this._groupValue, { silent: true });
13797
- this._sync();
13798
- const next = this.get();
13799
- if (!Object.is(previous, next)) this.emit("change", { value: next });
13800
- }
13801
- /** @returns {void} */
13802
- _sync() {
13803
- this.refs.private.checked = this._mode === "private";
13804
- this.refs.public.checked = this._mode === "public";
13805
- this.refs.group.checked = this._mode === "group";
13806
- if (this._mode === "group") this._groupSelect?.enable();
13807
- else this._groupSelect?.disable();
13808
- this._root?.setAttribute("data-state", this._mode);
13809
- }
13810
- /**
13811
- * @param {string} name
13812
- * @param {'private'|'public'|'group'} value
13813
- * @param {string} text
13814
- * @returns {{label: HTMLLabelElement, input: HTMLInputElement}}
13815
- */
13816
- _choice(name, value, text3) {
13817
- const input = (
13818
- /** @type {HTMLInputElement} */
13819
- h("input", {
13820
- type: "radio",
13821
- name,
13822
- value
13823
- })
13824
- );
13825
- const label = (
13826
- /** @type {HTMLLabelElement} */
13827
- h("label", {
13828
- class: "zx-permission__choice"
13829
- }, input, h("span", {}, text3))
13830
- );
13831
- return { label, input };
13832
- }
13833
- /** @param {string} key @param {string} fallback @returns {string} */
13834
- _message(key, fallback) {
13835
- const message = this.msg(key);
13836
- return message === key ? fallback : message;
13837
- }
13838
- };
13839
- function read(item, reader) {
13840
- if (typeof reader === "function") return reader(item);
13841
- if (item === null || typeof item !== "object") return item;
13842
- return item[reader];
13843
- }
13844
-
13845
14196
  // src/components/data-filter/filter-core.js
13846
14197
  function normalizeText(value) {
13847
14198
  return String(value ?? "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLocaleLowerCase();
@@ -15425,9 +15776,9 @@ function translateChecklistOptions(options = {}) {
15425
15776
  delete translated.onClick;
15426
15777
  return translated;
15427
15778
  }
15428
- function translateDateboxFormat(format) {
15429
- if (typeof format === "string") return format.replaceAll("&nbsp;", " ");
15430
- const parts = Array.isArray(format) ? format : ["d", ".", "M", ".", "y"];
15779
+ function translateDateboxFormat(format2) {
15780
+ if (typeof format2 === "string") return format2.replaceAll("&nbsp;", " ");
15781
+ const parts = Array.isArray(format2) ? format2 : ["d", ".", "M", ".", "y"];
15431
15782
  const tokens = {
15432
15783
  d: "%d",
15433
15784
  m: "%m",
@@ -15615,26 +15966,39 @@ var Checklist2 = class extends ChecklistBase {
15615
15966
  var BootstrapChecklist = class extends ChecklistBase {
15616
15967
  static legacyName = "gx.bootstrap.Checklist";
15617
15968
  };
15618
- var Permission2 = class extends GxWrapper {
15969
+ function toLegacyPermission(value) {
15970
+ if (value === false) return "private";
15971
+ if (value === true) return "public";
15972
+ return value;
15973
+ }
15974
+ function fromLegacyPermission(value) {
15975
+ if (value === false || value === "private") return false;
15976
+ if (value === true || value === "public") return true;
15977
+ return value;
15978
+ }
15979
+ var Permission = class extends GxWrapper {
15619
15980
  static legacyName = "gx.zeyos.Permission";
15620
15981
  /** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
15621
15982
  constructor(display, options = {}) {
15622
15983
  super(options, { value: true, groups: [] });
15623
- const component = new Permission(display, {
15624
- value: options.value ?? true,
15984
+ const component = Select.permission(display, {
15985
+ value: fromLegacyPermission(options.value ?? true),
15625
15986
  groups: options.groups ?? options.data ?? [],
15626
- groupsValueKey: options.groupsValueKey ?? options.elementIndex ?? "ID",
15627
- groupsLabelKey: options.groupsLabelKey ?? options.elementLabel ?? "name"
15987
+ valueKey: options.groupsValueKey ?? options.elementIndex ?? "ID",
15988
+ labelKey: options.groupsLabelKey ?? options.elementLabel ?? "name"
15989
+ });
15990
+ this._attach(component, {
15991
+ events: { change: { type: "change", args: (detail) => [toLegacyPermission(detail.value)] } },
15992
+ setters: { value: "set" }
15628
15993
  });
15629
- this._attach(component, { events: { change: { type: "change", args: (detail) => [detail.value] } }, setters: { value: "set" } });
15630
15994
  }
15631
15995
  /** @returns {unknown} */
15632
15996
  get() {
15633
- return this._zx.get();
15997
+ return toLegacyPermission(this._zx.value);
15634
15998
  }
15635
15999
  /** @param {unknown} value @param {boolean} [silent=false] @returns {this} */
15636
16000
  set(value, silent = false) {
15637
- this._zx.set(value, { silent });
16001
+ this._zx.set(fromLegacyPermission(value), { silent });
15638
16002
  return this;
15639
16003
  }
15640
16004
  };
@@ -15867,11 +16231,11 @@ var Datebox2 = class extends GxWrapper {
15867
16231
  constructor(display, options = {}) {
15868
16232
  super(options, { timestamp: 0, unit: "milliseconds", format: ["d", ".", "M", ".", "y", " ", "h", ":", "i"] });
15869
16233
  const initial = options.timestamp == null || Number(options.timestamp) === 0 ? /* @__PURE__ */ new Date() : legacyDate(options.timestamp, options.unit ?? "milliseconds");
15870
- const format = translateDateboxFormat(options.format);
16234
+ const format2 = translateDateboxFormat(options.format);
15871
16235
  const component = new Datebox(display, {
15872
16236
  value: initial,
15873
- format,
15874
- time: /%[HMS]/.test(format),
16237
+ format: format2,
16238
+ time: /%[HMS]/.test(format2),
15875
16239
  disabled: Boolean(options.disabled)
15876
16240
  });
15877
16241
  this._attach(component, {
@@ -15937,13 +16301,13 @@ var PickerBase = class extends GxWrapper {
15937
16301
  return this;
15938
16302
  }
15939
16303
  /** @param {string} [format] @returns {Date|number|string|null} */
15940
- get(format = this.options.return_format) {
16304
+ get(format2 = this.options.return_format) {
15941
16305
  const date = this._readDate();
15942
16306
  if (!date) return null;
15943
- if (format == null) return date;
15944
- if (format === "%s" || format === "seconds") return Math.floor(date.getTime() / 1e3);
15945
- if (format === "date") return date;
15946
- return formatDate(date, String(format));
16307
+ if (format2 == null) return date;
16308
+ if (format2 === "%s" || format2 === "seconds") return Math.floor(date.getTime() / 1e3);
16309
+ if (format2 === "date") return date;
16310
+ return formatDate(date, String(format2));
15947
16311
  }
15948
16312
  /** @returns {number|null} */
15949
16313
  getSeconds() {
@@ -15956,8 +16320,8 @@ var PickerBase = class extends GxWrapper {
15956
16320
  return this;
15957
16321
  }
15958
16322
  /** @param {string} format @param {boolean} [enableTimePicker] @returns {this} */
15959
- setFormat(format, enableTimePicker) {
15960
- this.options.format = format;
16323
+ setFormat(format2, enableTimePicker) {
16324
+ this.options.format = format2;
15961
16325
  this.options.timePicker = enableTimePicker;
15962
16326
  return this;
15963
16327
  }
@@ -17422,7 +17786,7 @@ var gx = {
17422
17786
  SelectDyn,
17423
17787
  SelectPrio,
17424
17788
  Checklist: Checklist2,
17425
- Permission: Permission2,
17789
+ Permission,
17426
17790
  Table: Table2,
17427
17791
  Tabbox: Tabbox2,
17428
17792
  Panel: Panel2,