@zeyos/zx 2.3.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/DESIGN-SYSTEM.md +136 -0
- package/MIGRATION.md +155 -4
- package/README.md +24 -13
- 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 +7 -1
- package/dist/types/components/questionnaire/items.d.ts +327 -0
- package/dist/types/components/questionnaire/questionnaire.d.ts +449 -0
- 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/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 +641 -277
- package/dist/zx-compat.esm.min.js +1 -1
- package/dist/zx-compat.global.js +7609 -2236
- package/dist/zx-compat.global.min.js +3 -3
- package/dist/zx-zeyos.esm.js +546 -87
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +1452 -101
- package/dist/zx.esm.js +7952 -2592
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +7952 -2592
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +2276 -337
- package/docs/llms.md +426 -30
- 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/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/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.js +2 -1
- 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/select/select.css +0 -1
- 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/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 +2 -3
- package/styles/tokens/global.css +5 -5
- package/styles/tokens/semantic.css +5 -3
- package/styles/tokens/themes.css +1 -1
- package/styles/zx.css +10 -1
- package/dist/types/components/permission/permission.d.ts +0 -96
- package/src/components/permission/permission.css +0 -47
- package/src/components/permission/permission.js +0 -201
package/dist/zx-zeyos.esm.js
CHANGED
|
@@ -136,12 +136,12 @@ function registerFieldType(typeOrFormat, strategy) {
|
|
|
136
136
|
function fieldToZxField(meta) {
|
|
137
137
|
const normalized = normalizeMeta(meta);
|
|
138
138
|
const strategy = strategyFor(normalized);
|
|
139
|
-
const
|
|
139
|
+
const fragment2 = strategyPart(strategy.field, normalized);
|
|
140
140
|
const descriptor = {
|
|
141
141
|
id: normalized.id,
|
|
142
142
|
type: "text",
|
|
143
143
|
label: fieldLabel(normalized),
|
|
144
|
-
...
|
|
144
|
+
...fragment2
|
|
145
145
|
};
|
|
146
146
|
if (normalized.description != null) descriptor.description = String(normalized.description);
|
|
147
147
|
if (normalized.required === true || normalized.nullable === false) descriptor.required = true;
|
|
@@ -2970,6 +2970,14 @@ var MonthPicker = class extends DatePicker {
|
|
|
2970
2970
|
static cssName = "month-picker";
|
|
2971
2971
|
/** @type {MonthPickerOptions} */
|
|
2972
2972
|
static defaults = { value: null, min: null, max: null };
|
|
2973
|
+
/**
|
|
2974
|
+
* Creates a month picker with its narrower month-based option contract.
|
|
2975
|
+
* @param {Element|string|null} target Existing element, selector, or null.
|
|
2976
|
+
* @param {MonthPickerOptions} [options={}] Month-picker options.
|
|
2977
|
+
*/
|
|
2978
|
+
constructor(target, options = {}) {
|
|
2979
|
+
super(target, options);
|
|
2980
|
+
}
|
|
2973
2981
|
/** @returns {HTMLElement} */
|
|
2974
2982
|
render() {
|
|
2975
2983
|
const root = (
|
|
@@ -3189,7 +3197,13 @@ var PLACEMENTS = /* @__PURE__ */ new Set([
|
|
|
3189
3197
|
"top-start",
|
|
3190
3198
|
"top-end",
|
|
3191
3199
|
"bottom",
|
|
3192
|
-
"top"
|
|
3200
|
+
"top",
|
|
3201
|
+
"right-start",
|
|
3202
|
+
"right-end",
|
|
3203
|
+
"left-start",
|
|
3204
|
+
"left-end",
|
|
3205
|
+
"right",
|
|
3206
|
+
"left"
|
|
3193
3207
|
]);
|
|
3194
3208
|
function position(anchor, floating, options = {}) {
|
|
3195
3209
|
if (!(anchor instanceof Element) || !(floating instanceof HTMLElement)) {
|
|
@@ -3217,13 +3231,15 @@ function position(anchor, floating, options = {}) {
|
|
|
3217
3231
|
floating.style.inset = "auto";
|
|
3218
3232
|
floating.style.margin = "0";
|
|
3219
3233
|
floating.style.setProperty("position-anchor", anchorName);
|
|
3220
|
-
|
|
3221
|
-
floating.style.setProperty("
|
|
3234
|
+
const area = positionArea(placement, getComputedStyle(anchor).direction === "rtl");
|
|
3235
|
+
floating.style.setProperty("position-area", area);
|
|
3236
|
+
floating.style.setProperty("inset-area", area);
|
|
3222
3237
|
floating.style.setProperty(
|
|
3223
3238
|
"position-try-fallbacks",
|
|
3224
3239
|
flip ? "flip-block, flip-inline, flip-block flip-inline" : "none"
|
|
3225
3240
|
);
|
|
3226
|
-
|
|
3241
|
+
const margin = placement.startsWith("top") ? "margin-bottom" : placement.startsWith("bottom") ? "margin-top" : placement.startsWith("left") ? "margin-right" : "margin-left";
|
|
3242
|
+
floating.style.setProperty(margin, `${offset}px`);
|
|
3227
3243
|
update = () => {
|
|
3228
3244
|
if (matchWidth) floating.style.minWidth = `${anchor.getBoundingClientRect().width}px`;
|
|
3229
3245
|
};
|
|
@@ -3267,14 +3283,20 @@ function position(anchor, floating, options = {}) {
|
|
|
3267
3283
|
}
|
|
3268
3284
|
};
|
|
3269
3285
|
}
|
|
3270
|
-
function positionArea(placement) {
|
|
3286
|
+
function positionArea(placement, rtl) {
|
|
3271
3287
|
return {
|
|
3272
|
-
"bottom-start": "
|
|
3273
|
-
"bottom-end": "
|
|
3274
|
-
"top-start": "
|
|
3275
|
-
"top-end": "
|
|
3276
|
-
|
|
3277
|
-
|
|
3288
|
+
"bottom-start": rtl ? "bottom span-left" : "bottom span-right",
|
|
3289
|
+
"bottom-end": rtl ? "bottom span-right" : "bottom span-left",
|
|
3290
|
+
"top-start": rtl ? "top span-left" : "top span-right",
|
|
3291
|
+
"top-end": rtl ? "top span-right" : "top span-left",
|
|
3292
|
+
"right-start": "right span-bottom",
|
|
3293
|
+
"right-end": "right span-top",
|
|
3294
|
+
"left-start": "left span-bottom",
|
|
3295
|
+
"left-end": "left span-top",
|
|
3296
|
+
bottom: "bottom",
|
|
3297
|
+
top: "top",
|
|
3298
|
+
right: "right",
|
|
3299
|
+
left: "left"
|
|
3278
3300
|
}[placement];
|
|
3279
3301
|
}
|
|
3280
3302
|
function updateFallback(anchor, floating, { placement, offset, flip, matchWidth }) {
|
|
@@ -3284,26 +3306,54 @@ function updateFallback(anchor, floating, { placement, offset, flip, matchWidth
|
|
|
3284
3306
|
const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
3285
3307
|
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
3286
3308
|
let actualPlacement = placement;
|
|
3287
|
-
const
|
|
3309
|
+
const side = placementSide(placement);
|
|
3288
3310
|
const bottomY = anchorRect.bottom + offset;
|
|
3289
3311
|
const topY = anchorRect.top - offset - floatingRect.height;
|
|
3312
|
+
const rightX = anchorRect.right + offset;
|
|
3313
|
+
const leftX = anchorRect.left - offset - floatingRect.width;
|
|
3290
3314
|
if (flip) {
|
|
3291
|
-
if (
|
|
3292
|
-
actualPlacement =
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
placement
|
|
3315
|
+
if (side === "bottom" && bottomY + floatingRect.height > viewportHeight && topY >= 0) {
|
|
3316
|
+
actualPlacement = flipPlacement(placement, "bottom", "top");
|
|
3317
|
+
} else if (side === "top" && topY < 0 && bottomY + floatingRect.height <= viewportHeight) {
|
|
3318
|
+
actualPlacement = flipPlacement(placement, "top", "bottom");
|
|
3319
|
+
} else if (side === "right" && rightX + floatingRect.width > viewportWidth && leftX >= 0) {
|
|
3320
|
+
actualPlacement = flipPlacement(placement, "right", "left");
|
|
3321
|
+
} else if (side === "left" && leftX < 0 && rightX + floatingRect.width <= viewportWidth) {
|
|
3322
|
+
actualPlacement = flipPlacement(placement, "left", "right");
|
|
3297
3323
|
}
|
|
3298
3324
|
}
|
|
3325
|
+
const actualSide = placementSide(actualPlacement);
|
|
3299
3326
|
let left;
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3327
|
+
let top;
|
|
3328
|
+
if (actualSide === "bottom" || actualSide === "top") {
|
|
3329
|
+
const rtl = getComputedStyle(anchor).direction === "rtl";
|
|
3330
|
+
if (actualPlacement.endsWith("-end")) {
|
|
3331
|
+
left = rtl ? anchorRect.left : anchorRect.right - floatingRect.width;
|
|
3332
|
+
} else if (actualPlacement.endsWith("-start")) {
|
|
3333
|
+
left = rtl ? anchorRect.right - floatingRect.width : anchorRect.left;
|
|
3334
|
+
} else left = anchorRect.left + (anchorRect.width - floatingRect.width) / 2;
|
|
3335
|
+
top = actualSide === "bottom" ? bottomY : topY;
|
|
3336
|
+
} else {
|
|
3337
|
+
left = actualSide === "right" ? rightX : leftX;
|
|
3338
|
+
if (actualPlacement.endsWith("-end")) top = anchorRect.bottom - floatingRect.height;
|
|
3339
|
+
else if (actualPlacement.endsWith("-start")) top = anchorRect.top;
|
|
3340
|
+
else top = anchorRect.top + (anchorRect.height - floatingRect.height) / 2;
|
|
3341
|
+
}
|
|
3304
3342
|
floating.style.left = `${Math.round(clamp(left, 0, Math.max(0, viewportWidth - floatingRect.width)))}px`;
|
|
3305
3343
|
floating.style.top = `${Math.round(clamp(top, 0, Math.max(0, viewportHeight - floatingRect.height)))}px`;
|
|
3306
3344
|
}
|
|
3345
|
+
function placementSide(placement) {
|
|
3346
|
+
return (
|
|
3347
|
+
/** @type {'top'|'bottom'|'left'|'right'} */
|
|
3348
|
+
placement.split("-")[0]
|
|
3349
|
+
);
|
|
3350
|
+
}
|
|
3351
|
+
function flipPlacement(placement, from, to) {
|
|
3352
|
+
return (
|
|
3353
|
+
/** @type {Placement} */
|
|
3354
|
+
placement.replace(from, to)
|
|
3355
|
+
);
|
|
3356
|
+
}
|
|
3307
3357
|
function showPopover(element) {
|
|
3308
3358
|
if (typeof element.showPopover !== "function") return;
|
|
3309
3359
|
try {
|
|
@@ -4136,31 +4186,31 @@ var PLACEHOLDER_TOKENS = {
|
|
|
4136
4186
|
"%Y": "YYYY",
|
|
4137
4187
|
"%y": "YY"
|
|
4138
4188
|
};
|
|
4139
|
-
function parseRangeText(text3,
|
|
4189
|
+
function parseRangeText(text3, format2, separator) {
|
|
4140
4190
|
const source = String(text3 ?? "").trim();
|
|
4141
4191
|
if (source === "") return { start: null, end: null };
|
|
4142
4192
|
const raw2 = String(separator ?? " \u2013 ");
|
|
4143
4193
|
const core = raw2.trim();
|
|
4144
|
-
const strict = core !== "" && String(
|
|
4194
|
+
const strict = core !== "" && String(format2).includes(core) && /^\s|\s$/.test(raw2);
|
|
4145
4195
|
const lead = strict ? "\\s+" : "\\s*";
|
|
4146
4196
|
const tail = strict ? "(?:\\s+|$)" : "\\s*";
|
|
4147
4197
|
const parts = core === "" ? [source] : source.split(new RegExp(`${lead}${escapeRegExp(core)}${tail}`));
|
|
4148
4198
|
if (parts.length > 2) return null;
|
|
4149
|
-
const first = parseDate(parts[0].trim(),
|
|
4199
|
+
const first = parseDate(parts[0].trim(), format2);
|
|
4150
4200
|
if (!first) return null;
|
|
4151
4201
|
if (parts.length === 1) return { start: first, end: new Date(first.getTime()) };
|
|
4152
4202
|
if (parts[1].trim() === "") return { start: first, end: null };
|
|
4153
|
-
const second = parseDate(parts[1].trim(),
|
|
4203
|
+
const second = parseDate(parts[1].trim(), format2);
|
|
4154
4204
|
if (!second) return null;
|
|
4155
4205
|
return normalizeRange(first, second);
|
|
4156
4206
|
}
|
|
4157
|
-
function formatRangeText(range,
|
|
4207
|
+
function formatRangeText(range, format2, separator) {
|
|
4158
4208
|
const start = range?.start ?? null;
|
|
4159
4209
|
const end = range?.end ?? null;
|
|
4160
4210
|
if (!start && !end) return "";
|
|
4161
|
-
if (!end) return formatDate(start,
|
|
4162
|
-
if (!start) return formatDate(end,
|
|
4163
|
-
return `${formatDate(start,
|
|
4211
|
+
if (!end) return formatDate(start, format2);
|
|
4212
|
+
if (!start) return formatDate(end, format2);
|
|
4213
|
+
return `${formatDate(start, format2)}${separator}${formatDate(end, format2)}`;
|
|
4164
4214
|
}
|
|
4165
4215
|
var DateRangeBox = class extends Component {
|
|
4166
4216
|
static cssName = "date-range-box";
|
|
@@ -4818,12 +4868,12 @@ var DateTimeBox = function DateTimeBox2(target, options = {}) {
|
|
|
4818
4868
|
function validDate4(value) {
|
|
4819
4869
|
return value instanceof Date && !Number.isNaN(value.getTime()) ? new Date(value.getTime()) : null;
|
|
4820
4870
|
}
|
|
4821
|
-
function effectiveFormat(
|
|
4822
|
-
const value = String(
|
|
4871
|
+
function effectiveFormat(format2, time) {
|
|
4872
|
+
const value = String(format2 || "%d.%m.%Y");
|
|
4823
4873
|
return time && !/%[HM]/.test(value) ? `${value} %H:%M` : value;
|
|
4824
4874
|
}
|
|
4825
|
-
function placeholderFromFormat(
|
|
4826
|
-
return
|
|
4875
|
+
function placeholderFromFormat(format2) {
|
|
4876
|
+
return format2.replace(/%[demYyHMS]/g, (token) => ({
|
|
4827
4877
|
"%d": "DD",
|
|
4828
4878
|
"%e": "D",
|
|
4829
4879
|
"%m": "MM",
|
|
@@ -9074,6 +9124,82 @@ function onBreakpoint(handler, options = {}) {
|
|
|
9074
9124
|
};
|
|
9075
9125
|
}
|
|
9076
9126
|
|
|
9127
|
+
// src/core/format.js
|
|
9128
|
+
var MIN_DIGITS = 0;
|
|
9129
|
+
var MAX_DIGITS = 20;
|
|
9130
|
+
var DEFAULT_MAX_DIGITS = 3;
|
|
9131
|
+
var numberFormatters = /* @__PURE__ */ new Map();
|
|
9132
|
+
function formatNumber(value, options = {}) {
|
|
9133
|
+
const number = toFiniteNumber(value);
|
|
9134
|
+
if (number === null) return "";
|
|
9135
|
+
const { locale = getLanguage(), decimals, minDecimals, maxDecimals, group = true } = options;
|
|
9136
|
+
return format(locale, digitOptions({ decimals, minDecimals, maxDecimals, group }), number);
|
|
9137
|
+
}
|
|
9138
|
+
function formatCurrency(value, currency, options = {}) {
|
|
9139
|
+
const number = toFiniteNumber(value);
|
|
9140
|
+
if (number === null) return "";
|
|
9141
|
+
const { locale = getLanguage(), decimals } = options;
|
|
9142
|
+
const code = currencyCode(currency);
|
|
9143
|
+
if (code === null) return formatNumber(number, { locale, decimals });
|
|
9144
|
+
const digits = digitOptions({ decimals, group: true });
|
|
9145
|
+
return format(locale, { ...digits, style: "currency", currency: code }, number);
|
|
9146
|
+
}
|
|
9147
|
+
function formatPercent2(value, options = {}) {
|
|
9148
|
+
const number = toFiniteNumber(value);
|
|
9149
|
+
if (number === null) return "";
|
|
9150
|
+
const { locale = getLanguage(), decimals = 0 } = options;
|
|
9151
|
+
return format(locale, { ...digitOptions({ decimals, group: true }), style: "percent" }, number);
|
|
9152
|
+
}
|
|
9153
|
+
function format(locale, options, value) {
|
|
9154
|
+
const key = `${locale}\0${JSON.stringify(options)}`;
|
|
9155
|
+
let formatter = numberFormatters.get(key);
|
|
9156
|
+
if (formatter === void 0) {
|
|
9157
|
+
formatter = createNumberFormat(locale, options);
|
|
9158
|
+
numberFormatters.set(key, formatter);
|
|
9159
|
+
}
|
|
9160
|
+
return formatter.format(value);
|
|
9161
|
+
}
|
|
9162
|
+
function createNumberFormat(locale, options) {
|
|
9163
|
+
try {
|
|
9164
|
+
return new Intl.NumberFormat(locale, options);
|
|
9165
|
+
} catch {
|
|
9166
|
+
try {
|
|
9167
|
+
return new Intl.NumberFormat(void 0, options);
|
|
9168
|
+
} catch {
|
|
9169
|
+
return new Intl.NumberFormat();
|
|
9170
|
+
}
|
|
9171
|
+
}
|
|
9172
|
+
}
|
|
9173
|
+
function digitOptions({ decimals, minDecimals, maxDecimals, group = true }) {
|
|
9174
|
+
const result = { useGrouping: group !== false };
|
|
9175
|
+
const min = digitCount(minDecimals ?? decimals);
|
|
9176
|
+
const max = digitCount(maxDecimals ?? decimals);
|
|
9177
|
+
if (min !== null) result.minimumFractionDigits = min;
|
|
9178
|
+
if (max !== null) {
|
|
9179
|
+
result.maximumFractionDigits = max;
|
|
9180
|
+
if (min !== null && min > max) result.minimumFractionDigits = max;
|
|
9181
|
+
} else if (min !== null) {
|
|
9182
|
+
result.maximumFractionDigits = Math.max(min, DEFAULT_MAX_DIGITS);
|
|
9183
|
+
}
|
|
9184
|
+
return result;
|
|
9185
|
+
}
|
|
9186
|
+
function digitCount(value) {
|
|
9187
|
+
if (value == null) return null;
|
|
9188
|
+
const number = Number(value);
|
|
9189
|
+
if (!Number.isFinite(number)) return null;
|
|
9190
|
+
return Math.min(MAX_DIGITS, Math.max(MIN_DIGITS, Math.round(number)));
|
|
9191
|
+
}
|
|
9192
|
+
function toFiniteNumber(value) {
|
|
9193
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
9194
|
+
const number = typeof value === "number" ? value : Number(value);
|
|
9195
|
+
return Number.isFinite(number) ? number : null;
|
|
9196
|
+
}
|
|
9197
|
+
function currencyCode(value) {
|
|
9198
|
+
if (typeof value !== "string") return null;
|
|
9199
|
+
const code = value.trim().toUpperCase();
|
|
9200
|
+
return /^[A-Z]{3}$/.test(code) ? code : null;
|
|
9201
|
+
}
|
|
9202
|
+
|
|
9077
9203
|
// src/components/table/sort.js
|
|
9078
9204
|
function compareStrings(left, right) {
|
|
9079
9205
|
return String(left).localeCompare(String(right));
|
|
@@ -9129,7 +9255,8 @@ var Table = class extends Component {
|
|
|
9129
9255
|
emptyText: null,
|
|
9130
9256
|
rowClass: null,
|
|
9131
9257
|
zebra: true,
|
|
9132
|
-
editMode: false
|
|
9258
|
+
editMode: false,
|
|
9259
|
+
hierarchy: false
|
|
9133
9260
|
};
|
|
9134
9261
|
/**
|
|
9135
9262
|
* Creates a table around a target or creates a new root when target is null.
|
|
@@ -9166,8 +9293,17 @@ var Table = class extends Component {
|
|
|
9166
9293
|
this._rovingKey = null;
|
|
9167
9294
|
this._rovingCell = null;
|
|
9168
9295
|
this._rovingMatched = false;
|
|
9296
|
+
this._hierarchy = normalizeHierarchy(this.options.hierarchy, this._columns);
|
|
9297
|
+
this._expanded = initialExpanded(this._hierarchy?.expanded);
|
|
9169
9298
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
9299
|
+
if (this._hierarchy?.expanded === true) {
|
|
9300
|
+
for (const id of hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId)) {
|
|
9301
|
+
this._expanded.add(id);
|
|
9302
|
+
}
|
|
9303
|
+
}
|
|
9304
|
+
this._reconcileExpanded();
|
|
9170
9305
|
this._table = h("table", { class: "zx-table__table" });
|
|
9306
|
+
if (this._hierarchy) this._table.setAttribute("role", "treegrid");
|
|
9171
9307
|
this._colgroup = h("colgroup", { class: "zx-table__columns" });
|
|
9172
9308
|
this._thead = h("thead", { class: "zx-table__head" });
|
|
9173
9309
|
this._tbody = h("tbody", { class: "zx-table__body" });
|
|
@@ -9236,6 +9372,7 @@ var Table = class extends Component {
|
|
|
9236
9372
|
assertRows(rows);
|
|
9237
9373
|
this._data = [...rows];
|
|
9238
9374
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
9375
|
+
this._reconcileExpanded();
|
|
9239
9376
|
const selectionChanged = this._pruneSelection();
|
|
9240
9377
|
this._renderBody();
|
|
9241
9378
|
if (selectionChanged) this._emitSelectionChange();
|
|
@@ -9253,6 +9390,7 @@ var Table = class extends Component {
|
|
|
9253
9390
|
assertRows(rows);
|
|
9254
9391
|
this._data.push(...rows);
|
|
9255
9392
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
9393
|
+
this._reconcileExpanded();
|
|
9256
9394
|
this._renderBody();
|
|
9257
9395
|
this._emitDataChange();
|
|
9258
9396
|
return this;
|
|
@@ -9272,6 +9410,7 @@ var Table = class extends Component {
|
|
|
9272
9410
|
this._data[index] = row;
|
|
9273
9411
|
if (wasSelected) this._selected.add(this._idFor(row));
|
|
9274
9412
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
9413
|
+
this._reconcileExpanded();
|
|
9275
9414
|
this._renderBody();
|
|
9276
9415
|
if (wasSelected && !Object.is(id, this._idFor(row))) this._emitSelectionChange();
|
|
9277
9416
|
this._emitDataChange();
|
|
@@ -9289,6 +9428,7 @@ var Table = class extends Component {
|
|
|
9289
9428
|
const index = this._data.findIndex((candidate) => Object.is(this._idFor(candidate), id));
|
|
9290
9429
|
if (index < 0) return this;
|
|
9291
9430
|
this._data.splice(index, 1);
|
|
9431
|
+
this._reconcileExpanded();
|
|
9292
9432
|
const selectionChanged = this._selected.delete(id);
|
|
9293
9433
|
if (Object.is(this._selectionAnchorId, id)) this._selectionAnchorId = null;
|
|
9294
9434
|
this._renderBody();
|
|
@@ -9304,7 +9444,10 @@ var Table = class extends Component {
|
|
|
9304
9444
|
getRow(id) {
|
|
9305
9445
|
return this._data.find((row) => Object.is(this._idFor(row), id)) ?? null;
|
|
9306
9446
|
}
|
|
9307
|
-
/**
|
|
9447
|
+
/**
|
|
9448
|
+
* Returns a shallow copy of the current rows in display order.
|
|
9449
|
+
* @returns {TableRow[]} Current table rows.
|
|
9450
|
+
*/
|
|
9308
9451
|
getData() {
|
|
9309
9452
|
return [...this._data];
|
|
9310
9453
|
}
|
|
@@ -9318,6 +9461,7 @@ var Table = class extends Component {
|
|
|
9318
9461
|
empty() {
|
|
9319
9462
|
const selectionChanged = this._selected.size > 0;
|
|
9320
9463
|
this._data = [];
|
|
9464
|
+
this._expanded.clear();
|
|
9321
9465
|
this._selected.clear();
|
|
9322
9466
|
this._selectionAnchorId = null;
|
|
9323
9467
|
this._renderBody();
|
|
@@ -9352,7 +9496,10 @@ var Table = class extends Component {
|
|
|
9352
9496
|
if (!options.silent) this.emit("sort", { id, dir: direction });
|
|
9353
9497
|
return this;
|
|
9354
9498
|
}
|
|
9355
|
-
/**
|
|
9499
|
+
/**
|
|
9500
|
+
* Returns selected rows in current display order.
|
|
9501
|
+
* @returns {TableRow[]} Selected rows.
|
|
9502
|
+
*/
|
|
9356
9503
|
getSelection() {
|
|
9357
9504
|
return this._data.filter((row) => this._selected.has(this._idFor(row)));
|
|
9358
9505
|
}
|
|
@@ -9391,6 +9538,75 @@ var Table = class extends Component {
|
|
|
9391
9538
|
this._emitSelectionChange();
|
|
9392
9539
|
return this;
|
|
9393
9540
|
}
|
|
9541
|
+
/**
|
|
9542
|
+
* Toggles one hierarchy branch. A leaf or an id absent from the table is a no-op.
|
|
9543
|
+
* @param {unknown} id Row id.
|
|
9544
|
+
* @param {{silent?: boolean}} [options={}] Event behavior.
|
|
9545
|
+
* @returns {this}
|
|
9546
|
+
* @fires Table#rowtoggle
|
|
9547
|
+
*/
|
|
9548
|
+
toggleRow(id, options = {}) {
|
|
9549
|
+
return this._expanded.has(id) ? this.collapseRow(id, options) : this.expandRow(id, options);
|
|
9550
|
+
}
|
|
9551
|
+
/**
|
|
9552
|
+
* Expands one hierarchy branch.
|
|
9553
|
+
* @param {unknown} id Row id.
|
|
9554
|
+
* @param {{silent?: boolean}} [options={}] Event behavior.
|
|
9555
|
+
* @returns {this}
|
|
9556
|
+
* @fires Table#rowtoggle
|
|
9557
|
+
*/
|
|
9558
|
+
expandRow(id, options = {}) {
|
|
9559
|
+
return this._setRowExpanded(id, true, options);
|
|
9560
|
+
}
|
|
9561
|
+
/**
|
|
9562
|
+
* Collapses one hierarchy branch without discarding its descendants or their expansion state.
|
|
9563
|
+
* @param {unknown} id Row id.
|
|
9564
|
+
* @param {{silent?: boolean}} [options={}] Event behavior.
|
|
9565
|
+
* @returns {this}
|
|
9566
|
+
* @fires Table#rowtoggle
|
|
9567
|
+
*/
|
|
9568
|
+
collapseRow(id, options = {}) {
|
|
9569
|
+
return this._setRowExpanded(id, false, options);
|
|
9570
|
+
}
|
|
9571
|
+
/**
|
|
9572
|
+
* Expands every row that currently has children.
|
|
9573
|
+
* @param {{silent?: boolean}} [options={}] Event behavior. When not silent, one `rowtoggle`
|
|
9574
|
+
* event is emitted per branch whose state changed.
|
|
9575
|
+
* @returns {this}
|
|
9576
|
+
*/
|
|
9577
|
+
expandAll(options = {}) {
|
|
9578
|
+
if (!this._hierarchy) return this;
|
|
9579
|
+
const branchIds = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
|
|
9580
|
+
const changed = branchIds.filter((id) => !this._expanded.has(id));
|
|
9581
|
+
for (const id of changed) this._expanded.add(id);
|
|
9582
|
+
if (changed.length) this._renderBody();
|
|
9583
|
+
if (!options.silent) {
|
|
9584
|
+
for (const id of changed) this._emitRowToggle(id, true);
|
|
9585
|
+
}
|
|
9586
|
+
return this;
|
|
9587
|
+
}
|
|
9588
|
+
/**
|
|
9589
|
+
* Collapses every hierarchy branch.
|
|
9590
|
+
* @param {{silent?: boolean}} [options={}] Event behavior.
|
|
9591
|
+
* @returns {this}
|
|
9592
|
+
*/
|
|
9593
|
+
collapseAll(options = {}) {
|
|
9594
|
+
if (!this._hierarchy || this._expanded.size === 0) return this;
|
|
9595
|
+
const changed = [...this._expanded];
|
|
9596
|
+
this._expanded.clear();
|
|
9597
|
+
this._renderBody();
|
|
9598
|
+
if (!options.silent) {
|
|
9599
|
+
for (const id of changed) this._emitRowToggle(id, false);
|
|
9600
|
+
}
|
|
9601
|
+
return this;
|
|
9602
|
+
}
|
|
9603
|
+
/**
|
|
9604
|
+
* Returns expanded branch ids in current flat-data order.
|
|
9605
|
+
* @returns {unknown[]} Expanded branch ids.
|
|
9606
|
+
*/
|
|
9607
|
+
getExpanded() {
|
|
9608
|
+
return this._data.map((row) => this._idFor(row)).filter((id) => this._expanded.has(id));
|
|
9609
|
+
}
|
|
9394
9610
|
/**
|
|
9395
9611
|
* Opens the editor for a cell. No-op unless the table runs with `editMode` and the column
|
|
9396
9612
|
* resolves to an editable type for that row. In `'row'` mode every editable cell of the row is
|
|
@@ -9498,11 +9714,17 @@ var Table = class extends Component {
|
|
|
9498
9714
|
this._abortEdit({ focus: true });
|
|
9499
9715
|
return this;
|
|
9500
9716
|
}
|
|
9501
|
-
/**
|
|
9717
|
+
/**
|
|
9718
|
+
* Reports whether a cell or row is currently open for editing.
|
|
9719
|
+
* @returns {boolean} Whether an edit is open.
|
|
9720
|
+
*/
|
|
9502
9721
|
isEditing() {
|
|
9503
9722
|
return this._edit !== null;
|
|
9504
9723
|
}
|
|
9505
|
-
/**
|
|
9724
|
+
/**
|
|
9725
|
+
* Returns the row id and focused column id for the open edit.
|
|
9726
|
+
* @returns {{id: unknown, columnId: string}|null} Editing location, or null.
|
|
9727
|
+
*/
|
|
9506
9728
|
getEditing() {
|
|
9507
9729
|
return this._edit ? { id: this._edit.id, columnId: this._edit.columnId } : null;
|
|
9508
9730
|
}
|
|
@@ -9511,7 +9733,31 @@ var Table = class extends Component {
|
|
|
9511
9733
|
* @returns {TableRow[]}
|
|
9512
9734
|
*/
|
|
9513
9735
|
_visibleData() {
|
|
9514
|
-
return this.
|
|
9736
|
+
return this._visibleEntries().map((entry) => entry.row);
|
|
9737
|
+
}
|
|
9738
|
+
/** @returns {TableHierarchyEntry[]} Rows visible after hierarchy expansion, before growing. */
|
|
9739
|
+
_projectedData() {
|
|
9740
|
+
if (!this._hierarchy) {
|
|
9741
|
+
return this._data.map((row, index) => ({
|
|
9742
|
+
row,
|
|
9743
|
+
id: this._idFor(row),
|
|
9744
|
+
index,
|
|
9745
|
+
depth: 0,
|
|
9746
|
+
hasChildren: false,
|
|
9747
|
+
parentId: null
|
|
9748
|
+
}));
|
|
9749
|
+
}
|
|
9750
|
+
return projectHierarchyRows(
|
|
9751
|
+
this._data,
|
|
9752
|
+
this.options.rowId,
|
|
9753
|
+
this._hierarchy.parentId,
|
|
9754
|
+
this._expanded
|
|
9755
|
+
);
|
|
9756
|
+
}
|
|
9757
|
+
/** @returns {TableHierarchyEntry[]} Rows that currently have DOM entries. */
|
|
9758
|
+
_visibleEntries() {
|
|
9759
|
+
const projected = this._projectedData();
|
|
9760
|
+
return this._rendered === Infinity ? projected : projected.slice(0, this._rendered);
|
|
9515
9761
|
}
|
|
9516
9762
|
/**
|
|
9517
9763
|
* Renders the next batch of rows.
|
|
@@ -9523,10 +9769,11 @@ var Table = class extends Component {
|
|
|
9523
9769
|
if (!this._growStep) return this;
|
|
9524
9770
|
const step = Number(count) > 0 ? Math.trunc(Number(count)) : this._growStep;
|
|
9525
9771
|
const before = this._rendered;
|
|
9526
|
-
|
|
9772
|
+
const total = this._projectedData().length;
|
|
9773
|
+
this._rendered = Math.min(total, this._rendered + step);
|
|
9527
9774
|
if (this._rendered === before) return this;
|
|
9528
9775
|
this._renderBody();
|
|
9529
|
-
this.emit("grow", { rendered: this._rendered, total
|
|
9776
|
+
this.emit("grow", { rendered: this._rendered, total });
|
|
9530
9777
|
return this;
|
|
9531
9778
|
}
|
|
9532
9779
|
/**
|
|
@@ -9535,14 +9782,14 @@ var Table = class extends Component {
|
|
|
9535
9782
|
* @fires Table#grow
|
|
9536
9783
|
*/
|
|
9537
9784
|
showAll() {
|
|
9538
|
-
return this.growBy(this.
|
|
9785
|
+
return this.growBy(this._projectedData().length);
|
|
9539
9786
|
}
|
|
9540
9787
|
/**
|
|
9541
9788
|
* How many rows are currently rendered.
|
|
9542
9789
|
* @returns {number}
|
|
9543
9790
|
*/
|
|
9544
9791
|
getRenderedCount() {
|
|
9545
|
-
return Math.min(this._rendered, this.
|
|
9792
|
+
return Math.min(this._rendered, this._projectedData().length);
|
|
9546
9793
|
}
|
|
9547
9794
|
/**
|
|
9548
9795
|
* Keeps the "show more" control in step with what is rendered.
|
|
@@ -9554,7 +9801,7 @@ var Table = class extends Component {
|
|
|
9554
9801
|
*/
|
|
9555
9802
|
_syncGrowing() {
|
|
9556
9803
|
if (!this._growStep) return;
|
|
9557
|
-
const remaining = this.
|
|
9804
|
+
const remaining = this._projectedData().length - this.getRenderedCount();
|
|
9558
9805
|
if (remaining <= 0) {
|
|
9559
9806
|
this._more?.remove();
|
|
9560
9807
|
this._more = null;
|
|
@@ -9625,10 +9872,11 @@ var Table = class extends Component {
|
|
|
9625
9872
|
* @returns {void}
|
|
9626
9873
|
*/
|
|
9627
9874
|
_applyStackedRoles(stacked) {
|
|
9628
|
-
const parts = [[this._table, "table"], [this._thead, "rowgroup"], [this._tbody, "rowgroup"]];
|
|
9875
|
+
const parts = [[this._table, this._hierarchy ? "treegrid" : "table"], [this._thead, "rowgroup"], [this._tbody, "rowgroup"]];
|
|
9629
9876
|
for (const [element, role] of parts) {
|
|
9630
9877
|
if (!element) continue;
|
|
9631
9878
|
if (stacked) element.setAttribute("role", role);
|
|
9879
|
+
else if (element === this._table && this._hierarchy) element.setAttribute("role", "treegrid");
|
|
9632
9880
|
else element.removeAttribute("role");
|
|
9633
9881
|
}
|
|
9634
9882
|
for (const [selector, role] of [["tr", "row"], ["td", "cell"], ["th", "columnheader"]]) {
|
|
@@ -9659,9 +9907,9 @@ var Table = class extends Component {
|
|
|
9659
9907
|
}
|
|
9660
9908
|
/** @returns {void} */
|
|
9661
9909
|
_renderColumns() {
|
|
9662
|
-
const
|
|
9910
|
+
const fragment2 = document.createDocumentFragment();
|
|
9663
9911
|
if (this.options.selectable === "multi") {
|
|
9664
|
-
|
|
9912
|
+
fragment2.append(h("col", { class: "zx-table__selection-column" }));
|
|
9665
9913
|
}
|
|
9666
9914
|
const fractions = this._columns.map((column) => parseFraction(column.width));
|
|
9667
9915
|
const total = fractions.reduce((sum, value) => sum + value, 0);
|
|
@@ -9670,9 +9918,9 @@ var Table = class extends Component {
|
|
|
9670
9918
|
const col = h("col");
|
|
9671
9919
|
if (fractions[index] > 0) col.style.width = `${fractions[index] / total * 100}%`;
|
|
9672
9920
|
else if (column.width && column.width !== "auto") col.style.width = String(column.width);
|
|
9673
|
-
|
|
9921
|
+
fragment2.append(col);
|
|
9674
9922
|
});
|
|
9675
|
-
this._colgroup.replaceChildren(
|
|
9923
|
+
this._colgroup.replaceChildren(fragment2);
|
|
9676
9924
|
}
|
|
9677
9925
|
/** @returns {void} */
|
|
9678
9926
|
_renderHeader() {
|
|
@@ -9705,7 +9953,8 @@ var Table = class extends Component {
|
|
|
9705
9953
|
this._headers = /* @__PURE__ */ new Map();
|
|
9706
9954
|
for (const column of this._columns) {
|
|
9707
9955
|
const th = h("th", { scope: "col" });
|
|
9708
|
-
|
|
9956
|
+
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
9957
|
+
if (align) th.dataset.align = align;
|
|
9709
9958
|
if (column.headerTitle) th.title = column.headerTitle;
|
|
9710
9959
|
if (column.sortable) {
|
|
9711
9960
|
const button = h("button", {
|
|
@@ -9729,13 +9978,15 @@ var Table = class extends Component {
|
|
|
9729
9978
|
/** @returns {void} @fires Table#editcancel */
|
|
9730
9979
|
_renderBody() {
|
|
9731
9980
|
this._abortEdit({ focus: false });
|
|
9732
|
-
const
|
|
9981
|
+
const fragment2 = document.createDocumentFragment();
|
|
9733
9982
|
this._rowMeta = /* @__PURE__ */ new WeakMap();
|
|
9734
9983
|
this._rowElements = /* @__PURE__ */ new Map();
|
|
9735
9984
|
this._rovingCell = null;
|
|
9736
9985
|
this._rovingMatched = false;
|
|
9986
|
+
const projected = this._projectedData();
|
|
9987
|
+
this._hierarchyMeta = new Map(projected.map((entry) => [entry.id, entry]));
|
|
9737
9988
|
if (this._data.length === 0) {
|
|
9738
|
-
|
|
9989
|
+
fragment2.append(h(
|
|
9739
9990
|
"tr",
|
|
9740
9991
|
{ class: "zx-table__empty-row" },
|
|
9741
9992
|
h("td", {
|
|
@@ -9744,10 +9995,12 @@ var Table = class extends Component {
|
|
|
9744
9995
|
}, this._emptyContent())
|
|
9745
9996
|
));
|
|
9746
9997
|
} else {
|
|
9747
|
-
this.
|
|
9998
|
+
this._visibleEntries().forEach((entry, visibleIndex) => {
|
|
9999
|
+
fragment2.append(this._createRow(entry.row, entry.index, { ...entry, visibleIndex }));
|
|
10000
|
+
});
|
|
9748
10001
|
}
|
|
9749
|
-
this._tbody.replaceChildren(
|
|
9750
|
-
if (this._growStep) this._table.setAttribute("aria-rowcount", String(
|
|
10002
|
+
this._tbody.replaceChildren(fragment2);
|
|
10003
|
+
if (this._growStep) this._table.setAttribute("aria-rowcount", String(projected.length + 1));
|
|
9751
10004
|
this._syncSelectAll();
|
|
9752
10005
|
this._syncGrowing();
|
|
9753
10006
|
if (this._stacked) this._applyStackedRoles(true);
|
|
@@ -9766,18 +10019,27 @@ var Table = class extends Component {
|
|
|
9766
10019
|
if (empty == null) return this.msg("table.empty");
|
|
9767
10020
|
return typeof empty === "function" ? empty() : empty;
|
|
9768
10021
|
}
|
|
9769
|
-
/**
|
|
9770
|
-
|
|
10022
|
+
/**
|
|
10023
|
+
* @param {TableRow} row
|
|
10024
|
+
* @param {number} index
|
|
10025
|
+
* @param {TableHierarchyEntry & {visibleIndex: number}} tree
|
|
10026
|
+
* @returns {HTMLTableRowElement}
|
|
10027
|
+
*/
|
|
10028
|
+
_createRow(row, index, tree) {
|
|
9771
10029
|
const id = this._idFor(row);
|
|
9772
10030
|
const tr = (
|
|
9773
10031
|
/** @type {HTMLTableRowElement} */
|
|
9774
10032
|
h("tr", { dataset: { row: "" } })
|
|
9775
10033
|
);
|
|
9776
|
-
if (this._growStep) tr.setAttribute("aria-rowindex", String(
|
|
10034
|
+
if (this._growStep) tr.setAttribute("aria-rowindex", String(tree.visibleIndex + 2));
|
|
9777
10035
|
const rowClass = typeof this.options.rowClass === "function" ? this.options.rowClass(row) : "";
|
|
9778
10036
|
if (rowClass) tr.classList.add(...String(rowClass).split(/\s+/).filter(Boolean));
|
|
9779
10037
|
if (this.options.selectable !== false) tr.setAttribute("aria-selected", String(this._selected.has(id)));
|
|
9780
|
-
this.
|
|
10038
|
+
if (this._hierarchy) {
|
|
10039
|
+
tr.setAttribute("aria-level", String(tree.depth + 1));
|
|
10040
|
+
if (tree.hasChildren) tr.setAttribute("aria-expanded", String(this._expanded.has(id)));
|
|
10041
|
+
}
|
|
10042
|
+
this._rowMeta.set(tr, { row, id, index, visibleIndex: tree.visibleIndex });
|
|
9781
10043
|
const elements = this._rowElements.get(id) ?? [];
|
|
9782
10044
|
elements.push(tr);
|
|
9783
10045
|
this._rowElements.set(id, elements);
|
|
@@ -9795,7 +10057,8 @@ var Table = class extends Component {
|
|
|
9795
10057
|
/** @type {HTMLTableCellElement} */
|
|
9796
10058
|
h("td")
|
|
9797
10059
|
);
|
|
9798
|
-
|
|
10060
|
+
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
10061
|
+
if (align) cell.dataset.align = align;
|
|
9799
10062
|
cell.dataset.label = column.label;
|
|
9800
10063
|
if (column.popin === false) cell.dataset.popin = "false";
|
|
9801
10064
|
if (this._editMode !== false) {
|
|
@@ -9806,7 +10069,7 @@ var Table = class extends Component {
|
|
|
9806
10069
|
this._offerRovingCell(cell, id, column.id);
|
|
9807
10070
|
}
|
|
9808
10071
|
}
|
|
9809
|
-
this._renderCellContent(cell, column, row, index);
|
|
10072
|
+
this._renderCellContent(cell, column, row, index, tree);
|
|
9810
10073
|
tr.append(cell);
|
|
9811
10074
|
});
|
|
9812
10075
|
return tr;
|
|
@@ -9817,13 +10080,33 @@ var Table = class extends Component {
|
|
|
9817
10080
|
* @param {TableColumn} column Column definition.
|
|
9818
10081
|
* @param {TableRow} row Row data.
|
|
9819
10082
|
* @param {number} index Row index.
|
|
10083
|
+
* @param {TableHierarchyEntry} [tree] Hierarchy metadata for the row.
|
|
9820
10084
|
* @returns {void}
|
|
9821
10085
|
*/
|
|
9822
|
-
_renderCellContent(cell, column, row, index) {
|
|
9823
|
-
const value =
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
else
|
|
10086
|
+
_renderCellContent(cell, column, row, index, tree = this._hierarchyMeta?.get(this._idFor(row))) {
|
|
10087
|
+
const value = formatTableCell(column, row, index);
|
|
10088
|
+
const content = h("span", { class: "zx-table__cell-content" });
|
|
10089
|
+
if (value && typeof value === "object" && typeof value.nodeType === "number") content.append(value);
|
|
10090
|
+
else if (value != null) content.append(document.createTextNode(String(value)));
|
|
10091
|
+
if (!this._hierarchy || column.id !== this._hierarchy.column || !tree) {
|
|
10092
|
+
cell.replaceChildren(...content.childNodes);
|
|
10093
|
+
return;
|
|
10094
|
+
}
|
|
10095
|
+
const branch = h("span", { class: "zx-table__tree-cell" });
|
|
10096
|
+
branch.style.setProperty("--zx-table-depth", String(tree.depth));
|
|
10097
|
+
if (tree.hasChildren) {
|
|
10098
|
+
const expanded = this._expanded.has(tree.id);
|
|
10099
|
+
branch.append(h("button", {
|
|
10100
|
+
class: "zx-table__tree-toggle",
|
|
10101
|
+
type: "button",
|
|
10102
|
+
ariaExpanded: String(expanded),
|
|
10103
|
+
ariaLabel: `${expanded ? "Collapse" : "Expand"} row ${index + 1}`
|
|
10104
|
+
}, icon(expanded ? "chevron-down" : "chevron-right", { size: 14 })));
|
|
10105
|
+
} else {
|
|
10106
|
+
branch.append(h("span", { class: "zx-table__tree-spacer", ariaHidden: "true" }));
|
|
10107
|
+
}
|
|
10108
|
+
branch.append(content);
|
|
10109
|
+
cell.replaceChildren(branch);
|
|
9827
10110
|
}
|
|
9828
10111
|
/** @param {MouseEvent} event @returns {void} */
|
|
9829
10112
|
_handleBodyClick(event) {
|
|
@@ -9836,7 +10119,15 @@ var Table = class extends Component {
|
|
|
9836
10119
|
if (!rowElement || !this._tbody.contains(rowElement)) return;
|
|
9837
10120
|
const meta = this._rowMeta.get(rowElement);
|
|
9838
10121
|
if (!meta) return;
|
|
9839
|
-
if (this._edit)
|
|
10122
|
+
if (this._edit) {
|
|
10123
|
+
this.commitEdit();
|
|
10124
|
+
if (this._edit) return;
|
|
10125
|
+
}
|
|
10126
|
+
const disclosure = target.closest(".zx-table__tree-toggle");
|
|
10127
|
+
if (disclosure) {
|
|
10128
|
+
this.toggleRow(meta.id);
|
|
10129
|
+
return;
|
|
10130
|
+
}
|
|
9840
10131
|
const checkbox = target.closest(".zx-table__row-checkbox");
|
|
9841
10132
|
if (checkbox && this.options.selectable === "multi") {
|
|
9842
10133
|
this._toggleMultiSelection(
|
|
@@ -9932,7 +10223,15 @@ var Table = class extends Component {
|
|
|
9932
10223
|
return entry;
|
|
9933
10224
|
}
|
|
9934
10225
|
if (type === "number") {
|
|
9935
|
-
const
|
|
10226
|
+
const locale = resolveColumnOption(column.locale, row);
|
|
10227
|
+
const decimals = resolveColumnDecimals(column, row);
|
|
10228
|
+
const suffix = column.type === "currency" ? resolveColumnOption(column.currency, row) : column.type === "unit" ? resolveColumnOption(column.unit, row) : null;
|
|
10229
|
+
const inferred = {
|
|
10230
|
+
...locale != null && !Object.prototype.hasOwnProperty.call(props, "locale") ? { locale } : {},
|
|
10231
|
+
...decimals != null && !Object.prototype.hasOwnProperty.call(props, "precision") ? { precision: decimals } : {},
|
|
10232
|
+
...suffix != null && !Object.prototype.hasOwnProperty.call(props, "unit") ? { unit: String(suffix) } : {}
|
|
10233
|
+
};
|
|
10234
|
+
const field = new NumberField(null, { ...inferred, ...props, value: value ?? null });
|
|
9936
10235
|
host.append(field.el);
|
|
9937
10236
|
entry.component = field;
|
|
9938
10237
|
entry.control = field.getInput();
|
|
@@ -10163,9 +10462,12 @@ var Table = class extends Component {
|
|
|
10163
10462
|
_nextEditableCell(rowIndex, columnId, direction) {
|
|
10164
10463
|
const columnCount = this._columns.length;
|
|
10165
10464
|
if (rowIndex < 0 || columnCount === 0) return null;
|
|
10166
|
-
|
|
10465
|
+
const visible = this._visibleData();
|
|
10466
|
+
const startingId = this._idFor(this._data[rowIndex]);
|
|
10467
|
+
let row = visible.findIndex((candidate) => Object.is(this._idFor(candidate), startingId));
|
|
10468
|
+
if (row < 0) return null;
|
|
10167
10469
|
let column = this._columns.findIndex((candidate) => candidate.id === columnId);
|
|
10168
|
-
const limit =
|
|
10470
|
+
const limit = visible.length * columnCount + columnCount;
|
|
10169
10471
|
for (let step = 0; step < limit; step += 1) {
|
|
10170
10472
|
column += direction;
|
|
10171
10473
|
if (column >= columnCount) {
|
|
@@ -10175,11 +10477,15 @@ var Table = class extends Component {
|
|
|
10175
10477
|
row -= 1;
|
|
10176
10478
|
column = columnCount - 1;
|
|
10177
10479
|
}
|
|
10178
|
-
if (row < 0 || row >=
|
|
10179
|
-
const candidateRow =
|
|
10480
|
+
if (row < 0 || row >= visible.length) return null;
|
|
10481
|
+
const candidateRow = visible[row];
|
|
10180
10482
|
const candidateColumn = this._columns[column];
|
|
10181
10483
|
if (resolveEditable(candidateColumn, candidateRow) !== false) {
|
|
10182
|
-
return {
|
|
10484
|
+
return {
|
|
10485
|
+
id: this._idFor(candidateRow),
|
|
10486
|
+
columnId: candidateColumn.id,
|
|
10487
|
+
index: this._data.indexOf(candidateRow)
|
|
10488
|
+
};
|
|
10183
10489
|
}
|
|
10184
10490
|
}
|
|
10185
10491
|
return null;
|
|
@@ -10246,14 +10552,16 @@ var Table = class extends Component {
|
|
|
10246
10552
|
const message = this.msg(key);
|
|
10247
10553
|
return message === key ? fallback : message;
|
|
10248
10554
|
}
|
|
10249
|
-
/** @param {{row: TableRow, id: unknown, index: number}} meta @param {boolean} checked @param {boolean} shiftKey @returns {void} */
|
|
10555
|
+
/** @param {{row: TableRow, id: unknown, index: number, visibleIndex?: number}} meta @param {boolean} checked @param {boolean} shiftKey @returns {void} */
|
|
10250
10556
|
_toggleMultiSelection(meta, checked, shiftKey) {
|
|
10251
|
-
const
|
|
10557
|
+
const visible = this._visibleData();
|
|
10558
|
+
const anchorIndex = visible.findIndex((row) => Object.is(this._idFor(row), this._selectionAnchorId));
|
|
10252
10559
|
if (shiftKey && anchorIndex >= 0) {
|
|
10253
|
-
const
|
|
10254
|
-
const
|
|
10560
|
+
const currentIndex = meta.visibleIndex ?? visible.findIndex((row) => Object.is(this._idFor(row), meta.id));
|
|
10561
|
+
const start = Math.min(anchorIndex, currentIndex);
|
|
10562
|
+
const end = Math.max(anchorIndex, currentIndex);
|
|
10255
10563
|
for (let index = start; index <= end; index += 1) {
|
|
10256
|
-
const id = this._idFor(
|
|
10564
|
+
const id = this._idFor(visible[index]);
|
|
10257
10565
|
if (checked) this._selected.add(id);
|
|
10258
10566
|
else this._selected.delete(id);
|
|
10259
10567
|
}
|
|
@@ -10304,7 +10612,34 @@ var Table = class extends Component {
|
|
|
10304
10612
|
const column = this._columns.find((candidate) => candidate.id === this._sort.id);
|
|
10305
10613
|
if (!column) return;
|
|
10306
10614
|
const getValue = typeof column.sortValue === "function" ? column.sortValue : (row) => row?.[column.id];
|
|
10307
|
-
this._data = sortRows(this._data, getValue, this._sort.dir);
|
|
10615
|
+
this._data = this._hierarchy ? sortHierarchyRows(this._data, this.options.rowId, this._hierarchy.parentId, getValue, this._sort.dir) : sortRows(this._data, getValue, this._sort.dir);
|
|
10616
|
+
}
|
|
10617
|
+
/** @param {unknown} id @param {boolean} expanded @param {{silent?: boolean}} options @returns {this} */
|
|
10618
|
+
_setRowExpanded(id, expanded, options) {
|
|
10619
|
+
if (!this._hierarchy) return this;
|
|
10620
|
+
const branchIds = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
|
|
10621
|
+
if (!branchIds.some((candidate) => Object.is(candidate, id))) return this;
|
|
10622
|
+
if (this._expanded.has(id) === expanded) return this;
|
|
10623
|
+
if (expanded) this._expanded.add(id);
|
|
10624
|
+
else this._expanded.delete(id);
|
|
10625
|
+
this._renderBody();
|
|
10626
|
+
if (!options.silent) this._emitRowToggle(id, expanded);
|
|
10627
|
+
return this;
|
|
10628
|
+
}
|
|
10629
|
+
/** @param {unknown} id @param {boolean} expanded @returns {void} */
|
|
10630
|
+
_emitRowToggle(id, expanded) {
|
|
10631
|
+
const row = this.getRow(id);
|
|
10632
|
+
if (row) this.emit("rowtoggle", { row, id, expanded });
|
|
10633
|
+
}
|
|
10634
|
+
/** Keeps the reader's current expansion state limited to branches still present in the data. */
|
|
10635
|
+
_reconcileExpanded() {
|
|
10636
|
+
if (!this._hierarchy) {
|
|
10637
|
+
this._expanded.clear();
|
|
10638
|
+
return;
|
|
10639
|
+
}
|
|
10640
|
+
const branches = hierarchyBranchIds(this._data, this.options.rowId, this._hierarchy.parentId);
|
|
10641
|
+
const valid = new Set(branches);
|
|
10642
|
+
for (const id of this._expanded) if (!valid.has(id)) this._expanded.delete(id);
|
|
10308
10643
|
}
|
|
10309
10644
|
/** @returns {boolean} Whether selection changed. */
|
|
10310
10645
|
_pruneSelection() {
|
|
@@ -10328,6 +10663,65 @@ var Table = class extends Component {
|
|
|
10328
10663
|
this.emit("datachange", { rows: this.getData() });
|
|
10329
10664
|
}
|
|
10330
10665
|
};
|
|
10666
|
+
function formatTableCell(column, row, index = 0) {
|
|
10667
|
+
if (typeof column?.render === "function") return column.render(row, index);
|
|
10668
|
+
const value = row?.[column?.id];
|
|
10669
|
+
const type = column?.type ?? "text";
|
|
10670
|
+
if (type === "text") return value;
|
|
10671
|
+
const locale = resolveColumnOption(column.locale, row);
|
|
10672
|
+
const decimals = resolveColumnDecimals(column, row);
|
|
10673
|
+
const options = {
|
|
10674
|
+
...locale != null ? { locale: String(locale) } : {},
|
|
10675
|
+
...decimals != null ? { decimals } : {}
|
|
10676
|
+
};
|
|
10677
|
+
if (type === "number") return formatNumber(value, options);
|
|
10678
|
+
if (type === "currency") {
|
|
10679
|
+
const currency = resolveColumnOption(column.currency, row);
|
|
10680
|
+
return formatCurrency(value, currency == null ? null : String(currency), options);
|
|
10681
|
+
}
|
|
10682
|
+
if (type === "percent") return formatPercent2(value, options);
|
|
10683
|
+
if (type === "unit") {
|
|
10684
|
+
const number = formatNumber(value, options);
|
|
10685
|
+
const unit = resolveColumnOption(column.unit, row);
|
|
10686
|
+
return number && unit != null && String(unit) !== "" ? `${number}\xA0${unit}` : number;
|
|
10687
|
+
}
|
|
10688
|
+
return value;
|
|
10689
|
+
}
|
|
10690
|
+
function projectHierarchyRows(rows, rowId, parentId, expanded = []) {
|
|
10691
|
+
const forest = hierarchyForest(rows, rowId, parentId);
|
|
10692
|
+
const open = expanded instanceof Set ? expanded : new Set(expanded);
|
|
10693
|
+
const result = [];
|
|
10694
|
+
const stack = forest.roots.slice().reverse().map((node) => ({ node, depth: 0 }));
|
|
10695
|
+
while (stack.length) {
|
|
10696
|
+
const { node, depth } = stack.pop();
|
|
10697
|
+
result.push({
|
|
10698
|
+
row: node.row,
|
|
10699
|
+
id: node.id,
|
|
10700
|
+
index: node.index,
|
|
10701
|
+
depth,
|
|
10702
|
+
hasChildren: node.children.length > 0,
|
|
10703
|
+
parentId: node.parent?.id ?? null
|
|
10704
|
+
});
|
|
10705
|
+
if (!open.has(node.id)) continue;
|
|
10706
|
+
for (let index = node.children.length - 1; index >= 0; index -= 1) {
|
|
10707
|
+
stack.push({ node: node.children[index], depth: depth + 1 });
|
|
10708
|
+
}
|
|
10709
|
+
}
|
|
10710
|
+
return result;
|
|
10711
|
+
}
|
|
10712
|
+
function sortHierarchyRows(rows, rowId, parentId, getValue, direction) {
|
|
10713
|
+
const forest = hierarchyForest(rows, rowId, parentId);
|
|
10714
|
+
const sorted = (nodes) => sortRows(nodes, (node) => getValue(node.row), direction);
|
|
10715
|
+
const result = [];
|
|
10716
|
+
const stack = sorted(forest.roots).reverse();
|
|
10717
|
+
while (stack.length) {
|
|
10718
|
+
const node = stack.pop();
|
|
10719
|
+
result.push(node.row);
|
|
10720
|
+
const children = sorted(node.children);
|
|
10721
|
+
for (let index = children.length - 1; index >= 0; index -= 1) stack.push(children[index]);
|
|
10722
|
+
}
|
|
10723
|
+
return result;
|
|
10724
|
+
}
|
|
10331
10725
|
function resolveEditable(column, row) {
|
|
10332
10726
|
if (!column || typeof column !== "object") return false;
|
|
10333
10727
|
if (typeof column.editor === "function") {
|
|
@@ -10335,7 +10729,7 @@ function resolveEditable(column, row) {
|
|
|
10335
10729
|
return "custom";
|
|
10336
10730
|
}
|
|
10337
10731
|
const declared = typeof column.editable === "function" ? column.editable(row) : column.editable;
|
|
10338
|
-
if (declared === true) return "text";
|
|
10732
|
+
if (declared === true) return isNumericColumn(column) ? "number" : "text";
|
|
10339
10733
|
if (typeof declared === "string" && EDITOR_TYPES.has(declared)) return (
|
|
10340
10734
|
/** @type {TableEditorType} */
|
|
10341
10735
|
declared
|
|
@@ -10384,6 +10778,71 @@ function firstValidationError(values, columns, row, fallbackMessage = "Invalid v
|
|
|
10384
10778
|
}
|
|
10385
10779
|
return null;
|
|
10386
10780
|
}
|
|
10781
|
+
function resolveColumnOption(option, row) {
|
|
10782
|
+
return typeof option === "function" ? option(row) : option;
|
|
10783
|
+
}
|
|
10784
|
+
function resolveColumnDecimals(column, row) {
|
|
10785
|
+
const value = resolveColumnOption(column?.decimals, row);
|
|
10786
|
+
if (value == null) return null;
|
|
10787
|
+
const number = Number(value);
|
|
10788
|
+
return Number.isFinite(number) ? Math.max(0, Math.trunc(number)) : null;
|
|
10789
|
+
}
|
|
10790
|
+
function isNumericColumn(column) {
|
|
10791
|
+
return ["number", "currency", "percent", "unit"].includes(column?.type);
|
|
10792
|
+
}
|
|
10793
|
+
function hierarchyForest(rows, rowId, parentId) {
|
|
10794
|
+
const nodes = (Array.isArray(rows) ? rows : []).map((row, index) => ({
|
|
10795
|
+
row,
|
|
10796
|
+
id: readRowValue(rowId, row),
|
|
10797
|
+
index,
|
|
10798
|
+
parent: null,
|
|
10799
|
+
children: []
|
|
10800
|
+
}));
|
|
10801
|
+
const byId = /* @__PURE__ */ new Map();
|
|
10802
|
+
for (const node of nodes) if (!byId.has(node.id)) byId.set(node.id, node);
|
|
10803
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
10804
|
+
for (const node of nodes) {
|
|
10805
|
+
const parent = byId.get(readRowValue(parentId, node.row)) ?? null;
|
|
10806
|
+
parentOf.set(node, parent === node ? null : parent);
|
|
10807
|
+
}
|
|
10808
|
+
for (const node of nodes) {
|
|
10809
|
+
const seen = /* @__PURE__ */ new Set([node]);
|
|
10810
|
+
let cursor = parentOf.get(node) ?? null;
|
|
10811
|
+
while (cursor) {
|
|
10812
|
+
if (seen.has(cursor)) {
|
|
10813
|
+
parentOf.set(cursor, null);
|
|
10814
|
+
break;
|
|
10815
|
+
}
|
|
10816
|
+
seen.add(cursor);
|
|
10817
|
+
cursor = parentOf.get(cursor) ?? null;
|
|
10818
|
+
}
|
|
10819
|
+
}
|
|
10820
|
+
const roots = [];
|
|
10821
|
+
for (const node of nodes) {
|
|
10822
|
+
node.parent = parentOf.get(node) ?? null;
|
|
10823
|
+
if (node.parent) node.parent.children.push(node);
|
|
10824
|
+
else roots.push(node);
|
|
10825
|
+
}
|
|
10826
|
+
return { roots, nodes };
|
|
10827
|
+
}
|
|
10828
|
+
function hierarchyBranchIds(rows, rowId, parentId) {
|
|
10829
|
+
return hierarchyForest(rows, rowId, parentId).nodes.filter((node) => node.children.length > 0).map((node) => node.id);
|
|
10830
|
+
}
|
|
10831
|
+
function readRowValue(accessor, row) {
|
|
10832
|
+
return typeof accessor === "function" ? accessor(row) : row?.[accessor];
|
|
10833
|
+
}
|
|
10834
|
+
function normalizeHierarchy(option, columns) {
|
|
10835
|
+
if (!option || typeof option !== "object") return null;
|
|
10836
|
+
const parentId = option.parentId;
|
|
10837
|
+
if (typeof parentId !== "string" && typeof parentId !== "function") return null;
|
|
10838
|
+
const requested = typeof option.column === "string" ? option.column : null;
|
|
10839
|
+
const column = columns.some((candidate) => candidate.id === requested) ? requested : columns[0]?.id;
|
|
10840
|
+
if (!column) return null;
|
|
10841
|
+
return { ...option, parentId, column };
|
|
10842
|
+
}
|
|
10843
|
+
function initialExpanded(option) {
|
|
10844
|
+
return new Set(Array.isArray(option) ? option : []);
|
|
10845
|
+
}
|
|
10387
10846
|
function normalizeEditMode(mode) {
|
|
10388
10847
|
if (mode === "cell" || mode === "row") return mode;
|
|
10389
10848
|
return mode === true ? "cell" : false;
|
|
@@ -11951,7 +12410,7 @@ function buildZeyosTableConfig(client, resource, opts = {}) {
|
|
|
11951
12410
|
const monetary = isMonetaryField(meta);
|
|
11952
12411
|
const column = fieldToZxColumn(monetary ? { ...meta, format: "money" } : meta);
|
|
11953
12412
|
if (monetary) {
|
|
11954
|
-
column.render = (row) =>
|
|
12413
|
+
column.render = (row) => formatCurrency2(row?.[meta.id], row?.currency);
|
|
11955
12414
|
if (schemaHasField(client, resource, "currency")) projection.currency = "currency";
|
|
11956
12415
|
}
|
|
11957
12416
|
return column;
|
|
@@ -12076,10 +12535,10 @@ function inferLabelKey2(client, resource) {
|
|
|
12076
12535
|
return names[0] ?? "ID";
|
|
12077
12536
|
}
|
|
12078
12537
|
function isMonetaryField(meta) {
|
|
12079
|
-
const
|
|
12080
|
-
return /money|currency|price/.test(
|
|
12538
|
+
const format2 = String(meta.format ?? "").toLowerCase();
|
|
12539
|
+
return /money|currency|price/.test(format2) || /(?:amount|price)$/.test(String(meta.id).toLowerCase());
|
|
12081
12540
|
}
|
|
12082
|
-
function
|
|
12541
|
+
function formatCurrency2(value, currency) {
|
|
12083
12542
|
if (value == null || value === "") return "";
|
|
12084
12543
|
const number = Number(value);
|
|
12085
12544
|
if (!Number.isFinite(number)) return "";
|