@zeyos/zx 2.2.1 → 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.
- package/CHANGELOG.md +197 -0
- package/DESIGN-SYSTEM.md +136 -0
- package/MIGRATION.md +155 -4
- package/README.md +51 -14
- package/dist/types/compat/map/data.d.ts +3 -2
- package/dist/types/components/account-menu/account-menu.d.ts +144 -0
- package/dist/types/components/app-rail/app-rail.d.ts +250 -0
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +169 -0
- package/dist/types/components/avatar/avatar.d.ts +100 -0
- package/dist/types/components/chart/chart.d.ts +321 -0
- package/dist/types/components/date-picker/month-picker.d.ts +6 -0
- package/dist/types/components/dialog/dialog.d.ts +9 -0
- package/dist/types/components/dock/dock.d.ts +495 -0
- package/dist/types/components/dropdown/dropdown.d.ts +2 -2
- package/dist/types/components/field/field.d.ts +14 -0
- package/dist/types/components/field-upload/field-upload.d.ts +37 -4
- package/dist/types/components/form/form.d.ts +25 -3
- package/dist/types/components/grid/grid.d.ts +172 -0
- package/dist/types/components/launcher/launcher.d.ts +300 -0
- package/dist/types/components/layout/layout.d.ts +4 -4
- package/dist/types/components/menu-button/menu-button.d.ts +10 -2
- package/dist/types/components/modal/modal.d.ts +25 -0
- package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +74 -9
- package/dist/types/components/questionnaire/items.d.ts +327 -0
- package/dist/types/components/questionnaire/questionnaire.d.ts +449 -0
- package/dist/types/components/select/select.d.ts +36 -1
- package/dist/types/components/sheet/sheet-stack.d.ts +167 -0
- package/dist/types/components/sheet/sheet.d.ts +294 -0
- package/dist/types/components/split-view/split-view.d.ts +2 -21
- package/dist/types/components/tabbox/tabbox.d.ts +12 -3
- package/dist/types/components/table/table.d.ts +219 -12
- package/dist/types/components/tooltip/tooltip.d.ts +2 -2
- package/dist/types/components/value-list/value-list.d.ts +24 -3
- package/dist/types/core/dom.d.ts +114 -0
- package/dist/types/core/drag-axis.d.ts +111 -0
- package/dist/types/core/position.d.ts +4 -2
- package/dist/types/index.d.ts +12 -2
- package/dist/zx-compat.esm.js +943 -311
- package/dist/zx-compat.esm.min.js +1 -1
- package/dist/zx-compat.global.js +7893 -2252
- package/dist/zx-compat.global.min.js +3 -3
- package/dist/zx-zeyos.esm.js +826 -114
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +1720 -243
- package/dist/zx.esm.js +8227 -2599
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +8227 -2599
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +2597 -255
- package/docs/llms.md +475 -37
- package/docs/llms.txt +21 -9
- package/package.json +4 -2
- package/src/compat/globals.js +3 -1
- package/src/compat/map/data.js +31 -9
- package/src/components/account-menu/account-menu.css +70 -0
- package/src/components/account-menu/account-menu.js +208 -0
- package/src/components/app-rail/app-rail.css +107 -0
- package/src/components/app-rail/app-rail.js +668 -0
- package/src/components/app-sidebar/app-sidebar.css +68 -0
- package/src/components/app-sidebar/app-sidebar.js +388 -0
- package/src/components/avatar/avatar.css +61 -0
- package/src/components/avatar/avatar.js +222 -0
- package/src/components/button/button.css +0 -1
- package/src/components/chart/chart.css +61 -0
- package/src/components/chart/chart.js +518 -0
- package/src/components/date-picker/date-range-picker.css +7 -0
- package/src/components/date-picker/month-picker.js +9 -0
- package/src/components/dialog/dialog.js +11 -4
- package/src/components/dock/dock.css +228 -0
- package/src/components/dock/dock.js +977 -0
- package/src/components/dropdown/dropdown.js +1 -1
- package/src/components/field/field.js +2 -0
- package/src/components/field-upload/field-upload.js +9 -4
- package/src/components/fieldset/fieldset.css +7 -0
- package/src/components/form/form.css +7 -0
- package/src/components/form/form.js +6 -3
- package/src/components/grid/grid.css +6 -0
- package/src/components/grid/grid.js +213 -0
- package/src/components/launcher/launcher.css +100 -0
- package/src/components/launcher/launcher.js +557 -0
- package/src/components/layout/layout.js +2 -2
- package/src/components/menu-button/menu-button.js +27 -2
- package/src/components/modal/modal.css +5 -1
- package/src/components/modal/modal.js +37 -2
- package/src/components/multi-value-editor/multi-value-editor.css +99 -15
- package/src/components/multi-value-editor/multi-value-editor.js +237 -19
- package/src/components/navigation-bar/navigation-bar.css +7 -0
- package/src/components/questionnaire/items.js +370 -0
- package/src/components/questionnaire/questionnaire.css +387 -0
- package/src/components/questionnaire/questionnaire.js +1033 -0
- package/src/components/search/search.css +10 -2
- package/src/components/select/select.css +6 -1
- package/src/components/select/select.js +99 -11
- package/src/components/sheet/sheet-stack.js +304 -0
- package/src/components/sheet/sheet.css +351 -0
- package/src/components/sheet/sheet.js +551 -0
- package/src/components/split-view/split-view.js +76 -161
- package/src/components/stepper/stepper.css +12 -2
- package/src/components/tabbox/tabbox.css +13 -3
- package/src/components/tabbox/tabbox.js +34 -10
- package/src/components/table/table.css +43 -0
- package/src/components/table/table.js +523 -45
- package/src/components/tooltip/tooltip.js +5 -2
- package/src/components/value-list/value-list.js +6 -3
- package/src/core/dom.js +302 -0
- package/src/core/drag-axis.js +203 -0
- package/src/core/position.js +68 -22
- package/src/index.js +19 -2
- package/styles/tokens/dark.css +15 -13
- package/styles/tokens/global.css +17 -5
- package/styles/tokens/semantic.css +14 -8
- package/styles/tokens/themes.css +72 -0
- package/styles/zx.css +11 -1
- package/dist/types/components/permission/permission.d.ts +0 -93
- package/src/components/permission/permission.css +0 -47
- package/src/components/permission/permission.js +0 -198
package/dist/zx-compat.esm.js
CHANGED
|
@@ -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
|
-
|
|
3089
|
-
floating.style.setProperty("
|
|
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
|
-
|
|
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": "
|
|
3141
|
-
"bottom-end": "
|
|
3142
|
-
"top-start": "
|
|
3143
|
-
"top-end": "
|
|
3144
|
-
|
|
3145
|
-
|
|
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
|
|
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 (
|
|
3160
|
-
actualPlacement =
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
placement
|
|
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
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
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,
|
|
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(
|
|
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(),
|
|
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(),
|
|
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,
|
|
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,
|
|
4030
|
-
if (!start) return formatDate(end,
|
|
4031
|
-
return `${formatDate(start,
|
|
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(
|
|
4690
|
-
const value = String(
|
|
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(
|
|
4694
|
-
return
|
|
4743
|
+
function placeholderFromFormat(format2) {
|
|
4744
|
+
return format2.replace(/%[demYyHMS]/g, (token) => ({
|
|
4695
4745
|
"%d": "DD",
|
|
4696
4746
|
"%e": "D",
|
|
4697
4747
|
"%m": "MM",
|
|
@@ -5118,18 +5168,34 @@ function registerFieldUploadAdapter() {
|
|
|
5118
5168
|
}
|
|
5119
5169
|
|
|
5120
5170
|
// src/components/multi-value-editor/multi-value-editor.js
|
|
5171
|
+
var REORDER = Object.freeze({
|
|
5172
|
+
both: { drag: true, buttons: true },
|
|
5173
|
+
buttons: { drag: false, buttons: true },
|
|
5174
|
+
drag: { drag: true, buttons: false },
|
|
5175
|
+
none: { drag: false, buttons: false }
|
|
5176
|
+
});
|
|
5177
|
+
var PARTS = Object.freeze({
|
|
5178
|
+
value: ".zx-multi-value-editor__value",
|
|
5179
|
+
handle: ".zx-multi-value-editor__handle",
|
|
5180
|
+
up: '[data-action="up"]',
|
|
5181
|
+
down: '[data-action="down"]'
|
|
5182
|
+
});
|
|
5121
5183
|
var MultiValueEditor = class extends Component {
|
|
5122
5184
|
static cssName = "multi-value-editor";
|
|
5123
5185
|
/** @type {MultiValueEditorOptions} */
|
|
5124
|
-
static defaults = { values: [], options: null, addLabel: "Add value" };
|
|
5186
|
+
static defaults = { values: [], options: null, addLabel: "Add value", reorder: "both" };
|
|
5125
5187
|
/** @returns {HTMLElement} */
|
|
5126
5188
|
render() {
|
|
5127
5189
|
const root = (
|
|
5128
5190
|
/** @type {HTMLElement} */
|
|
5129
5191
|
this.el ?? h("div")
|
|
5130
5192
|
);
|
|
5193
|
+
this.el = root;
|
|
5131
5194
|
this._values = Array.isArray(this.options.values) ? this.options.values.map(String) : [];
|
|
5132
5195
|
this._ownedNodes = [];
|
|
5196
|
+
this._initialState = root.getAttribute("data-state");
|
|
5197
|
+
this._dragIndex = -1;
|
|
5198
|
+
this._armed = null;
|
|
5133
5199
|
this._rows = h("div", { class: "zx-multi-value-editor__rows" });
|
|
5134
5200
|
this._add = h("button", {
|
|
5135
5201
|
class: "zx-btn zx-multi-value-editor__add",
|
|
@@ -5140,6 +5206,17 @@ var MultiValueEditor = class extends Component {
|
|
|
5140
5206
|
root.append(this._rows, this._add);
|
|
5141
5207
|
this.listen(root, "click", (event) => this._handleClick(event));
|
|
5142
5208
|
this.listen(this._rows, "change", (event) => this._handleChange(event));
|
|
5209
|
+
this.listen(this._rows, "keydown", (event) => this._handleKeydown(event));
|
|
5210
|
+
if (this._reorder().drag) {
|
|
5211
|
+
this.listen(this._rows, "pointerdown", (event) => this._handlePointerDown(event));
|
|
5212
|
+
this.listen(this._rows, "dragstart", (event) => this._handleDragStart(event));
|
|
5213
|
+
this.listen(this._rows, "dragover", (event) => this._handleDragOver(event));
|
|
5214
|
+
this.listen(this._rows, "dragleave", (event) => this._handleDragLeave(event));
|
|
5215
|
+
this.listen(this._rows, "drop", (event) => this._handleDrop(event));
|
|
5216
|
+
this.listen(this._rows, "dragend", () => this._finishDrag());
|
|
5217
|
+
this.listen(document, "pointerup", () => this._disarm());
|
|
5218
|
+
this.listen(document, "pointercancel", () => this._disarm());
|
|
5219
|
+
}
|
|
5143
5220
|
this._renderRows();
|
|
5144
5221
|
return root;
|
|
5145
5222
|
}
|
|
@@ -5162,16 +5239,27 @@ var MultiValueEditor = class extends Component {
|
|
|
5162
5239
|
if (!silent) this.emit("change", { values: this.getValues() });
|
|
5163
5240
|
return this;
|
|
5164
5241
|
}
|
|
5165
|
-
/** @
|
|
5166
|
-
|
|
5242
|
+
/** @returns {{drag: boolean, buttons: boolean}} */
|
|
5243
|
+
_reorder() {
|
|
5244
|
+
return REORDER[this.options.reorder] ?? REORDER.both;
|
|
5245
|
+
}
|
|
5246
|
+
/**
|
|
5247
|
+
* @param {number} [focusIndex=-1] Row to focus after the render, or -1 for none.
|
|
5248
|
+
* @param {keyof PARTS} [focusPart='value'] Which control of that row takes focus.
|
|
5249
|
+
* @returns {void}
|
|
5250
|
+
*/
|
|
5251
|
+
_renderRows(focusIndex = -1, focusPart = "value") {
|
|
5167
5252
|
const choices = normalizeOptions2(this.options.options);
|
|
5168
5253
|
const useSelect = this.options.options !== null;
|
|
5254
|
+
const { drag, buttons } = this._reorder();
|
|
5255
|
+
const last = this._values.length - 1;
|
|
5169
5256
|
const rows = this._values.map((value, index) => {
|
|
5257
|
+
const entries = !useSelect || choices.some(([option]) => option === value) ? choices : [[value, value], ...choices];
|
|
5170
5258
|
const control = useSelect ? h("select", {
|
|
5171
5259
|
class: "zx-multi-value-editor__value",
|
|
5172
5260
|
ariaLabel: `Value ${index + 1}`,
|
|
5173
5261
|
dataset: { index }
|
|
5174
|
-
},
|
|
5262
|
+
}, entries.map(([optionValue, label]) => h("option", {
|
|
5175
5263
|
value: optionValue,
|
|
5176
5264
|
selected: optionValue === value
|
|
5177
5265
|
}, label))) : h("input", {
|
|
@@ -5184,40 +5272,52 @@ var MultiValueEditor = class extends Component {
|
|
|
5184
5272
|
return h(
|
|
5185
5273
|
"div",
|
|
5186
5274
|
{ class: "zx-multi-value-editor__row", dataset: { row: index } },
|
|
5275
|
+
drag ? h("button", {
|
|
5276
|
+
class: "zx-multi-value-editor__handle",
|
|
5277
|
+
type: "button",
|
|
5278
|
+
ariaLabel: `Reorder value ${index + 1}. Use the arrow keys to move it.`,
|
|
5279
|
+
dataset: { action: "grab", index }
|
|
5280
|
+
}, icon("drag", { size: 12 })) : null,
|
|
5187
5281
|
control,
|
|
5188
5282
|
h(
|
|
5189
5283
|
"div",
|
|
5190
5284
|
{ class: "zx-multi-value-editor__controls" },
|
|
5191
|
-
h("button", {
|
|
5285
|
+
buttons ? h("button", {
|
|
5192
5286
|
class: "zx-btn",
|
|
5193
5287
|
type: "button",
|
|
5194
|
-
disabled
|
|
5288
|
+
// `aria-disabled` rather than `disabled`: the buttons re-render on every move, and a
|
|
5289
|
+
// control that disables itself under the reader's finger drops focus to the document.
|
|
5290
|
+
ariaDisabled: String(index === 0),
|
|
5195
5291
|
ariaLabel: `Move value ${index + 1} up`,
|
|
5196
5292
|
dataset: { action: "up", index }
|
|
5197
|
-
}, "
|
|
5198
|
-
h("button", {
|
|
5293
|
+
}, icon("chevron-up", { size: 12 })) : null,
|
|
5294
|
+
buttons ? h("button", {
|
|
5199
5295
|
class: "zx-btn",
|
|
5200
5296
|
type: "button",
|
|
5201
|
-
|
|
5297
|
+
ariaDisabled: String(index === last),
|
|
5202
5298
|
ariaLabel: `Move value ${index + 1} down`,
|
|
5203
5299
|
dataset: { action: "down", index }
|
|
5204
|
-
}, "
|
|
5300
|
+
}, icon("chevron-down", { size: 12 })) : null,
|
|
5205
5301
|
h("button", {
|
|
5206
5302
|
class: "zx-btn",
|
|
5207
5303
|
type: "button",
|
|
5208
5304
|
ariaLabel: `Remove value ${index + 1}`,
|
|
5209
5305
|
dataset: { action: "remove", index }
|
|
5210
|
-
}, "
|
|
5306
|
+
}, icon("x", { size: 12 }))
|
|
5211
5307
|
)
|
|
5212
5308
|
);
|
|
5213
5309
|
});
|
|
5214
5310
|
this._rows.replaceChildren(...rows);
|
|
5215
|
-
if (focusIndex >= 0)
|
|
5311
|
+
if (focusIndex >= 0) {
|
|
5312
|
+
const row = rows[Math.min(focusIndex, rows.length - 1)];
|
|
5313
|
+
row?.querySelector(PARTS[focusPart] ?? PARTS.value)?.focus();
|
|
5314
|
+
}
|
|
5216
5315
|
}
|
|
5217
5316
|
/** @param {MouseEvent} event @returns {void} */
|
|
5218
5317
|
_handleClick(event) {
|
|
5219
5318
|
const button2 = event.target instanceof Element ? event.target.closest("[data-action]") : null;
|
|
5220
5319
|
if (!button2 || !this.el.contains(button2)) return;
|
|
5320
|
+
if (button2.getAttribute("aria-disabled") === "true") return;
|
|
5221
5321
|
const action = button2.dataset.action;
|
|
5222
5322
|
const index = Number(button2.dataset.index);
|
|
5223
5323
|
if (action === "add") {
|
|
@@ -5230,28 +5330,156 @@ var MultiValueEditor = class extends Component {
|
|
|
5230
5330
|
this._renderRows(Math.min(index, this._values.length - 1));
|
|
5231
5331
|
this._emitChange();
|
|
5232
5332
|
} else if ((action === "up" || action === "down") && Number.isInteger(index)) {
|
|
5233
|
-
|
|
5234
|
-
if (target < 0 || target >= this._values.length) return;
|
|
5235
|
-
[this._values[index], this._values[target]] = [this._values[target], this._values[index]];
|
|
5236
|
-
this._renderRows(target);
|
|
5237
|
-
this._emitChange();
|
|
5333
|
+
this._move(index, index + (action === "up" ? -1 : 1), action);
|
|
5238
5334
|
}
|
|
5239
5335
|
}
|
|
5240
5336
|
/** @param {Event} event @returns {void} */
|
|
5241
5337
|
_handleChange(event) {
|
|
5242
5338
|
const control = event.target instanceof Element ? event.target.closest("[data-index]") : null;
|
|
5243
|
-
if (!control) return;
|
|
5339
|
+
if (!control || !("value" in control)) return;
|
|
5244
5340
|
const index = Number(control.dataset.index);
|
|
5245
5341
|
if (!Number.isInteger(index) || index < 0 || index >= this._values.length) return;
|
|
5246
5342
|
this._values[index] = control.value;
|
|
5247
5343
|
this._emitChange();
|
|
5248
5344
|
}
|
|
5345
|
+
/**
|
|
5346
|
+
* The handle is the keyboard equivalent of dragging it, so `reorder: 'drag'` is still operable
|
|
5347
|
+
* without a pointer.
|
|
5348
|
+
* @param {KeyboardEvent} event
|
|
5349
|
+
* @returns {void}
|
|
5350
|
+
*/
|
|
5351
|
+
_handleKeydown(event) {
|
|
5352
|
+
const handle = event.target instanceof Element ? event.target.closest(".zx-multi-value-editor__handle") : null;
|
|
5353
|
+
if (!handle) return;
|
|
5354
|
+
const index = Number(handle.dataset.index);
|
|
5355
|
+
const target = event.key === "ArrowUp" ? index - 1 : event.key === "ArrowDown" ? index + 1 : event.key === "Home" ? 0 : event.key === "End" ? this._values.length - 1 : -1;
|
|
5356
|
+
if (target < 0 || target >= this._values.length) return;
|
|
5357
|
+
event.preventDefault();
|
|
5358
|
+
this._move(index, target, "handle");
|
|
5359
|
+
}
|
|
5360
|
+
/**
|
|
5361
|
+
* Arms the row for dragging. Only the handle does this, so text selection inside a row's input
|
|
5362
|
+
* keeps working and a stray drag cannot reorder anything.
|
|
5363
|
+
* @param {PointerEvent} event
|
|
5364
|
+
* @returns {void}
|
|
5365
|
+
*/
|
|
5366
|
+
_handlePointerDown(event) {
|
|
5367
|
+
const handle = event.target instanceof Element ? event.target.closest(".zx-multi-value-editor__handle") : null;
|
|
5368
|
+
this._disarm();
|
|
5369
|
+
if (!handle || handle.disabled) return;
|
|
5370
|
+
const row = (
|
|
5371
|
+
/** @type {HTMLElement|null} */
|
|
5372
|
+
handle.closest(".zx-multi-value-editor__row")
|
|
5373
|
+
);
|
|
5374
|
+
if (!row) return;
|
|
5375
|
+
row.draggable = true;
|
|
5376
|
+
this._armed = row;
|
|
5377
|
+
}
|
|
5378
|
+
/** @returns {void} */
|
|
5379
|
+
_disarm() {
|
|
5380
|
+
if (this._armed) this._armed.draggable = false;
|
|
5381
|
+
this._armed = null;
|
|
5382
|
+
}
|
|
5383
|
+
/** @param {DragEvent} event @returns {void} */
|
|
5384
|
+
_handleDragStart(event) {
|
|
5385
|
+
const row = event.target instanceof Element ? event.target.closest(".zx-multi-value-editor__row") : null;
|
|
5386
|
+
if (!row || row !== this._armed) {
|
|
5387
|
+
event.preventDefault();
|
|
5388
|
+
return;
|
|
5389
|
+
}
|
|
5390
|
+
this._dragIndex = Number(row.dataset.row);
|
|
5391
|
+
row.dataset.dragging = "true";
|
|
5392
|
+
this.el.setAttribute("data-state", "dragging");
|
|
5393
|
+
event.dataTransfer?.setData("text/plain", String(this._dragIndex));
|
|
5394
|
+
if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
|
|
5395
|
+
}
|
|
5396
|
+
/** @param {DragEvent} event @returns {void} */
|
|
5397
|
+
_handleDragOver(event) {
|
|
5398
|
+
if (this._dragIndex < 0) return;
|
|
5399
|
+
event.preventDefault();
|
|
5400
|
+
if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
|
|
5401
|
+
this._showDrop(this._dropTarget(event.clientY));
|
|
5402
|
+
}
|
|
5403
|
+
/** @param {DragEvent} event @returns {void} */
|
|
5404
|
+
_handleDragLeave(event) {
|
|
5405
|
+
const to = event.relatedTarget;
|
|
5406
|
+
if (to instanceof Node && this._rows.contains(to)) return;
|
|
5407
|
+
this._clearDrop();
|
|
5408
|
+
}
|
|
5409
|
+
/** @param {DragEvent} event @returns {void} */
|
|
5410
|
+
_handleDrop(event) {
|
|
5411
|
+
if (this._dragIndex < 0) return;
|
|
5412
|
+
event.preventDefault();
|
|
5413
|
+
const from = this._dragIndex;
|
|
5414
|
+
const slot = this._dropTarget(event.clientY);
|
|
5415
|
+
this._finishDrag();
|
|
5416
|
+
this._move(from, slot > from ? slot - 1 : slot, "handle");
|
|
5417
|
+
}
|
|
5418
|
+
/** @returns {void} */
|
|
5419
|
+
_finishDrag() {
|
|
5420
|
+
this._dragIndex = -1;
|
|
5421
|
+
this._disarm();
|
|
5422
|
+
this._clearDrop();
|
|
5423
|
+
for (const row of this._rows.children) delete /** @type {HTMLElement} */
|
|
5424
|
+
row.dataset.dragging;
|
|
5425
|
+
if (this._initialState === null) this.el.removeAttribute("data-state");
|
|
5426
|
+
else this.el.setAttribute("data-state", this._initialState);
|
|
5427
|
+
}
|
|
5428
|
+
/**
|
|
5429
|
+
* Insertion slot (0…length) for a pointer at `clientY`.
|
|
5430
|
+
* @param {number} clientY Pointer position.
|
|
5431
|
+
* @returns {number}
|
|
5432
|
+
*/
|
|
5433
|
+
_dropTarget(clientY) {
|
|
5434
|
+
const rows = [...this._rows.children];
|
|
5435
|
+
for (const [index, row] of rows.entries()) {
|
|
5436
|
+
const box = row.getBoundingClientRect();
|
|
5437
|
+
if (clientY < box.top + box.height / 2) return index;
|
|
5438
|
+
}
|
|
5439
|
+
return rows.length;
|
|
5440
|
+
}
|
|
5441
|
+
/** @param {number} slot Insertion slot to mark. @returns {void} */
|
|
5442
|
+
_showDrop(slot) {
|
|
5443
|
+
const rows = [...this._rows.children];
|
|
5444
|
+
const inert = slot === this._dragIndex || slot === this._dragIndex + 1;
|
|
5445
|
+
for (const [index, row] of rows.entries()) {
|
|
5446
|
+
const cell = (
|
|
5447
|
+
/** @type {HTMLElement} */
|
|
5448
|
+
row
|
|
5449
|
+
);
|
|
5450
|
+
if (!inert && index === slot) cell.dataset.drop = "before";
|
|
5451
|
+
else if (!inert && slot === rows.length && index === rows.length - 1) cell.dataset.drop = "after";
|
|
5452
|
+
else delete cell.dataset.drop;
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
/** @returns {void} */
|
|
5456
|
+
_clearDrop() {
|
|
5457
|
+
for (const row of this._rows.children) delete /** @type {HTMLElement} */
|
|
5458
|
+
row.dataset.drop;
|
|
5459
|
+
}
|
|
5460
|
+
/**
|
|
5461
|
+
* @param {number} from Index to move.
|
|
5462
|
+
* @param {number} to Destination index.
|
|
5463
|
+
* @param {keyof PARTS} part Control of the moved row that takes focus.
|
|
5464
|
+
* @returns {boolean} Whether anything moved.
|
|
5465
|
+
*/
|
|
5466
|
+
_move(from, to, part) {
|
|
5467
|
+
const size = this._values.length;
|
|
5468
|
+
if (from === to || from < 0 || to < 0 || from >= size || to >= size) return false;
|
|
5469
|
+
const [value] = this._values.splice(from, 1);
|
|
5470
|
+
this._values.splice(to, 0, value);
|
|
5471
|
+
this._renderRows(to, part);
|
|
5472
|
+
this._emitChange();
|
|
5473
|
+
return true;
|
|
5474
|
+
}
|
|
5249
5475
|
/** @returns {void} */
|
|
5250
5476
|
_emitChange() {
|
|
5251
5477
|
this.emit("change", { values: this.getValues() });
|
|
5252
5478
|
}
|
|
5253
5479
|
/** @returns {void} */
|
|
5254
5480
|
destroy() {
|
|
5481
|
+
if (this._initialState === null) this.el?.removeAttribute("data-state");
|
|
5482
|
+
else this.el?.setAttribute("data-state", this._initialState);
|
|
5255
5483
|
for (const node of this._ownedNodes ?? []) node.remove();
|
|
5256
5484
|
super.destroy();
|
|
5257
5485
|
}
|
|
@@ -6276,6 +6504,7 @@ var Select = class _Select extends Component {
|
|
|
6276
6504
|
/** @type {SelectOptions} */
|
|
6277
6505
|
static defaults = {
|
|
6278
6506
|
items: [],
|
|
6507
|
+
fixedItems: [],
|
|
6279
6508
|
valueKey: "ID",
|
|
6280
6509
|
labelKey: "name",
|
|
6281
6510
|
renderItem: null,
|
|
@@ -6295,6 +6524,8 @@ var Select = class _Select extends Component {
|
|
|
6295
6524
|
render() {
|
|
6296
6525
|
this._items = [];
|
|
6297
6526
|
this._visibleItems = [];
|
|
6527
|
+
this._fixedItems = [];
|
|
6528
|
+
this._visibleFixed = [];
|
|
6298
6529
|
this._selected = null;
|
|
6299
6530
|
this._optionEntries = [];
|
|
6300
6531
|
this._activeIndex = -1;
|
|
@@ -6378,6 +6609,8 @@ var Select = class _Select extends Component {
|
|
|
6378
6609
|
root.replaceChildren(control, panel);
|
|
6379
6610
|
this._items = Array.isArray(this.options.items) ? this.options.items.slice() : [];
|
|
6380
6611
|
this._visibleItems = this._items.slice();
|
|
6612
|
+
this._fixedItems = Array.isArray(this.options.fixedItems) ? this.options.fixedItems.slice() : [];
|
|
6613
|
+
this._visibleFixed = this._fixedItems.slice();
|
|
6381
6614
|
this._disabled = Boolean(this.options.disabled);
|
|
6382
6615
|
this._handleTypeahead = typeahead(
|
|
6383
6616
|
() => this._optionEntries.filter((entry) => !entry.clear).map((entry) => entry.element),
|
|
@@ -6454,7 +6687,22 @@ var Select = class _Select extends Component {
|
|
|
6454
6687
|
const selectedValue = this.value;
|
|
6455
6688
|
this._items = Array.isArray(items) ? items.slice() : [];
|
|
6456
6689
|
this._visibleItems = this._items.slice();
|
|
6457
|
-
this._selected = selectedValue == null ? null : this.
|
|
6690
|
+
this._selected = selectedValue == null ? null : this._findItem(selectedValue);
|
|
6691
|
+
this._syncInputValue();
|
|
6692
|
+
this._renderOptions();
|
|
6693
|
+
this._position?.update();
|
|
6694
|
+
return this;
|
|
6695
|
+
}
|
|
6696
|
+
/**
|
|
6697
|
+
* Replaces the pinned choices and preserves selection by ID when possible.
|
|
6698
|
+
* @param {SelectItem[]} items New fixed items.
|
|
6699
|
+
* @returns {this}
|
|
6700
|
+
*/
|
|
6701
|
+
setFixedItems(items) {
|
|
6702
|
+
const selectedValue = this.value;
|
|
6703
|
+
this._fixedItems = Array.isArray(items) ? items.slice() : [];
|
|
6704
|
+
this._visibleFixed = this._fixedItems.slice();
|
|
6705
|
+
this._selected = selectedValue == null ? null : this._findItem(selectedValue);
|
|
6458
6706
|
this._syncInputValue();
|
|
6459
6707
|
this._renderOptions();
|
|
6460
6708
|
this._position?.update();
|
|
@@ -6508,6 +6756,7 @@ var Select = class _Select extends Component {
|
|
|
6508
6756
|
this.refs.input.removeAttribute("aria-activedescendant");
|
|
6509
6757
|
this._activeIndex = -1;
|
|
6510
6758
|
this._visibleItems = this._items.slice();
|
|
6759
|
+
this._visibleFixed = this._fixedItems.slice();
|
|
6511
6760
|
this._syncInputValue();
|
|
6512
6761
|
this.emit("close", {});
|
|
6513
6762
|
return this;
|
|
@@ -6563,6 +6812,38 @@ var Select = class _Select extends Component {
|
|
|
6563
6812
|
select.set(requestedValue, { silent: true });
|
|
6564
6813
|
return select;
|
|
6565
6814
|
}
|
|
6815
|
+
/**
|
|
6816
|
+
* Creates the record-permission picker: the fixed Private and Public choices above the groups a
|
|
6817
|
+
* record can be shared with. The value is the tri-state ZeyOS stores — `false` for private,
|
|
6818
|
+
* `true` for public, or a group ID — so the control binds straight to the record field.
|
|
6819
|
+
*
|
|
6820
|
+
* @param {Element|string|null} target Component target.
|
|
6821
|
+
* @param {SelectOptions & {groups?: SelectItem[]|((query: string) => Promise<SelectItem[]>|SelectItem[])}} [options={}]
|
|
6822
|
+
* Select overrides other than the fixed choices; `groups` holds the shareable groups, either as
|
|
6823
|
+
* an array (filtered locally) or as a loader function (queried remotely).
|
|
6824
|
+
* @returns {Select}
|
|
6825
|
+
*/
|
|
6826
|
+
static permission(target, options = {}) {
|
|
6827
|
+
const { groups = [], value = true, valueKey = "ID", labelKey = "name", ...rest } = options;
|
|
6828
|
+
const loader = typeof groups === "function" ? groups : null;
|
|
6829
|
+
const shareable = loader ? [] : groups;
|
|
6830
|
+
const choices = [{ ID: false, name: "Private" }, { ID: true, name: "Public" }];
|
|
6831
|
+
const select = new _Select(target, {
|
|
6832
|
+
filter: loader ?? "local",
|
|
6833
|
+
...rest,
|
|
6834
|
+
value: null,
|
|
6835
|
+
items: shareable,
|
|
6836
|
+
fixedItems: [],
|
|
6837
|
+
// The two choices carry their own ID and label, so a caller's group readers stay untouched.
|
|
6838
|
+
valueKey: (item) => choices.includes(item) ? item.ID : readItem(item, valueKey),
|
|
6839
|
+
labelKey: (item) => choices.includes(item) ? item.name : String(readItem(item, labelKey) ?? "")
|
|
6840
|
+
});
|
|
6841
|
+
choices[0].name = select._message("permission.private", "Private");
|
|
6842
|
+
choices[1].name = select._message("permission.public", "Public");
|
|
6843
|
+
select.setFixedItems(choices);
|
|
6844
|
+
select.set(value, { silent: true });
|
|
6845
|
+
return select;
|
|
6846
|
+
}
|
|
6566
6847
|
/** Cleans up the panel, pending async work, and enhanced target contents. @returns {void} */
|
|
6567
6848
|
destroy() {
|
|
6568
6849
|
this._cancelQuery();
|
|
@@ -6633,8 +6914,8 @@ var Select = class _Select extends Component {
|
|
|
6633
6914
|
);
|
|
6634
6915
|
if (!this._open) this.open();
|
|
6635
6916
|
if (this.options.filter === "local") {
|
|
6636
|
-
|
|
6637
|
-
this._visibleItems = matchItems(this._items, query,
|
|
6917
|
+
this._visibleFixed = this._matchFixed(query);
|
|
6918
|
+
this._visibleItems = matchItems(this._items, query, this._searchKeys());
|
|
6638
6919
|
this._renderOptions();
|
|
6639
6920
|
this._setActive(this._optionEntries.length > 0 ? 0 : -1);
|
|
6640
6921
|
this._position?.update();
|
|
@@ -6689,6 +6970,10 @@ var Select = class _Select extends Component {
|
|
|
6689
6970
|
if (this.options.clearable) {
|
|
6690
6971
|
this._appendOption(null, true, this.options.placeholder || this._message("select.none", "No selection"));
|
|
6691
6972
|
}
|
|
6973
|
+
for (const item of this._visibleFixed) this._appendOption(item, false);
|
|
6974
|
+
if (this._visibleFixed.length > 0 && this._visibleItems.length > 0 && !this.options.groupKey) {
|
|
6975
|
+
list.append(h("div", { class: "zx-select__separator", role: "presentation" }));
|
|
6976
|
+
}
|
|
6692
6977
|
for (const item of this._visibleItems) {
|
|
6693
6978
|
if (this.options.groupKey) {
|
|
6694
6979
|
const group = this._read(item, this.options.groupKey);
|
|
@@ -6702,7 +6987,7 @@ var Select = class _Select extends Component {
|
|
|
6702
6987
|
}
|
|
6703
6988
|
this._appendOption(item, false);
|
|
6704
6989
|
}
|
|
6705
|
-
if (this._visibleItems.length === 0 && !this._loading) {
|
|
6990
|
+
if (this._visibleItems.length === 0 && this._visibleFixed.length === 0 && !this._loading) {
|
|
6706
6991
|
list.append(h("div", {
|
|
6707
6992
|
class: "zx-select__empty",
|
|
6708
6993
|
role: "status"
|
|
@@ -6742,6 +7027,7 @@ var Select = class _Select extends Component {
|
|
|
6742
7027
|
if (this._queryTimer !== null) clearTimeout(this._queryTimer);
|
|
6743
7028
|
this._requestSequence += 1;
|
|
6744
7029
|
const sequence = this._requestSequence;
|
|
7030
|
+
this._visibleFixed = this._matchFixed(query);
|
|
6745
7031
|
if (query.length < Math.max(0, Number(this.options.minQuery) || 0)) {
|
|
6746
7032
|
this._setLoading(false);
|
|
6747
7033
|
this._visibleItems = [];
|
|
@@ -6826,13 +7112,14 @@ var Select = class _Select extends Component {
|
|
|
6826
7112
|
}
|
|
6827
7113
|
/** @param {unknown} candidate @returns {SelectItem|null} */
|
|
6828
7114
|
_findItem(candidate) {
|
|
6829
|
-
const
|
|
7115
|
+
const pool = this._fixedItems.length === 0 ? this._items : [...this._fixedItems, ...this._items];
|
|
7116
|
+
const direct = pool.find((item) => item === candidate);
|
|
6830
7117
|
if (direct !== void 0) return direct;
|
|
6831
7118
|
const value = candidate !== null && typeof candidate === "object" ? this._itemValue(
|
|
6832
7119
|
/** @type {SelectItem} */
|
|
6833
7120
|
candidate
|
|
6834
7121
|
) : candidate;
|
|
6835
|
-
return
|
|
7122
|
+
return pool.find((item) => Object.is(this._itemValue(item), value)) ?? null;
|
|
6836
7123
|
}
|
|
6837
7124
|
/** @param {SelectItem|null} item @returns {unknown} */
|
|
6838
7125
|
_itemValue(item) {
|
|
@@ -6845,9 +7132,20 @@ var Select = class _Select extends Component {
|
|
|
6845
7132
|
}
|
|
6846
7133
|
/** @param {SelectItem|null} item @param {SelectValueReader|SelectLabelReader} reader @returns {unknown} */
|
|
6847
7134
|
_read(item, reader) {
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
7135
|
+
return readItem(item, reader);
|
|
7136
|
+
}
|
|
7137
|
+
/** @returns {Array<SelectValueReader|SelectLabelReader>} */
|
|
7138
|
+
_searchKeys() {
|
|
7139
|
+
return this.options.searchKeys ?? [this.options.labelKey];
|
|
7140
|
+
}
|
|
7141
|
+
/**
|
|
7142
|
+
* Narrows the pinned choices. They are always matched here and never handed to a filter
|
|
7143
|
+
* function: a fixed choice belongs to the control, not to whatever the remote source returns.
|
|
7144
|
+
* @param {string} query Search text.
|
|
7145
|
+
* @returns {SelectItem[]}
|
|
7146
|
+
*/
|
|
7147
|
+
_matchFixed(query) {
|
|
7148
|
+
return matchItems(this._fixedItems, query, this._searchKeys());
|
|
6851
7149
|
}
|
|
6852
7150
|
/** @returns {number} */
|
|
6853
7151
|
_selectedEntryIndex() {
|
|
@@ -6870,6 +7168,11 @@ var Select = class _Select extends Component {
|
|
|
6870
7168
|
return message === key ? fallback : message;
|
|
6871
7169
|
}
|
|
6872
7170
|
};
|
|
7171
|
+
function readItem(item, reader) {
|
|
7172
|
+
if (typeof reader === "function") return reader(item);
|
|
7173
|
+
if (item === null || typeof item !== "object") return item;
|
|
7174
|
+
return item[reader];
|
|
7175
|
+
}
|
|
6873
7176
|
function isPrintable(event) {
|
|
6874
7177
|
return event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
6875
7178
|
}
|
|
@@ -8010,9 +8313,9 @@ var TagPicker = class extends Component {
|
|
|
8010
8313
|
function normalizeLabel(value) {
|
|
8011
8314
|
return String(value ?? "").trim().toLocaleLowerCase();
|
|
8012
8315
|
}
|
|
8013
|
-
function sameSelection(a, b,
|
|
8316
|
+
function sameSelection(a, b, read) {
|
|
8014
8317
|
if (a.length !== b.length) return false;
|
|
8015
|
-
return a.every((item, index) => Object.is(
|
|
8318
|
+
return a.every((item, index) => Object.is(read(item), read(b[index])));
|
|
8016
8319
|
}
|
|
8017
8320
|
|
|
8018
8321
|
// src/components/tag-picker/field-adapter.js
|
|
@@ -8982,6 +9285,82 @@ function isFileList(value) {
|
|
|
8982
9285
|
return typeof FileList === "function" && value instanceof FileList;
|
|
8983
9286
|
}
|
|
8984
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
|
+
|
|
8985
9364
|
// src/components/check-button/check-button.js
|
|
8986
9365
|
var CheckButton = class extends Component {
|
|
8987
9366
|
static cssName = "check-button";
|
|
@@ -9142,6 +9521,7 @@ var Modal = class extends Component {
|
|
|
9142
9521
|
if (!this.options.closable || cancelEvent.defaultPrevented) event.preventDefault();
|
|
9143
9522
|
});
|
|
9144
9523
|
this.listen(this.el, "close", () => {
|
|
9524
|
+
if (!this._isRealClose()) return;
|
|
9145
9525
|
this.el.dataset.state = "closed";
|
|
9146
9526
|
delete this.el.dataset.zxOverlayOrder;
|
|
9147
9527
|
const result = this.#hasPendingResult ? this.#pendingResult : this.el.returnValue || void 0;
|
|
@@ -9155,6 +9535,37 @@ var Modal = class extends Component {
|
|
|
9155
9535
|
this.close();
|
|
9156
9536
|
});
|
|
9157
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
|
+
}
|
|
9158
9569
|
/**
|
|
9159
9570
|
* Creates the owned native dialog.
|
|
9160
9571
|
* @returns {HTMLDialogElement}
|
|
@@ -9167,7 +9578,7 @@ var Modal = class extends Component {
|
|
|
9167
9578
|
}, h("div", { class: "zx-modal__content", ref: "content" }))
|
|
9168
9579
|
);
|
|
9169
9580
|
dialog.dataset.state = "closed";
|
|
9170
|
-
|
|
9581
|
+
this.mountTarget().append(dialog);
|
|
9171
9582
|
return dialog;
|
|
9172
9583
|
}
|
|
9173
9584
|
/**
|
|
@@ -9180,7 +9591,7 @@ var Modal = class extends Component {
|
|
|
9180
9591
|
this.el.dataset.zxOverlayOrder = String(nextOverlayOrder());
|
|
9181
9592
|
this.el.returnValue = "";
|
|
9182
9593
|
try {
|
|
9183
|
-
this.
|
|
9594
|
+
this._show();
|
|
9184
9595
|
} catch (error) {
|
|
9185
9596
|
delete this.el.dataset.zxOverlayOrder;
|
|
9186
9597
|
throw error;
|
|
@@ -9295,7 +9706,7 @@ var Dialog = class _Dialog extends Modal {
|
|
|
9295
9706
|
*/
|
|
9296
9707
|
constructor(_target = null, options = {}) {
|
|
9297
9708
|
super(null, options);
|
|
9298
|
-
this
|
|
9709
|
+
this._applySize(this.options.size);
|
|
9299
9710
|
this.#baseTitle = String(this.options.title ?? "");
|
|
9300
9711
|
this.#applyTitle(this.#baseTitle);
|
|
9301
9712
|
this.#baseButtons = copyButtons(this.options.buttons);
|
|
@@ -9345,7 +9756,7 @@ var Dialog = class _Dialog extends Modal {
|
|
|
9345
9756
|
)
|
|
9346
9757
|
);
|
|
9347
9758
|
dialog.dataset.state = "closed";
|
|
9348
|
-
|
|
9759
|
+
this.mountTarget().append(dialog);
|
|
9349
9760
|
return dialog;
|
|
9350
9761
|
}
|
|
9351
9762
|
/**
|
|
@@ -9567,8 +9978,15 @@ var Dialog = class _Dialog extends Modal {
|
|
|
9567
9978
|
dialog.open();
|
|
9568
9979
|
});
|
|
9569
9980
|
}
|
|
9570
|
-
/**
|
|
9571
|
-
|
|
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) {
|
|
9572
9990
|
const presets = { sm: 400, md: 600, lg: 840 };
|
|
9573
9991
|
const width = typeof size === "number" && Number.isFinite(size) ? size : presets[size] ?? presets.md;
|
|
9574
9992
|
this.el.style.inlineSize = `${Math.max(0, width)}px`;
|
|
@@ -9996,6 +10414,10 @@ var Tabbox = class extends Component {
|
|
|
9996
10414
|
if (!tab || !tablist.contains(tab)) return;
|
|
9997
10415
|
const record = this._recordForTab(tab);
|
|
9998
10416
|
if (!record || record.definition.disabled) return;
|
|
10417
|
+
if (event.target.closest?.(".zx-tabbox__close")) {
|
|
10418
|
+
this._closeTab(record);
|
|
10419
|
+
return;
|
|
10420
|
+
}
|
|
9999
10421
|
this._setFocused(record);
|
|
10000
10422
|
this.openTab(record.definition.name);
|
|
10001
10423
|
});
|
|
@@ -10045,8 +10467,9 @@ var Tabbox = class extends Component {
|
|
|
10045
10467
|
children.push(title, badge);
|
|
10046
10468
|
if (normalized.closable) {
|
|
10047
10469
|
children.push(h("span", {
|
|
10048
|
-
class: "zx-tabbox__close",
|
|
10049
|
-
ariaHidden: "true"
|
|
10470
|
+
class: "zx-tabbox__close zx-icon-btn",
|
|
10471
|
+
ariaHidden: "true",
|
|
10472
|
+
title: "Close"
|
|
10050
10473
|
}, icon("x", { size: 14 })));
|
|
10051
10474
|
}
|
|
10052
10475
|
const tab = (
|
|
@@ -10220,13 +10643,23 @@ var Tabbox = class extends Component {
|
|
|
10220
10643
|
}
|
|
10221
10644
|
if (event.key === "Delete" && current.definition.closable) {
|
|
10222
10645
|
event.preventDefault();
|
|
10223
|
-
|
|
10224
|
-
if (!this._removeTab(current.definition.name, true)) return;
|
|
10225
|
-
const remaining = this._tabs[Math.min(index, this._tabs.length - 1)] ?? this._tabs[index - 1];
|
|
10226
|
-
const focusTarget = remaining && !remaining.definition.disabled ? remaining : this._active;
|
|
10227
|
-
if (focusTarget) this._setFocused(focusTarget);
|
|
10646
|
+
this._closeTab(current);
|
|
10228
10647
|
}
|
|
10229
10648
|
}
|
|
10649
|
+
/**
|
|
10650
|
+
* Closes a tab on a user gesture, keeping roving focus inside the tablist.
|
|
10651
|
+
* @param {TabRecord} record Tab to close.
|
|
10652
|
+
* @returns {void}
|
|
10653
|
+
* @fires Tabbox#close
|
|
10654
|
+
*/
|
|
10655
|
+
_closeTab(record) {
|
|
10656
|
+
const index = this._tabs.indexOf(record);
|
|
10657
|
+
const held = record.tab.contains(document.activeElement);
|
|
10658
|
+
if (!this._removeTab(record.definition.name, true)) return;
|
|
10659
|
+
const remaining = this._tabs[Math.min(index, this._tabs.length - 1)] ?? this._tabs[index - 1];
|
|
10660
|
+
const focusTarget = remaining && !remaining.definition.disabled ? remaining : this._active;
|
|
10661
|
+
if (focusTarget) this._setFocused(focusTarget, held);
|
|
10662
|
+
}
|
|
10230
10663
|
/** @param {string} name @param {boolean} emitClose @returns {boolean} */
|
|
10231
10664
|
_removeTab(name, emitClose) {
|
|
10232
10665
|
const record = this._find(name);
|
|
@@ -10373,7 +10806,8 @@ var Table = class extends Component {
|
|
|
10373
10806
|
emptyText: null,
|
|
10374
10807
|
rowClass: null,
|
|
10375
10808
|
zebra: true,
|
|
10376
|
-
editMode: false
|
|
10809
|
+
editMode: false,
|
|
10810
|
+
hierarchy: false
|
|
10377
10811
|
};
|
|
10378
10812
|
/**
|
|
10379
10813
|
* Creates a table around a target or creates a new root when target is null.
|
|
@@ -10410,8 +10844,17 @@ var Table = class extends Component {
|
|
|
10410
10844
|
this._rovingKey = null;
|
|
10411
10845
|
this._rovingCell = null;
|
|
10412
10846
|
this._rovingMatched = false;
|
|
10847
|
+
this._hierarchy = normalizeHierarchy(this.options.hierarchy, this._columns);
|
|
10848
|
+
this._expanded = initialExpanded(this._hierarchy?.expanded);
|
|
10413
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();
|
|
10414
10856
|
this._table = h("table", { class: "zx-table__table" });
|
|
10857
|
+
if (this._hierarchy) this._table.setAttribute("role", "treegrid");
|
|
10415
10858
|
this._colgroup = h("colgroup", { class: "zx-table__columns" });
|
|
10416
10859
|
this._thead = h("thead", { class: "zx-table__head" });
|
|
10417
10860
|
this._tbody = h("tbody", { class: "zx-table__body" });
|
|
@@ -10480,6 +10923,7 @@ var Table = class extends Component {
|
|
|
10480
10923
|
assertRows(rows);
|
|
10481
10924
|
this._data = [...rows];
|
|
10482
10925
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
10926
|
+
this._reconcileExpanded();
|
|
10483
10927
|
const selectionChanged = this._pruneSelection();
|
|
10484
10928
|
this._renderBody();
|
|
10485
10929
|
if (selectionChanged) this._emitSelectionChange();
|
|
@@ -10497,6 +10941,7 @@ var Table = class extends Component {
|
|
|
10497
10941
|
assertRows(rows);
|
|
10498
10942
|
this._data.push(...rows);
|
|
10499
10943
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
10944
|
+
this._reconcileExpanded();
|
|
10500
10945
|
this._renderBody();
|
|
10501
10946
|
this._emitDataChange();
|
|
10502
10947
|
return this;
|
|
@@ -10516,6 +10961,7 @@ var Table = class extends Component {
|
|
|
10516
10961
|
this._data[index] = row;
|
|
10517
10962
|
if (wasSelected) this._selected.add(this._idFor(row));
|
|
10518
10963
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
10964
|
+
this._reconcileExpanded();
|
|
10519
10965
|
this._renderBody();
|
|
10520
10966
|
if (wasSelected && !Object.is(id, this._idFor(row))) this._emitSelectionChange();
|
|
10521
10967
|
this._emitDataChange();
|
|
@@ -10533,6 +10979,7 @@ var Table = class extends Component {
|
|
|
10533
10979
|
const index = this._data.findIndex((candidate) => Object.is(this._idFor(candidate), id));
|
|
10534
10980
|
if (index < 0) return this;
|
|
10535
10981
|
this._data.splice(index, 1);
|
|
10982
|
+
this._reconcileExpanded();
|
|
10536
10983
|
const selectionChanged = this._selected.delete(id);
|
|
10537
10984
|
if (Object.is(this._selectionAnchorId, id)) this._selectionAnchorId = null;
|
|
10538
10985
|
this._renderBody();
|
|
@@ -10548,7 +10995,10 @@ var Table = class extends Component {
|
|
|
10548
10995
|
getRow(id) {
|
|
10549
10996
|
return this._data.find((row) => Object.is(this._idFor(row), id)) ?? null;
|
|
10550
10997
|
}
|
|
10551
|
-
/**
|
|
10998
|
+
/**
|
|
10999
|
+
* Returns a shallow copy of the current rows in display order.
|
|
11000
|
+
* @returns {TableRow[]} Current table rows.
|
|
11001
|
+
*/
|
|
10552
11002
|
getData() {
|
|
10553
11003
|
return [...this._data];
|
|
10554
11004
|
}
|
|
@@ -10562,6 +11012,7 @@ var Table = class extends Component {
|
|
|
10562
11012
|
empty() {
|
|
10563
11013
|
const selectionChanged = this._selected.size > 0;
|
|
10564
11014
|
this._data = [];
|
|
11015
|
+
this._expanded.clear();
|
|
10565
11016
|
this._selected.clear();
|
|
10566
11017
|
this._selectionAnchorId = null;
|
|
10567
11018
|
this._renderBody();
|
|
@@ -10596,7 +11047,10 @@ var Table = class extends Component {
|
|
|
10596
11047
|
if (!options.silent) this.emit("sort", { id, dir: direction });
|
|
10597
11048
|
return this;
|
|
10598
11049
|
}
|
|
10599
|
-
/**
|
|
11050
|
+
/**
|
|
11051
|
+
* Returns selected rows in current display order.
|
|
11052
|
+
* @returns {TableRow[]} Selected rows.
|
|
11053
|
+
*/
|
|
10600
11054
|
getSelection() {
|
|
10601
11055
|
return this._data.filter((row) => this._selected.has(this._idFor(row)));
|
|
10602
11056
|
}
|
|
@@ -10635,6 +11089,75 @@ var Table = class extends Component {
|
|
|
10635
11089
|
this._emitSelectionChange();
|
|
10636
11090
|
return this;
|
|
10637
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
|
+
}
|
|
10638
11161
|
/**
|
|
10639
11162
|
* Opens the editor for a cell. No-op unless the table runs with `editMode` and the column
|
|
10640
11163
|
* resolves to an editable type for that row. In `'row'` mode every editable cell of the row is
|
|
@@ -10742,11 +11265,17 @@ var Table = class extends Component {
|
|
|
10742
11265
|
this._abortEdit({ focus: true });
|
|
10743
11266
|
return this;
|
|
10744
11267
|
}
|
|
10745
|
-
/**
|
|
11268
|
+
/**
|
|
11269
|
+
* Reports whether a cell or row is currently open for editing.
|
|
11270
|
+
* @returns {boolean} Whether an edit is open.
|
|
11271
|
+
*/
|
|
10746
11272
|
isEditing() {
|
|
10747
11273
|
return this._edit !== null;
|
|
10748
11274
|
}
|
|
10749
|
-
/**
|
|
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
|
+
*/
|
|
10750
11279
|
getEditing() {
|
|
10751
11280
|
return this._edit ? { id: this._edit.id, columnId: this._edit.columnId } : null;
|
|
10752
11281
|
}
|
|
@@ -10755,7 +11284,31 @@ var Table = class extends Component {
|
|
|
10755
11284
|
* @returns {TableRow[]}
|
|
10756
11285
|
*/
|
|
10757
11286
|
_visibleData() {
|
|
10758
|
-
return this.
|
|
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);
|
|
10759
11312
|
}
|
|
10760
11313
|
/**
|
|
10761
11314
|
* Renders the next batch of rows.
|
|
@@ -10767,10 +11320,11 @@ var Table = class extends Component {
|
|
|
10767
11320
|
if (!this._growStep) return this;
|
|
10768
11321
|
const step = Number(count) > 0 ? Math.trunc(Number(count)) : this._growStep;
|
|
10769
11322
|
const before = this._rendered;
|
|
10770
|
-
|
|
11323
|
+
const total = this._projectedData().length;
|
|
11324
|
+
this._rendered = Math.min(total, this._rendered + step);
|
|
10771
11325
|
if (this._rendered === before) return this;
|
|
10772
11326
|
this._renderBody();
|
|
10773
|
-
this.emit("grow", { rendered: this._rendered, total
|
|
11327
|
+
this.emit("grow", { rendered: this._rendered, total });
|
|
10774
11328
|
return this;
|
|
10775
11329
|
}
|
|
10776
11330
|
/**
|
|
@@ -10779,14 +11333,14 @@ var Table = class extends Component {
|
|
|
10779
11333
|
* @fires Table#grow
|
|
10780
11334
|
*/
|
|
10781
11335
|
showAll() {
|
|
10782
|
-
return this.growBy(this.
|
|
11336
|
+
return this.growBy(this._projectedData().length);
|
|
10783
11337
|
}
|
|
10784
11338
|
/**
|
|
10785
11339
|
* How many rows are currently rendered.
|
|
10786
11340
|
* @returns {number}
|
|
10787
11341
|
*/
|
|
10788
11342
|
getRenderedCount() {
|
|
10789
|
-
return Math.min(this._rendered, this.
|
|
11343
|
+
return Math.min(this._rendered, this._projectedData().length);
|
|
10790
11344
|
}
|
|
10791
11345
|
/**
|
|
10792
11346
|
* Keeps the "show more" control in step with what is rendered.
|
|
@@ -10798,7 +11352,7 @@ var Table = class extends Component {
|
|
|
10798
11352
|
*/
|
|
10799
11353
|
_syncGrowing() {
|
|
10800
11354
|
if (!this._growStep) return;
|
|
10801
|
-
const remaining = this.
|
|
11355
|
+
const remaining = this._projectedData().length - this.getRenderedCount();
|
|
10802
11356
|
if (remaining <= 0) {
|
|
10803
11357
|
this._more?.remove();
|
|
10804
11358
|
this._more = null;
|
|
@@ -10869,10 +11423,11 @@ var Table = class extends Component {
|
|
|
10869
11423
|
* @returns {void}
|
|
10870
11424
|
*/
|
|
10871
11425
|
_applyStackedRoles(stacked) {
|
|
10872
|
-
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"]];
|
|
10873
11427
|
for (const [element, role] of parts) {
|
|
10874
11428
|
if (!element) continue;
|
|
10875
11429
|
if (stacked) element.setAttribute("role", role);
|
|
11430
|
+
else if (element === this._table && this._hierarchy) element.setAttribute("role", "treegrid");
|
|
10876
11431
|
else element.removeAttribute("role");
|
|
10877
11432
|
}
|
|
10878
11433
|
for (const [selector, role] of [["tr", "row"], ["td", "cell"], ["th", "columnheader"]]) {
|
|
@@ -10949,7 +11504,8 @@ var Table = class extends Component {
|
|
|
10949
11504
|
this._headers = /* @__PURE__ */ new Map();
|
|
10950
11505
|
for (const column of this._columns) {
|
|
10951
11506
|
const th = h("th", { scope: "col" });
|
|
10952
|
-
|
|
11507
|
+
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
11508
|
+
if (align) th.dataset.align = align;
|
|
10953
11509
|
if (column.headerTitle) th.title = column.headerTitle;
|
|
10954
11510
|
if (column.sortable) {
|
|
10955
11511
|
const button2 = h("button", {
|
|
@@ -10978,6 +11534,8 @@ var Table = class extends Component {
|
|
|
10978
11534
|
this._rowElements = /* @__PURE__ */ new Map();
|
|
10979
11535
|
this._rovingCell = null;
|
|
10980
11536
|
this._rovingMatched = false;
|
|
11537
|
+
const projected = this._projectedData();
|
|
11538
|
+
this._hierarchyMeta = new Map(projected.map((entry) => [entry.id, entry]));
|
|
10981
11539
|
if (this._data.length === 0) {
|
|
10982
11540
|
fragment.append(h(
|
|
10983
11541
|
"tr",
|
|
@@ -10988,10 +11546,12 @@ var Table = class extends Component {
|
|
|
10988
11546
|
}, this._emptyContent())
|
|
10989
11547
|
));
|
|
10990
11548
|
} else {
|
|
10991
|
-
this.
|
|
11549
|
+
this._visibleEntries().forEach((entry, visibleIndex) => {
|
|
11550
|
+
fragment.append(this._createRow(entry.row, entry.index, { ...entry, visibleIndex }));
|
|
11551
|
+
});
|
|
10992
11552
|
}
|
|
10993
11553
|
this._tbody.replaceChildren(fragment);
|
|
10994
|
-
if (this._growStep) this._table.setAttribute("aria-rowcount", String(
|
|
11554
|
+
if (this._growStep) this._table.setAttribute("aria-rowcount", String(projected.length + 1));
|
|
10995
11555
|
this._syncSelectAll();
|
|
10996
11556
|
this._syncGrowing();
|
|
10997
11557
|
if (this._stacked) this._applyStackedRoles(true);
|
|
@@ -11010,18 +11570,27 @@ var Table = class extends Component {
|
|
|
11010
11570
|
if (empty == null) return this.msg("table.empty");
|
|
11011
11571
|
return typeof empty === "function" ? empty() : empty;
|
|
11012
11572
|
}
|
|
11013
|
-
/**
|
|
11014
|
-
|
|
11573
|
+
/**
|
|
11574
|
+
* @param {TableRow} row
|
|
11575
|
+
* @param {number} index
|
|
11576
|
+
* @param {TableHierarchyEntry & {visibleIndex: number}} tree
|
|
11577
|
+
* @returns {HTMLTableRowElement}
|
|
11578
|
+
*/
|
|
11579
|
+
_createRow(row, index, tree) {
|
|
11015
11580
|
const id = this._idFor(row);
|
|
11016
11581
|
const tr = (
|
|
11017
11582
|
/** @type {HTMLTableRowElement} */
|
|
11018
11583
|
h("tr", { dataset: { row: "" } })
|
|
11019
11584
|
);
|
|
11020
|
-
if (this._growStep) tr.setAttribute("aria-rowindex", String(
|
|
11585
|
+
if (this._growStep) tr.setAttribute("aria-rowindex", String(tree.visibleIndex + 2));
|
|
11021
11586
|
const rowClass = typeof this.options.rowClass === "function" ? this.options.rowClass(row) : "";
|
|
11022
11587
|
if (rowClass) tr.classList.add(...String(rowClass).split(/\s+/).filter(Boolean));
|
|
11023
11588
|
if (this.options.selectable !== false) tr.setAttribute("aria-selected", String(this._selected.has(id)));
|
|
11024
|
-
this.
|
|
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 });
|
|
11025
11594
|
const elements = this._rowElements.get(id) ?? [];
|
|
11026
11595
|
elements.push(tr);
|
|
11027
11596
|
this._rowElements.set(id, elements);
|
|
@@ -11039,7 +11608,8 @@ var Table = class extends Component {
|
|
|
11039
11608
|
/** @type {HTMLTableCellElement} */
|
|
11040
11609
|
h("td")
|
|
11041
11610
|
);
|
|
11042
|
-
|
|
11611
|
+
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
11612
|
+
if (align) cell.dataset.align = align;
|
|
11043
11613
|
cell.dataset.label = column.label;
|
|
11044
11614
|
if (column.popin === false) cell.dataset.popin = "false";
|
|
11045
11615
|
if (this._editMode !== false) {
|
|
@@ -11050,7 +11620,7 @@ var Table = class extends Component {
|
|
|
11050
11620
|
this._offerRovingCell(cell, id, column.id);
|
|
11051
11621
|
}
|
|
11052
11622
|
}
|
|
11053
|
-
this._renderCellContent(cell, column, row, index);
|
|
11623
|
+
this._renderCellContent(cell, column, row, index, tree);
|
|
11054
11624
|
tr.append(cell);
|
|
11055
11625
|
});
|
|
11056
11626
|
return tr;
|
|
@@ -11061,13 +11631,33 @@ var Table = class extends Component {
|
|
|
11061
11631
|
* @param {TableColumn} column Column definition.
|
|
11062
11632
|
* @param {TableRow} row Row data.
|
|
11063
11633
|
* @param {number} index Row index.
|
|
11634
|
+
* @param {TableHierarchyEntry} [tree] Hierarchy metadata for the row.
|
|
11064
11635
|
* @returns {void}
|
|
11065
11636
|
*/
|
|
11066
|
-
_renderCellContent(cell, column, row, index) {
|
|
11067
|
-
const value =
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
else
|
|
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);
|
|
11071
11661
|
}
|
|
11072
11662
|
/** @param {MouseEvent} event @returns {void} */
|
|
11073
11663
|
_handleBodyClick(event) {
|
|
@@ -11080,7 +11670,15 @@ var Table = class extends Component {
|
|
|
11080
11670
|
if (!rowElement || !this._tbody.contains(rowElement)) return;
|
|
11081
11671
|
const meta = this._rowMeta.get(rowElement);
|
|
11082
11672
|
if (!meta) return;
|
|
11083
|
-
if (this._edit)
|
|
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
|
+
}
|
|
11084
11682
|
const checkbox = target.closest(".zx-table__row-checkbox");
|
|
11085
11683
|
if (checkbox && this.options.selectable === "multi") {
|
|
11086
11684
|
this._toggleMultiSelection(
|
|
@@ -11176,7 +11774,15 @@ var Table = class extends Component {
|
|
|
11176
11774
|
return entry;
|
|
11177
11775
|
}
|
|
11178
11776
|
if (type === "number") {
|
|
11179
|
-
const
|
|
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 });
|
|
11180
11786
|
host.append(field.el);
|
|
11181
11787
|
entry.component = field;
|
|
11182
11788
|
entry.control = field.getInput();
|
|
@@ -11407,9 +12013,12 @@ var Table = class extends Component {
|
|
|
11407
12013
|
_nextEditableCell(rowIndex, columnId, direction) {
|
|
11408
12014
|
const columnCount = this._columns.length;
|
|
11409
12015
|
if (rowIndex < 0 || columnCount === 0) return null;
|
|
11410
|
-
|
|
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;
|
|
11411
12020
|
let column = this._columns.findIndex((candidate) => candidate.id === columnId);
|
|
11412
|
-
const limit =
|
|
12021
|
+
const limit = visible.length * columnCount + columnCount;
|
|
11413
12022
|
for (let step = 0; step < limit; step += 1) {
|
|
11414
12023
|
column += direction;
|
|
11415
12024
|
if (column >= columnCount) {
|
|
@@ -11419,11 +12028,15 @@ var Table = class extends Component {
|
|
|
11419
12028
|
row -= 1;
|
|
11420
12029
|
column = columnCount - 1;
|
|
11421
12030
|
}
|
|
11422
|
-
if (row < 0 || row >=
|
|
11423
|
-
const candidateRow =
|
|
12031
|
+
if (row < 0 || row >= visible.length) return null;
|
|
12032
|
+
const candidateRow = visible[row];
|
|
11424
12033
|
const candidateColumn = this._columns[column];
|
|
11425
12034
|
if (resolveEditable(candidateColumn, candidateRow) !== false) {
|
|
11426
|
-
return {
|
|
12035
|
+
return {
|
|
12036
|
+
id: this._idFor(candidateRow),
|
|
12037
|
+
columnId: candidateColumn.id,
|
|
12038
|
+
index: this._data.indexOf(candidateRow)
|
|
12039
|
+
};
|
|
11427
12040
|
}
|
|
11428
12041
|
}
|
|
11429
12042
|
return null;
|
|
@@ -11490,14 +12103,16 @@ var Table = class extends Component {
|
|
|
11490
12103
|
const message = this.msg(key);
|
|
11491
12104
|
return message === key ? fallback : message;
|
|
11492
12105
|
}
|
|
11493
|
-
/** @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} */
|
|
11494
12107
|
_toggleMultiSelection(meta, checked, shiftKey) {
|
|
11495
|
-
const
|
|
12108
|
+
const visible = this._visibleData();
|
|
12109
|
+
const anchorIndex = visible.findIndex((row) => Object.is(this._idFor(row), this._selectionAnchorId));
|
|
11496
12110
|
if (shiftKey && anchorIndex >= 0) {
|
|
11497
|
-
const
|
|
11498
|
-
const
|
|
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);
|
|
11499
12114
|
for (let index = start; index <= end; index += 1) {
|
|
11500
|
-
const id = this._idFor(
|
|
12115
|
+
const id = this._idFor(visible[index]);
|
|
11501
12116
|
if (checked) this._selected.add(id);
|
|
11502
12117
|
else this._selected.delete(id);
|
|
11503
12118
|
}
|
|
@@ -11548,7 +12163,34 @@ var Table = class extends Component {
|
|
|
11548
12163
|
const column = this._columns.find((candidate) => candidate.id === this._sort.id);
|
|
11549
12164
|
if (!column) return;
|
|
11550
12165
|
const getValue = typeof column.sortValue === "function" ? column.sortValue : (row) => row?.[column.id];
|
|
11551
|
-
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);
|
|
11552
12194
|
}
|
|
11553
12195
|
/** @returns {boolean} Whether selection changed. */
|
|
11554
12196
|
_pruneSelection() {
|
|
@@ -11572,6 +12214,65 @@ var Table = class extends Component {
|
|
|
11572
12214
|
this.emit("datachange", { rows: this.getData() });
|
|
11573
12215
|
}
|
|
11574
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
|
+
}
|
|
11575
12276
|
function resolveEditable(column, row) {
|
|
11576
12277
|
if (!column || typeof column !== "object") return false;
|
|
11577
12278
|
if (typeof column.editor === "function") {
|
|
@@ -11579,7 +12280,7 @@ function resolveEditable(column, row) {
|
|
|
11579
12280
|
return "custom";
|
|
11580
12281
|
}
|
|
11581
12282
|
const declared = typeof column.editable === "function" ? column.editable(row) : column.editable;
|
|
11582
|
-
if (declared === true) return "text";
|
|
12283
|
+
if (declared === true) return isNumericColumn(column) ? "number" : "text";
|
|
11583
12284
|
if (typeof declared === "string" && EDITOR_TYPES.has(declared)) return (
|
|
11584
12285
|
/** @type {TableEditorType} */
|
|
11585
12286
|
declared
|
|
@@ -11628,6 +12329,71 @@ function firstValidationError(values, columns, row, fallbackMessage = "Invalid v
|
|
|
11628
12329
|
}
|
|
11629
12330
|
return null;
|
|
11630
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
|
+
}
|
|
11631
12397
|
function normalizeEditMode(mode) {
|
|
11632
12398
|
if (mode === "cell" || mode === "row") return mode;
|
|
11633
12399
|
return mode === true ? "cell" : false;
|
|
@@ -12094,6 +12860,29 @@ var MenuButton = class extends Component {
|
|
|
12094
12860
|
isOpen() {
|
|
12095
12861
|
return this.#dropdown.isOpen();
|
|
12096
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
|
+
}
|
|
12097
12886
|
/**
|
|
12098
12887
|
* Sets the visible trigger label.
|
|
12099
12888
|
* @param {string} label Trigger label.
|
|
@@ -12153,7 +12942,8 @@ var MenuButton = class extends Component {
|
|
|
12153
12942
|
const index = Number(element.getAttribute("data-menu-item"));
|
|
12154
12943
|
const item = this.#items[index];
|
|
12155
12944
|
if (!item || item === "-" || item.disabled) return;
|
|
12156
|
-
this.emit("select", { value: item.value, item });
|
|
12945
|
+
const selected = this.emit("select", { value: item.value, item });
|
|
12946
|
+
if (selected.defaultPrevented) return;
|
|
12157
12947
|
try {
|
|
12158
12948
|
item.onselect?.(item.value, item, this);
|
|
12159
12949
|
} finally {
|
|
@@ -13403,177 +14193,6 @@ function restore9(element, state) {
|
|
|
13403
14193
|
element.replaceChildren(...state.children);
|
|
13404
14194
|
}
|
|
13405
14195
|
|
|
13406
|
-
// src/components/permission/permission.js
|
|
13407
|
-
var Permission = class extends Component {
|
|
13408
|
-
static cssName = "permission";
|
|
13409
|
-
/** @type {PermissionOptions} */
|
|
13410
|
-
static defaults = {
|
|
13411
|
-
value: true,
|
|
13412
|
-
groups: [],
|
|
13413
|
-
groupsValueKey: "ID",
|
|
13414
|
-
groupsLabelKey: "name"
|
|
13415
|
-
};
|
|
13416
|
-
/** @returns {HTMLElement} */
|
|
13417
|
-
render() {
|
|
13418
|
-
this._mode = "public";
|
|
13419
|
-
this._groupValue = null;
|
|
13420
|
-
this._groupSelect = null;
|
|
13421
|
-
this._createdRoot = false;
|
|
13422
|
-
this._originalChildren = [];
|
|
13423
|
-
this._root = null;
|
|
13424
|
-
this._originalState = null;
|
|
13425
|
-
this._createdRoot = this.el === null;
|
|
13426
|
-
const root = (
|
|
13427
|
-
/** @type {HTMLElement} */
|
|
13428
|
-
this.el ?? h("div")
|
|
13429
|
-
);
|
|
13430
|
-
this.el = root;
|
|
13431
|
-
this._root = root;
|
|
13432
|
-
if (!this._createdRoot) {
|
|
13433
|
-
this._originalChildren = Array.from(root.childNodes);
|
|
13434
|
-
this._originalState = root.getAttribute("data-state");
|
|
13435
|
-
}
|
|
13436
|
-
const name = uid("zx-permission");
|
|
13437
|
-
const choices = h("div", {
|
|
13438
|
-
class: "zx-permission__choices",
|
|
13439
|
-
role: "radiogroup",
|
|
13440
|
-
ariaLabel: this._message("permission.label", "Permission")
|
|
13441
|
-
});
|
|
13442
|
-
const privateChoice = this._choice(name, "private", this._message("permission.private", "Private"));
|
|
13443
|
-
const publicChoice = this._choice(name, "public", this._message("permission.public", "Public"));
|
|
13444
|
-
const groupChoice = this._choice(name, "group", this._message("permission.group", "Group"));
|
|
13445
|
-
const groupHost = h("div", { ref: "groupHost", class: "zx-permission__groups" });
|
|
13446
|
-
choices.append(privateChoice.label, publicChoice.label, groupChoice.label, groupHost);
|
|
13447
|
-
root.replaceChildren(choices);
|
|
13448
|
-
this.refs.private = privateChoice.input;
|
|
13449
|
-
this.refs.public = publicChoice.input;
|
|
13450
|
-
this.refs.group = groupChoice.input;
|
|
13451
|
-
this._groupSelect = new Select(groupHost, {
|
|
13452
|
-
items: Array.isArray(this.options.groups) ? this.options.groups : [],
|
|
13453
|
-
valueKey: this.options.groupsValueKey,
|
|
13454
|
-
labelKey: this.options.groupsLabelKey,
|
|
13455
|
-
placeholder: this._message("permission.group", "Group")
|
|
13456
|
-
});
|
|
13457
|
-
this._groupSelect.refs.input.setAttribute(
|
|
13458
|
-
"aria-label",
|
|
13459
|
-
this._message("permission.group", "Group")
|
|
13460
|
-
);
|
|
13461
|
-
for (const input of [privateChoice.input, publicChoice.input, groupChoice.input]) {
|
|
13462
|
-
this.listen(input, "change", () => {
|
|
13463
|
-
if (!input.checked) return;
|
|
13464
|
-
if (input.value === "group") this._selectGroupMode();
|
|
13465
|
-
else this.set(input.value);
|
|
13466
|
-
});
|
|
13467
|
-
}
|
|
13468
|
-
this.listen(groupHost, "zx-change", (event) => {
|
|
13469
|
-
event.stopPropagation();
|
|
13470
|
-
if (this._mode !== "group") return;
|
|
13471
|
-
const previous = this.get();
|
|
13472
|
-
this._groupValue = /** @type {CustomEvent} */
|
|
13473
|
-
event.detail.value;
|
|
13474
|
-
const value = this.get();
|
|
13475
|
-
if (!Object.is(previous, value)) this.emit("change", { value });
|
|
13476
|
-
});
|
|
13477
|
-
this.set(this.options.value, { silent: true });
|
|
13478
|
-
return root;
|
|
13479
|
-
}
|
|
13480
|
-
/** Returns the normalized permission value. @returns {'private'|'public'|unknown} */
|
|
13481
|
-
get() {
|
|
13482
|
-
if (this._mode === "private") return "private";
|
|
13483
|
-
if (this._mode === "public") return "public";
|
|
13484
|
-
return this._groupValue;
|
|
13485
|
-
}
|
|
13486
|
-
/**
|
|
13487
|
-
* Sets a public, private, or group permission.
|
|
13488
|
-
* @param {boolean|string|number|symbol|bigint|null} value Permission value.
|
|
13489
|
-
* @param {{silent?: boolean}} [options={}] Update behavior.
|
|
13490
|
-
* @returns {this}
|
|
13491
|
-
* @fires Permission#change
|
|
13492
|
-
*/
|
|
13493
|
-
set(value, { silent = false } = {}) {
|
|
13494
|
-
const previous = this.get();
|
|
13495
|
-
if (value === true || value === "public") {
|
|
13496
|
-
this._mode = "public";
|
|
13497
|
-
} else if (value === false || value === "private") {
|
|
13498
|
-
this._mode = "private";
|
|
13499
|
-
} else {
|
|
13500
|
-
this._mode = "group";
|
|
13501
|
-
this._groupValue = value;
|
|
13502
|
-
this._groupSelect?.set(value, { silent: true });
|
|
13503
|
-
}
|
|
13504
|
-
this._sync();
|
|
13505
|
-
const next = this.get();
|
|
13506
|
-
if (!silent && !Object.is(previous, next)) this.emit("change", { value: next });
|
|
13507
|
-
return this;
|
|
13508
|
-
}
|
|
13509
|
-
/** Destroys the embedded Select and restores an enhanced target. @returns {void} */
|
|
13510
|
-
destroy() {
|
|
13511
|
-
this._groupSelect?.destroy();
|
|
13512
|
-
this._groupSelect = null;
|
|
13513
|
-
if (!this._createdRoot && this.el) {
|
|
13514
|
-
this.el.replaceChildren(...this._originalChildren);
|
|
13515
|
-
if (this._originalState === null) this.el.removeAttribute("data-state");
|
|
13516
|
-
else this.el.setAttribute("data-state", this._originalState);
|
|
13517
|
-
}
|
|
13518
|
-
super.destroy();
|
|
13519
|
-
}
|
|
13520
|
-
/** @returns {void} */
|
|
13521
|
-
_selectGroupMode() {
|
|
13522
|
-
const previous = this.get();
|
|
13523
|
-
this._mode = "group";
|
|
13524
|
-
if (this._groupValue == null) {
|
|
13525
|
-
const first = Array.isArray(this.options.groups) ? this.options.groups[0] : null;
|
|
13526
|
-
this._groupValue = first == null ? null : read(first, this.options.groupsValueKey);
|
|
13527
|
-
}
|
|
13528
|
-
this._groupSelect?.set(this._groupValue, { silent: true });
|
|
13529
|
-
this._sync();
|
|
13530
|
-
const next = this.get();
|
|
13531
|
-
if (!Object.is(previous, next)) this.emit("change", { value: next });
|
|
13532
|
-
}
|
|
13533
|
-
/** @returns {void} */
|
|
13534
|
-
_sync() {
|
|
13535
|
-
this.refs.private.checked = this._mode === "private";
|
|
13536
|
-
this.refs.public.checked = this._mode === "public";
|
|
13537
|
-
this.refs.group.checked = this._mode === "group";
|
|
13538
|
-
if (this._mode === "group") this._groupSelect?.enable();
|
|
13539
|
-
else this._groupSelect?.disable();
|
|
13540
|
-
this._root?.setAttribute("data-state", this._mode);
|
|
13541
|
-
}
|
|
13542
|
-
/**
|
|
13543
|
-
* @param {string} name
|
|
13544
|
-
* @param {'private'|'public'|'group'} value
|
|
13545
|
-
* @param {string} text
|
|
13546
|
-
* @returns {{label: HTMLLabelElement, input: HTMLInputElement}}
|
|
13547
|
-
*/
|
|
13548
|
-
_choice(name, value, text3) {
|
|
13549
|
-
const input = (
|
|
13550
|
-
/** @type {HTMLInputElement} */
|
|
13551
|
-
h("input", {
|
|
13552
|
-
type: "radio",
|
|
13553
|
-
name,
|
|
13554
|
-
value
|
|
13555
|
-
})
|
|
13556
|
-
);
|
|
13557
|
-
const label = (
|
|
13558
|
-
/** @type {HTMLLabelElement} */
|
|
13559
|
-
h("label", {
|
|
13560
|
-
class: "zx-permission__choice"
|
|
13561
|
-
}, input, h("span", {}, text3))
|
|
13562
|
-
);
|
|
13563
|
-
return { label, input };
|
|
13564
|
-
}
|
|
13565
|
-
/** @param {string} key @param {string} fallback @returns {string} */
|
|
13566
|
-
_message(key, fallback) {
|
|
13567
|
-
const message = this.msg(key);
|
|
13568
|
-
return message === key ? fallback : message;
|
|
13569
|
-
}
|
|
13570
|
-
};
|
|
13571
|
-
function read(item, reader) {
|
|
13572
|
-
if (typeof reader === "function") return reader(item);
|
|
13573
|
-
if (item === null || typeof item !== "object") return item;
|
|
13574
|
-
return item[reader];
|
|
13575
|
-
}
|
|
13576
|
-
|
|
13577
14196
|
// src/components/data-filter/filter-core.js
|
|
13578
14197
|
function normalizeText(value) {
|
|
13579
14198
|
return String(value ?? "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLocaleLowerCase();
|
|
@@ -15157,9 +15776,9 @@ function translateChecklistOptions(options = {}) {
|
|
|
15157
15776
|
delete translated.onClick;
|
|
15158
15777
|
return translated;
|
|
15159
15778
|
}
|
|
15160
|
-
function translateDateboxFormat(
|
|
15161
|
-
if (typeof
|
|
15162
|
-
const parts = Array.isArray(
|
|
15779
|
+
function translateDateboxFormat(format2) {
|
|
15780
|
+
if (typeof format2 === "string") return format2.replaceAll(" ", " ");
|
|
15781
|
+
const parts = Array.isArray(format2) ? format2 : ["d", ".", "M", ".", "y"];
|
|
15163
15782
|
const tokens = {
|
|
15164
15783
|
d: "%d",
|
|
15165
15784
|
m: "%m",
|
|
@@ -15347,26 +15966,39 @@ var Checklist2 = class extends ChecklistBase {
|
|
|
15347
15966
|
var BootstrapChecklist = class extends ChecklistBase {
|
|
15348
15967
|
static legacyName = "gx.bootstrap.Checklist";
|
|
15349
15968
|
};
|
|
15350
|
-
|
|
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 {
|
|
15351
15980
|
static legacyName = "gx.zeyos.Permission";
|
|
15352
15981
|
/** @param {Element|string|null} display @param {Record<string, any>} [options={}] */
|
|
15353
15982
|
constructor(display, options = {}) {
|
|
15354
15983
|
super(options, { value: true, groups: [] });
|
|
15355
|
-
const component =
|
|
15356
|
-
value: options.value ?? true,
|
|
15984
|
+
const component = Select.permission(display, {
|
|
15985
|
+
value: fromLegacyPermission(options.value ?? true),
|
|
15357
15986
|
groups: options.groups ?? options.data ?? [],
|
|
15358
|
-
|
|
15359
|
-
|
|
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" }
|
|
15360
15993
|
});
|
|
15361
|
-
this._attach(component, { events: { change: { type: "change", args: (detail) => [detail.value] } }, setters: { value: "set" } });
|
|
15362
15994
|
}
|
|
15363
15995
|
/** @returns {unknown} */
|
|
15364
15996
|
get() {
|
|
15365
|
-
return this._zx.
|
|
15997
|
+
return toLegacyPermission(this._zx.value);
|
|
15366
15998
|
}
|
|
15367
15999
|
/** @param {unknown} value @param {boolean} [silent=false] @returns {this} */
|
|
15368
16000
|
set(value, silent = false) {
|
|
15369
|
-
this._zx.set(value, { silent });
|
|
16001
|
+
this._zx.set(fromLegacyPermission(value), { silent });
|
|
15370
16002
|
return this;
|
|
15371
16003
|
}
|
|
15372
16004
|
};
|
|
@@ -15599,11 +16231,11 @@ var Datebox2 = class extends GxWrapper {
|
|
|
15599
16231
|
constructor(display, options = {}) {
|
|
15600
16232
|
super(options, { timestamp: 0, unit: "milliseconds", format: ["d", ".", "M", ".", "y", " ", "h", ":", "i"] });
|
|
15601
16233
|
const initial = options.timestamp == null || Number(options.timestamp) === 0 ? /* @__PURE__ */ new Date() : legacyDate(options.timestamp, options.unit ?? "milliseconds");
|
|
15602
|
-
const
|
|
16234
|
+
const format2 = translateDateboxFormat(options.format);
|
|
15603
16235
|
const component = new Datebox(display, {
|
|
15604
16236
|
value: initial,
|
|
15605
|
-
format,
|
|
15606
|
-
time: /%[HMS]/.test(
|
|
16237
|
+
format: format2,
|
|
16238
|
+
time: /%[HMS]/.test(format2),
|
|
15607
16239
|
disabled: Boolean(options.disabled)
|
|
15608
16240
|
});
|
|
15609
16241
|
this._attach(component, {
|
|
@@ -15669,13 +16301,13 @@ var PickerBase = class extends GxWrapper {
|
|
|
15669
16301
|
return this;
|
|
15670
16302
|
}
|
|
15671
16303
|
/** @param {string} [format] @returns {Date|number|string|null} */
|
|
15672
|
-
get(
|
|
16304
|
+
get(format2 = this.options.return_format) {
|
|
15673
16305
|
const date = this._readDate();
|
|
15674
16306
|
if (!date) return null;
|
|
15675
|
-
if (
|
|
15676
|
-
if (
|
|
15677
|
-
if (
|
|
15678
|
-
return formatDate(date, String(
|
|
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));
|
|
15679
16311
|
}
|
|
15680
16312
|
/** @returns {number|null} */
|
|
15681
16313
|
getSeconds() {
|
|
@@ -15688,8 +16320,8 @@ var PickerBase = class extends GxWrapper {
|
|
|
15688
16320
|
return this;
|
|
15689
16321
|
}
|
|
15690
16322
|
/** @param {string} format @param {boolean} [enableTimePicker] @returns {this} */
|
|
15691
|
-
setFormat(
|
|
15692
|
-
this.options.format =
|
|
16323
|
+
setFormat(format2, enableTimePicker) {
|
|
16324
|
+
this.options.format = format2;
|
|
15693
16325
|
this.options.timePicker = enableTimePicker;
|
|
15694
16326
|
return this;
|
|
15695
16327
|
}
|
|
@@ -17154,7 +17786,7 @@ var gx = {
|
|
|
17154
17786
|
SelectDyn,
|
|
17155
17787
|
SelectPrio,
|
|
17156
17788
|
Checklist: Checklist2,
|
|
17157
|
-
Permission
|
|
17789
|
+
Permission,
|
|
17158
17790
|
Table: Table2,
|
|
17159
17791
|
Tabbox: Tabbox2,
|
|
17160
17792
|
Panel: Panel2,
|