@zeyos/zx 4.0.0 → 4.1.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 +44 -0
- package/DESIGN-SYSTEM.md +59 -3
- package/dist/types/components/app-icon/app-icon.d.ts +88 -0
- package/dist/types/components/filter/filter-model.d.ts +87 -0
- package/dist/types/components/filter/filter.d.ts +331 -0
- package/dist/types/components/select/select.d.ts +46 -4
- package/dist/types/components/table/table.d.ts +103 -0
- package/dist/types/components/tag-picker/tag-picker.d.ts +16 -0
- package/dist/types/core/dom.d.ts +1 -1
- package/dist/types/core/util.d.ts +9 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/zeyos/icons.d.ts +19 -2
- package/dist/types/zeyos/index.d.ts +1 -1
- package/dist/types/zeyos/select.d.ts +2 -0
- package/dist/zx-zeyos.esm.js +702 -75
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +415 -4
- package/dist/zx.esm.js +1568 -115
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +1568 -115
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +379 -0
- package/docs/llms.md +93 -16
- package/docs/llms.txt +11 -9
- package/package.json +1 -1
- package/src/components/app-icon/app-icon.css +105 -0
- package/src/components/app-icon/app-icon.js +134 -0
- package/src/components/filter/filter-model.js +226 -0
- package/src/components/filter/filter.css +147 -0
- package/src/components/filter/filter.js +554 -0
- package/src/components/grid/grid.css +1 -1
- package/src/components/grid/grid.js +4 -1
- package/src/components/message/message.css +36 -3
- package/src/components/select/select.css +17 -0
- package/src/components/select/select.js +105 -24
- package/src/components/table/table.css +85 -0
- package/src/components/table/table.js +418 -24
- package/src/components/tag-picker/tag-picker.css +19 -0
- package/src/components/tag-picker/tag-picker.js +42 -5
- package/src/core/dom.js +1 -1
- package/src/core/util.js +20 -0
- package/src/index.js +7 -1
- package/src/zeyos/icons.js +34 -21
- package/src/zeyos/index.js +1 -1
- package/src/zeyos/select.js +6 -5
- package/styles/tokens/semantic.css +9 -0
- package/styles/tokens/themes.css +2 -2
- package/styles/zx.css +2 -0
package/dist/zx-zeyos.esm.js
CHANGED
|
@@ -500,6 +500,20 @@ function isElement(value) {
|
|
|
500
500
|
return Boolean(value && typeof value === "object" && /** @type {{nodeType?: unknown}} */
|
|
501
501
|
value.nodeType === 1);
|
|
502
502
|
}
|
|
503
|
+
function isCssColor(value) {
|
|
504
|
+
if (typeof value !== "string") return false;
|
|
505
|
+
const text3 = value.trim();
|
|
506
|
+
if (!text3 || text3.length > 256 || /[;{}\u0000-\u001f\u007f]/.test(text3) || /(?:url|image|image-set|cross-fade|element|var)\s*\(/i.test(text3)) return false;
|
|
507
|
+
const supports = globalThis.CSS?.supports;
|
|
508
|
+
if (typeof supports === "function") {
|
|
509
|
+
try {
|
|
510
|
+
return supports.call(globalThis.CSS, "color", text3);
|
|
511
|
+
} catch {
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return /^(?:#[\da-f]{3,8}|[a-z]+|(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix)\([^;{}]+\))$/i.test(text3);
|
|
516
|
+
}
|
|
503
517
|
function clamp(n, min, max) {
|
|
504
518
|
return Math.min(max, Math.max(min, n));
|
|
505
519
|
}
|
|
@@ -6563,6 +6577,7 @@ var Select = class _Select extends Component {
|
|
|
6563
6577
|
static defaults = {
|
|
6564
6578
|
items: [],
|
|
6565
6579
|
fixedItems: [],
|
|
6580
|
+
fixedLabel: null,
|
|
6566
6581
|
valueKey: "ID",
|
|
6567
6582
|
labelKey: "name",
|
|
6568
6583
|
renderItem: null,
|
|
@@ -6600,8 +6615,7 @@ var Select = class _Select extends Component {
|
|
|
6600
6615
|
this._position = null;
|
|
6601
6616
|
this._createdRoot = false;
|
|
6602
6617
|
this._root = null;
|
|
6603
|
-
this.
|
|
6604
|
-
this._originalAttributes = /* @__PURE__ */ new Map();
|
|
6618
|
+
this._snapshot = null;
|
|
6605
6619
|
this._createdRoot = this.el === null;
|
|
6606
6620
|
const root = (
|
|
6607
6621
|
/** @type {HTMLElement} */
|
|
@@ -6609,10 +6623,7 @@ var Select = class _Select extends Component {
|
|
|
6609
6623
|
);
|
|
6610
6624
|
this.el = root;
|
|
6611
6625
|
this._root = root;
|
|
6612
|
-
|
|
6613
|
-
this._rememberAttribute(root, "data-state");
|
|
6614
|
-
this._rememberAttribute(root, "data-loading");
|
|
6615
|
-
this._rememberAttribute(root, "aria-disabled");
|
|
6626
|
+
this._snapshot = this._createdRoot ? null : snapshotTarget(root);
|
|
6616
6627
|
const listId = uid("zx-select-list");
|
|
6617
6628
|
const input = h("input", {
|
|
6618
6629
|
ref: "input",
|
|
@@ -6915,6 +6926,66 @@ var Select = class _Select extends Component {
|
|
|
6915
6926
|
select.set(value, { silent: true });
|
|
6916
6927
|
return select;
|
|
6917
6928
|
}
|
|
6929
|
+
/**
|
|
6930
|
+
* Creates a rich entity picker with optional Recent choices and a create command.
|
|
6931
|
+
* @param {Element|string|null} target Component target.
|
|
6932
|
+
* @param {SelectOptions & EntitySelectOptions} [options={}] Entity-preset options.
|
|
6933
|
+
* @returns {Select}
|
|
6934
|
+
*/
|
|
6935
|
+
static entity(target, options = {}) {
|
|
6936
|
+
const {
|
|
6937
|
+
recent = [],
|
|
6938
|
+
recentLabel = "Recent",
|
|
6939
|
+
create = false,
|
|
6940
|
+
iconKey = "icon",
|
|
6941
|
+
colorKey = "color",
|
|
6942
|
+
subtitleKey = "description",
|
|
6943
|
+
renderIcon = null,
|
|
6944
|
+
fixedItems = [],
|
|
6945
|
+
actions = [],
|
|
6946
|
+
renderItem = null,
|
|
6947
|
+
renderValueAdornment = null,
|
|
6948
|
+
...rest
|
|
6949
|
+
} = options;
|
|
6950
|
+
const visual = (item, selected = false) => {
|
|
6951
|
+
if (typeof renderIcon === "function") return renderIcon(item, { selected });
|
|
6952
|
+
const value = readSelectItem(item, iconKey);
|
|
6953
|
+
if (value && typeof value === "object" && typeof value.nodeType === "number") return value.cloneNode(true);
|
|
6954
|
+
if (typeof value !== "string" || !value) return null;
|
|
6955
|
+
const color = readSelectItem(item, colorKey);
|
|
6956
|
+
return h("span", {
|
|
6957
|
+
class: "zx-select__entity-glyph",
|
|
6958
|
+
style: isCssColor(color) ? { "--zx-select-entity-color": String(color) } : null,
|
|
6959
|
+
ariaHidden: "true"
|
|
6960
|
+
}, icon(value, { size: 14 }));
|
|
6961
|
+
};
|
|
6962
|
+
const createAction = create ? normalizeEntityCreateAction(create) : null;
|
|
6963
|
+
const select = new _Select(target, {
|
|
6964
|
+
...rest,
|
|
6965
|
+
fixedItems: [...Array.isArray(recent) ? recent : [], ...Array.isArray(fixedItems) ? fixedItems : []],
|
|
6966
|
+
fixedLabel: Array.isArray(recent) && recent.length ? recentLabel : rest.fixedLabel ?? null,
|
|
6967
|
+
actions: [...Array.isArray(actions) ? actions : [], ...createAction ? [createAction] : []],
|
|
6968
|
+
renderItem: renderItem ?? ((item) => {
|
|
6969
|
+
const decoration = visual(item, false);
|
|
6970
|
+
const subtitle = readSelectItem(item, subtitleKey);
|
|
6971
|
+
const copy = h(
|
|
6972
|
+
"span",
|
|
6973
|
+
{ class: "zx-select__entity-copy" },
|
|
6974
|
+
h("span", { class: "zx-select__entity-label" }, String(readSelectItem(item, rest.labelKey ?? "name") ?? "")),
|
|
6975
|
+
subtitle == null || subtitle === "" ? null : h("span", { class: "zx-select__entity-subtitle" }, String(subtitle))
|
|
6976
|
+
);
|
|
6977
|
+
return h(
|
|
6978
|
+
"span",
|
|
6979
|
+
{ class: "zx-select__entity" },
|
|
6980
|
+
decoration ? h("span", { class: "zx-select__entity-icon", ariaHidden: "true" }, decoration) : null,
|
|
6981
|
+
copy
|
|
6982
|
+
);
|
|
6983
|
+
}),
|
|
6984
|
+
renderValueAdornment: renderValueAdornment ?? ((item) => visual(item, true))
|
|
6985
|
+
});
|
|
6986
|
+
select.el.dataset.preset = "entity";
|
|
6987
|
+
return select;
|
|
6988
|
+
}
|
|
6918
6989
|
/**
|
|
6919
6990
|
* Creates the record-permission picker: the fixed Private and Public choices above the groups a
|
|
6920
6991
|
* record can be shared with. The value is the tri-state ZeyOS stores — `false` for private,
|
|
@@ -6965,13 +7036,7 @@ var Select = class _Select extends Component {
|
|
|
6965
7036
|
/** @type {HTMLElement} */
|
|
6966
7037
|
this.el
|
|
6967
7038
|
);
|
|
6968
|
-
if (!this._createdRoot && root)
|
|
6969
|
-
root.replaceChildren(...this._originalChildren);
|
|
6970
|
-
for (const [name, value] of this._originalAttributes) {
|
|
6971
|
-
if (value === null) root.removeAttribute(name);
|
|
6972
|
-
else root.setAttribute(name, value);
|
|
6973
|
-
}
|
|
6974
|
-
}
|
|
7039
|
+
if (!this._createdRoot && root) restoreTarget(root, this._snapshot);
|
|
6975
7040
|
super.destroy();
|
|
6976
7041
|
}
|
|
6977
7042
|
/** @param {KeyboardEvent} event @returns {void} */
|
|
@@ -7108,14 +7173,19 @@ var Select = class _Select extends Component {
|
|
|
7108
7173
|
list.replaceChildren();
|
|
7109
7174
|
this._optionEntries = [];
|
|
7110
7175
|
let lastGroup = /* @__PURE__ */ Symbol("initial-group");
|
|
7176
|
+
const fixed = this._uniqueItems(this._visibleFixed);
|
|
7177
|
+
const items = this._uniqueItems(this._visibleItems, fixed);
|
|
7111
7178
|
if (this.options.clearable) {
|
|
7112
7179
|
this._appendOption(null, true, this.options.noneLabel ?? this._message("select.none", "No selection"));
|
|
7113
7180
|
}
|
|
7114
|
-
|
|
7115
|
-
|
|
7181
|
+
if (fixed.length > 0 && this.options.fixedLabel) {
|
|
7182
|
+
list.append(h("div", { class: "zx-select__group", role: "presentation" }, String(this.options.fixedLabel)));
|
|
7183
|
+
}
|
|
7184
|
+
for (const item of fixed) this._appendOption(item, false);
|
|
7185
|
+
if (fixed.length > 0 && items.length > 0 && !this.options.groupKey) {
|
|
7116
7186
|
list.append(h("div", { class: "zx-select__separator", role: "presentation" }));
|
|
7117
7187
|
}
|
|
7118
|
-
for (const item of
|
|
7188
|
+
for (const item of items) {
|
|
7119
7189
|
if (this.options.groupKey) {
|
|
7120
7190
|
const group = this._read(item, this.options.groupKey);
|
|
7121
7191
|
if (!Object.is(group, lastGroup)) {
|
|
@@ -7129,7 +7199,7 @@ var Select = class _Select extends Component {
|
|
|
7129
7199
|
this._appendOption(item, false);
|
|
7130
7200
|
}
|
|
7131
7201
|
if (this._actions.length > 0) {
|
|
7132
|
-
if (
|
|
7202
|
+
if (fixed.length > 0 || items.length > 0 || this.options.clearable) {
|
|
7133
7203
|
list.append(h("div", { class: "zx-select__separator", role: "presentation" }));
|
|
7134
7204
|
}
|
|
7135
7205
|
let actionGroup = /* @__PURE__ */ Symbol("initial-action-group");
|
|
@@ -7144,7 +7214,7 @@ var Select = class _Select extends Component {
|
|
|
7144
7214
|
this._appendAction(action);
|
|
7145
7215
|
}
|
|
7146
7216
|
}
|
|
7147
|
-
if (
|
|
7217
|
+
if (items.length === 0 && fixed.length === 0 && this._actions.length === 0 && !this._loading) {
|
|
7148
7218
|
list.append(h("div", {
|
|
7149
7219
|
class: "zx-select__empty",
|
|
7150
7220
|
role: "status"
|
|
@@ -7345,6 +7415,16 @@ var Select = class _Select extends Component {
|
|
|
7345
7415
|
_matchFixed(query) {
|
|
7346
7416
|
return matchItems(this._fixedItems, query, this._searchKeys());
|
|
7347
7417
|
}
|
|
7418
|
+
/** De-duplicates choices by public value while preserving caller order. @param {SelectItem[]} items @param {SelectItem[]} [excluded=[]] @returns {SelectItem[]} */
|
|
7419
|
+
_uniqueItems(items, excluded = []) {
|
|
7420
|
+
const values = excluded.map((item) => this._itemValue(item));
|
|
7421
|
+
return items.filter((item) => {
|
|
7422
|
+
const value = this._itemValue(item);
|
|
7423
|
+
if (values.some((candidate) => Object.is(candidate, value))) return false;
|
|
7424
|
+
values.push(value);
|
|
7425
|
+
return true;
|
|
7426
|
+
});
|
|
7427
|
+
}
|
|
7348
7428
|
/** @returns {number} */
|
|
7349
7429
|
_selectedEntryIndex() {
|
|
7350
7430
|
if (this._selected === null) return this.options.clearable ? 0 : -1;
|
|
@@ -7356,16 +7436,28 @@ var Select = class _Select extends Component {
|
|
|
7356
7436
|
_itemEntryIndex(itemIndex) {
|
|
7357
7437
|
return itemIndex + (this.options.clearable ? 1 : 0);
|
|
7358
7438
|
}
|
|
7359
|
-
/** @param {string} name @returns {void} */
|
|
7360
|
-
_rememberAttribute(element, name) {
|
|
7361
|
-
this._originalAttributes.set(name, element.getAttribute(name));
|
|
7362
|
-
}
|
|
7363
7439
|
/** @param {string} key @param {string} fallback @returns {string} */
|
|
7364
7440
|
_message(key, fallback) {
|
|
7365
7441
|
const message = this.msg(key);
|
|
7366
7442
|
return message === key ? fallback : message;
|
|
7367
7443
|
}
|
|
7368
7444
|
};
|
|
7445
|
+
function readSelectItem(item, reader) {
|
|
7446
|
+
if (typeof reader === "function") return reader(item);
|
|
7447
|
+
if (item !== null && typeof item === "object" && typeof reader === "string") return item[reader];
|
|
7448
|
+
return null;
|
|
7449
|
+
}
|
|
7450
|
+
function normalizeEntityCreateAction(value) {
|
|
7451
|
+
const descriptor = value === true ? {} : value;
|
|
7452
|
+
return {
|
|
7453
|
+
id: descriptor.id ?? "create",
|
|
7454
|
+
label: descriptor.label ?? "Create new\u2026",
|
|
7455
|
+
description: descriptor.description,
|
|
7456
|
+
group: descriptor.group ?? "New",
|
|
7457
|
+
icon: descriptor.icon ?? "plus",
|
|
7458
|
+
invoke: descriptor.invoke
|
|
7459
|
+
};
|
|
7460
|
+
}
|
|
7369
7461
|
function normalizeRenderedContent(rendered) {
|
|
7370
7462
|
return rendered && typeof rendered === "object" && "nodeType" in rendered ? (
|
|
7371
7463
|
/** @type {Node} */
|
|
@@ -7842,6 +7934,8 @@ var TagPicker = class extends Component {
|
|
|
7842
7934
|
values: [],
|
|
7843
7935
|
valueKey: "ID",
|
|
7844
7936
|
labelKey: "name",
|
|
7937
|
+
iconKey: "icon",
|
|
7938
|
+
colorKey: "color",
|
|
7845
7939
|
searchKeys: null,
|
|
7846
7940
|
filter: "local",
|
|
7847
7941
|
minQuery: 0,
|
|
@@ -8182,12 +8276,13 @@ var TagPicker = class extends Component {
|
|
|
8182
8276
|
_renderTags() {
|
|
8183
8277
|
const tags = this._selected.map((item) => {
|
|
8184
8278
|
const label = this._labelOf(item);
|
|
8185
|
-
const
|
|
8186
|
-
const
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8279
|
+
const color = this._colorOf(item);
|
|
8280
|
+
const content = this.options.renderTag ? this.options.renderTag(item) : [this._iconOf(item), h("span", { class: "zx-tag-picker__tag-label" }, label)];
|
|
8281
|
+
const tag = h("span", {
|
|
8282
|
+
class: "zx-tag-picker__tag",
|
|
8283
|
+
dataset: { colored: String(Boolean(color)) },
|
|
8284
|
+
style: color ? { "--zx-tag-color": color } : null
|
|
8285
|
+
}, content);
|
|
8191
8286
|
if (!this._readonly && !this._disabled) {
|
|
8192
8287
|
tag.append(h("button", {
|
|
8193
8288
|
class: "zx-icon-btn zx-tag-picker__remove",
|
|
@@ -8225,7 +8320,7 @@ var TagPicker = class extends Component {
|
|
|
8225
8320
|
h(
|
|
8226
8321
|
"span",
|
|
8227
8322
|
{ class: "zx-tag-picker__option-label" },
|
|
8228
|
-
this.options.renderItem ? this.options.renderItem(item) : this._labelOf(item)
|
|
8323
|
+
this.options.renderItem ? this.options.renderItem(item) : [this._iconOf(item), h("span", {}, this._labelOf(item))]
|
|
8229
8324
|
)
|
|
8230
8325
|
);
|
|
8231
8326
|
if (!selected && this.isFull()) option.setAttribute("aria-disabled", "true");
|
|
@@ -8546,6 +8641,34 @@ var TagPicker = class extends Component {
|
|
|
8546
8641
|
if (item !== null && typeof item === "object") return String(item[key] ?? "");
|
|
8547
8642
|
return String(item ?? "");
|
|
8548
8643
|
}
|
|
8644
|
+
/** @param {unknown} item @returns {Node|null} */
|
|
8645
|
+
_iconOf(item) {
|
|
8646
|
+
const value = this._readItem(item, this.options.iconKey);
|
|
8647
|
+
const visual = value && typeof value === "object" && typeof value.nodeType === "number" ? (
|
|
8648
|
+
/** @type {Node} */
|
|
8649
|
+
value.cloneNode(true)
|
|
8650
|
+
) : typeof value === "string" && value.trim() ? icon(value, { size: 12 }) : null;
|
|
8651
|
+
if (!visual) return null;
|
|
8652
|
+
return h("span", {
|
|
8653
|
+
class: "zx-tag-picker__visual",
|
|
8654
|
+
style: this._colorOf(item) ? { "--zx-tag-color": this._colorOf(item) } : null,
|
|
8655
|
+
ariaHidden: "true"
|
|
8656
|
+
}, visual);
|
|
8657
|
+
}
|
|
8658
|
+
/** @param {unknown} item @returns {string|null} */
|
|
8659
|
+
_colorOf(item) {
|
|
8660
|
+
const value = this._readItem(item, this.options.colorKey);
|
|
8661
|
+
return isCssColor(value) ? value : null;
|
|
8662
|
+
}
|
|
8663
|
+
/** @param {unknown} item @param {unknown} reader @returns {unknown} */
|
|
8664
|
+
_readItem(item, reader) {
|
|
8665
|
+
if (typeof reader === "function") return reader(
|
|
8666
|
+
/** @type {TagItem} */
|
|
8667
|
+
item
|
|
8668
|
+
);
|
|
8669
|
+
if (item !== null && typeof item === "object" && typeof reader === "string") return item[reader];
|
|
8670
|
+
return null;
|
|
8671
|
+
}
|
|
8549
8672
|
/** @returns {void} */
|
|
8550
8673
|
_emitChange() {
|
|
8551
8674
|
this.emit("change", { values: this.getValues(), items: this.getItems() });
|
|
@@ -9496,7 +9619,11 @@ var Table = class extends Component {
|
|
|
9496
9619
|
rowClass: null,
|
|
9497
9620
|
zebra: true,
|
|
9498
9621
|
editMode: false,
|
|
9499
|
-
|
|
9622
|
+
editTrigger: "double",
|
|
9623
|
+
hierarchy: false,
|
|
9624
|
+
rowReorder: false,
|
|
9625
|
+
columnVisibility: false,
|
|
9626
|
+
hiddenColumns: []
|
|
9500
9627
|
};
|
|
9501
9628
|
/**
|
|
9502
9629
|
* Creates a table around a target or creates a new root when target is null.
|
|
@@ -9525,6 +9652,7 @@ var Table = class extends Component {
|
|
|
9525
9652
|
this._rowElements = /* @__PURE__ */ new Map();
|
|
9526
9653
|
this._restored = false;
|
|
9527
9654
|
this._editMode = normalizeEditMode(this.options.editMode);
|
|
9655
|
+
this._editTrigger = this.options.editTrigger === "single" ? "single" : "double";
|
|
9528
9656
|
this._edit = null;
|
|
9529
9657
|
this._editMessage = null;
|
|
9530
9658
|
this._stacked = false;
|
|
@@ -9536,6 +9664,10 @@ var Table = class extends Component {
|
|
|
9536
9664
|
this._rovingCell = null;
|
|
9537
9665
|
this._rovingMatched = false;
|
|
9538
9666
|
this._hierarchy = normalizeHierarchy(this.options.hierarchy, this._columns);
|
|
9667
|
+
this._hiddenColumns = new Set((Array.isArray(this.options.hiddenColumns) ? this.options.hiddenColumns : []).map(String).filter((id) => this._columns.some((column) => column.id === id)));
|
|
9668
|
+
if (this._hiddenColumns.size >= this._columns.length && this._columns[0]) this._hiddenColumns.delete(this._columns[0].id);
|
|
9669
|
+
this._dragId = null;
|
|
9670
|
+
this._grabbedId = null;
|
|
9539
9671
|
this._expanded = initialExpanded(this._hierarchy?.expanded);
|
|
9540
9672
|
if (this._sort && this.options.sortMode === "local") this._sortData();
|
|
9541
9673
|
if (this._hierarchy?.expanded === true) {
|
|
@@ -9557,11 +9689,17 @@ var Table = class extends Component {
|
|
|
9557
9689
|
zebra: String(Boolean(this.options.zebra))
|
|
9558
9690
|
}
|
|
9559
9691
|
}, this._table);
|
|
9692
|
+
this._rowMoveMessage = this.options.rowReorder ? h("div", {
|
|
9693
|
+
class: "zx-table__reorder-status",
|
|
9694
|
+
role: "status",
|
|
9695
|
+
ariaLive: "polite"
|
|
9696
|
+
}) : null;
|
|
9560
9697
|
if (this.options.height != null) {
|
|
9561
9698
|
this._scroll.style.blockSize = typeof this.options.height === "number" ? `${this.options.height}px` : String(this.options.height);
|
|
9562
9699
|
}
|
|
9700
|
+
this._columnControls = this.options.columnVisibility ? this._createColumnControls() : null;
|
|
9563
9701
|
if (this._editMode === false) {
|
|
9564
|
-
root.replaceChildren(this._scroll);
|
|
9702
|
+
root.replaceChildren(...[this._columnControls, this._scroll, this._rowMoveMessage].filter(Boolean));
|
|
9565
9703
|
} else {
|
|
9566
9704
|
root.dataset.editMode = this._editMode;
|
|
9567
9705
|
this._editMessage = h("div", {
|
|
@@ -9570,7 +9708,7 @@ var Table = class extends Component {
|
|
|
9570
9708
|
role: "status",
|
|
9571
9709
|
ariaLive: "polite"
|
|
9572
9710
|
});
|
|
9573
|
-
root.replaceChildren(this._scroll, this._editMessage);
|
|
9711
|
+
root.replaceChildren(...[this._columnControls, this._scroll, this._editMessage, this._rowMoveMessage].filter(Boolean));
|
|
9574
9712
|
}
|
|
9575
9713
|
this._renderColumns();
|
|
9576
9714
|
this._renderHeader();
|
|
@@ -9578,6 +9716,34 @@ var Table = class extends Component {
|
|
|
9578
9716
|
this._watchWidth();
|
|
9579
9717
|
this.listen(this._tbody, "click", (event) => this._handleBodyClick(event));
|
|
9580
9718
|
this.listen(this._tbody, "dblclick", (event) => this._handleBodyDoubleClick(event));
|
|
9719
|
+
if (this.options.rowReorder) {
|
|
9720
|
+
this.listen(this._tbody, "dragstart", (event) => this._handleRowDragStart(
|
|
9721
|
+
/** @type {DragEvent} */
|
|
9722
|
+
event
|
|
9723
|
+
));
|
|
9724
|
+
this.listen(this._tbody, "dragover", (event) => this._handleRowDragOver(
|
|
9725
|
+
/** @type {DragEvent} */
|
|
9726
|
+
event
|
|
9727
|
+
));
|
|
9728
|
+
this.listen(this._tbody, "drop", (event) => this._handleRowDrop(
|
|
9729
|
+
/** @type {DragEvent} */
|
|
9730
|
+
event
|
|
9731
|
+
));
|
|
9732
|
+
this.listen(this._tbody, "dragend", () => this._clearRowDrag());
|
|
9733
|
+
this.listen(this._tbody, "keydown", (event) => this._handleRowHandleKeydown(
|
|
9734
|
+
/** @type {KeyboardEvent} */
|
|
9735
|
+
event
|
|
9736
|
+
));
|
|
9737
|
+
}
|
|
9738
|
+
if (this._columnControls) {
|
|
9739
|
+
this.listen(this._columnControls, "change", (event) => {
|
|
9740
|
+
const input = (
|
|
9741
|
+
/** @type {HTMLInputElement|null} */
|
|
9742
|
+
event.target
|
|
9743
|
+
);
|
|
9744
|
+
if (input?.classList.contains("zx-table__column-toggle")) this.setColumnVisible(input.value, input.checked);
|
|
9745
|
+
});
|
|
9746
|
+
}
|
|
9581
9747
|
if (this._editMode !== false) {
|
|
9582
9748
|
this.listen(this._tbody, "keydown", (event) => this._handleEditKeydown(
|
|
9583
9749
|
/** @type {KeyboardEvent} */
|
|
@@ -9693,6 +9859,81 @@ var Table = class extends Component {
|
|
|
9693
9859
|
getData() {
|
|
9694
9860
|
return [...this._data];
|
|
9695
9861
|
}
|
|
9862
|
+
/** Returns visible column IDs in caller order. @returns {string[]} */
|
|
9863
|
+
getVisibleColumns() {
|
|
9864
|
+
return this._visibleColumns().map((column) => column.id);
|
|
9865
|
+
}
|
|
9866
|
+
/** Returns hidden column IDs in caller order. @returns {string[]} */
|
|
9867
|
+
getHiddenColumns() {
|
|
9868
|
+
return this._columns.filter((column) => this._hiddenColumns.has(column.id)).map((column) => column.id);
|
|
9869
|
+
}
|
|
9870
|
+
/**
|
|
9871
|
+
* Shows or hides one column. The final visible column cannot be hidden.
|
|
9872
|
+
* @param {string} id Column ID.
|
|
9873
|
+
* @param {boolean} [visible=true] Desired visibility.
|
|
9874
|
+
* @param {{silent?:boolean}} [options={}] Event behavior.
|
|
9875
|
+
* @returns {this}
|
|
9876
|
+
*/
|
|
9877
|
+
setColumnVisible(id, visible = true, options = {}) {
|
|
9878
|
+
const column = this._columns.find((candidate) => candidate.id === id);
|
|
9879
|
+
if (!column) throw new RangeError(`Unknown table column: ${id}`);
|
|
9880
|
+
const active = (
|
|
9881
|
+
/** @type {HTMLElement|null} */
|
|
9882
|
+
document.activeElement
|
|
9883
|
+
);
|
|
9884
|
+
const restoreFocus = active?.classList.contains("zx-table__column-toggle") && this._columnList?.contains(active) ? (
|
|
9885
|
+
/** @type {HTMLInputElement} */
|
|
9886
|
+
active.value
|
|
9887
|
+
) : null;
|
|
9888
|
+
if (!visible && !this._hiddenColumns.has(id) && this._visibleColumns().length <= 1) {
|
|
9889
|
+
this._renderColumnControls(restoreFocus);
|
|
9890
|
+
return this;
|
|
9891
|
+
}
|
|
9892
|
+
const changed = visible ? this._hiddenColumns.delete(id) : !this._hiddenColumns.has(id);
|
|
9893
|
+
if (!visible && changed) this._hiddenColumns.add(id);
|
|
9894
|
+
if (!changed) return this;
|
|
9895
|
+
this._renderColumns();
|
|
9896
|
+
this._renderHeader();
|
|
9897
|
+
this._renderBody();
|
|
9898
|
+
this._renderColumnControls(restoreFocus);
|
|
9899
|
+
if (!options.silent) this.emit("columnvisibilitychange", {
|
|
9900
|
+
visible: this.getVisibleColumns(),
|
|
9901
|
+
hidden: this.getHiddenColumns()
|
|
9902
|
+
});
|
|
9903
|
+
return this;
|
|
9904
|
+
}
|
|
9905
|
+
/** Toggles one column. @param {string} id @param {{silent?:boolean}} [options={}] @returns {this} */
|
|
9906
|
+
toggleColumn(id, options = {}) {
|
|
9907
|
+
return this.setColumnVisible(id, this._hiddenColumns.has(id), options);
|
|
9908
|
+
}
|
|
9909
|
+
/**
|
|
9910
|
+
* Reorders one row relative to another and emits a cancelable `rowmove` before committing.
|
|
9911
|
+
* Hierarchical rows may only move among siblings; an active local sort disables manual order.
|
|
9912
|
+
* @param {unknown} id Moving row ID.
|
|
9913
|
+
* @param {unknown} targetId Target row ID.
|
|
9914
|
+
* @param {'before'|'after'} [position='before'] Target edge.
|
|
9915
|
+
* @returns {this}
|
|
9916
|
+
*/
|
|
9917
|
+
moveRow(id, targetId, position2 = "before") {
|
|
9918
|
+
if (!this.options.rowReorder || this._sort && this.options.sortMode === "local") return this;
|
|
9919
|
+
const row = this.getRow(id);
|
|
9920
|
+
const target = this.getRow(targetId);
|
|
9921
|
+
if (!row || !target || Object.is(id, targetId)) return this;
|
|
9922
|
+
const next = reorderTableRows(this._data, this.options.rowId, id, targetId, position2, this._hierarchy?.parentId);
|
|
9923
|
+
if (!next) return this;
|
|
9924
|
+
const event = this.emit("rowmove", { row, id, target, targetId, position: position2 });
|
|
9925
|
+
if (event.defaultPrevented) return this;
|
|
9926
|
+
this._data = next;
|
|
9927
|
+
this._renderBody();
|
|
9928
|
+
if (this._rowMoveMessage) {
|
|
9929
|
+
const siblings = this._siblingIds(id);
|
|
9930
|
+
const index = siblings.findIndex((candidate) => Object.is(candidate, id));
|
|
9931
|
+
this._rowMoveMessage.textContent = `Moved row to position ${index + 1} of ${siblings.length}.`;
|
|
9932
|
+
}
|
|
9933
|
+
this._emitDataChange();
|
|
9934
|
+
queueMicrotask(() => this._rowHandle(id)?.focus());
|
|
9935
|
+
return this;
|
|
9936
|
+
}
|
|
9696
9937
|
/**
|
|
9697
9938
|
* Removes all rows.
|
|
9698
9939
|
* @returns {this}
|
|
@@ -9861,14 +10102,17 @@ var Table = class extends Component {
|
|
|
9861
10102
|
*/
|
|
9862
10103
|
startEdit(rowId, columnId) {
|
|
9863
10104
|
if (this._editMode === false) return this;
|
|
9864
|
-
const
|
|
9865
|
-
if (!
|
|
10105
|
+
const requested = this._columns.find((candidate) => candidate.id === columnId);
|
|
10106
|
+
if (!requested) return this;
|
|
9866
10107
|
const current = this._data.find((candidate) => Object.is(this._idFor(candidate), rowId));
|
|
9867
|
-
if (current === void 0
|
|
10108
|
+
if (current === void 0) return this;
|
|
10109
|
+
const column = this._editMode === "row" && this._hiddenColumns.has(requested.id) ? this._visibleColumns().find((candidate) => resolveEditable(candidate, current) !== false) ?? null : requested;
|
|
10110
|
+
if (!column || resolveEditable(column, current) === false) return this;
|
|
10111
|
+
const activeColumnId = column.id;
|
|
9868
10112
|
if (this._edit) {
|
|
9869
|
-
if (Object.is(this._edit.id, rowId) && this._edit.cells.has(
|
|
9870
|
-
this._edit.columnId =
|
|
9871
|
-
this._focusEditor(
|
|
10113
|
+
if (Object.is(this._edit.id, rowId) && this._edit.cells.has(activeColumnId)) {
|
|
10114
|
+
this._edit.columnId = activeColumnId;
|
|
10115
|
+
this._focusEditor(activeColumnId);
|
|
9872
10116
|
return this;
|
|
9873
10117
|
}
|
|
9874
10118
|
this.commitEdit();
|
|
@@ -9879,7 +10123,7 @@ var Table = class extends Component {
|
|
|
9879
10123
|
const row = this._data[index];
|
|
9880
10124
|
const tr = this._rowElements.get(rowId)?.[0];
|
|
9881
10125
|
if (!tr) return this;
|
|
9882
|
-
const targets = this._editMode === "row" ? this.
|
|
10126
|
+
const targets = this._editMode === "row" ? this._visibleColumns().filter((candidate) => resolveEditable(candidate, row) !== false) : [column];
|
|
9883
10127
|
const cells = /* @__PURE__ */ new Map();
|
|
9884
10128
|
for (const target of targets) {
|
|
9885
10129
|
const td = cellIn(tr, target.id);
|
|
@@ -9888,10 +10132,10 @@ var Table = class extends Component {
|
|
|
9888
10132
|
if (entry) cells.set(target.id, entry);
|
|
9889
10133
|
}
|
|
9890
10134
|
if (cells.size === 0) return this;
|
|
9891
|
-
this._edit = { id: rowId, columnId, row, cells, tr };
|
|
10135
|
+
this._edit = { id: rowId, columnId: activeColumnId, row, cells, tr };
|
|
9892
10136
|
tr.dataset.editing = "true";
|
|
9893
|
-
this.emit("editstart", { row, id: rowId, column, columnId, value: row?.[
|
|
9894
|
-
this._focusEditor(
|
|
10137
|
+
this.emit("editstart", { row, id: rowId, column, columnId: activeColumnId, value: row?.[activeColumnId] });
|
|
10138
|
+
this._focusEditor(activeColumnId);
|
|
9895
10139
|
return this;
|
|
9896
10140
|
}
|
|
9897
10141
|
/**
|
|
@@ -10146,16 +10390,197 @@ var Table = class extends Component {
|
|
|
10146
10390
|
}
|
|
10147
10391
|
super.destroy();
|
|
10148
10392
|
}
|
|
10393
|
+
/** @returns {TableColumn[]} */
|
|
10394
|
+
_visibleColumns() {
|
|
10395
|
+
return this._columns.filter((column) => !this._hiddenColumns.has(column.id));
|
|
10396
|
+
}
|
|
10397
|
+
/** @returns {HTMLElement} */
|
|
10398
|
+
_createColumnControls() {
|
|
10399
|
+
const list = h("div", { class: "zx-table__column-list" });
|
|
10400
|
+
this._columnList = list;
|
|
10401
|
+
const details = h(
|
|
10402
|
+
"details",
|
|
10403
|
+
{ class: "zx-table__column-controls" },
|
|
10404
|
+
h("summary", { class: "zx-button zx-button--sm" }, icon("fields", { size: 13 }), "Columns"),
|
|
10405
|
+
list
|
|
10406
|
+
);
|
|
10407
|
+
this._renderColumnControls();
|
|
10408
|
+
return details;
|
|
10409
|
+
}
|
|
10410
|
+
/** @param {string|null} [focusColumn=null] Column checkbox that keeps focus. @returns {void} */
|
|
10411
|
+
_renderColumnControls(focusColumn = null) {
|
|
10412
|
+
if (!this._columnList) return;
|
|
10413
|
+
const visible = this._visibleColumns();
|
|
10414
|
+
const current = [...this._columnList.querySelectorAll(".zx-table__column-toggle")];
|
|
10415
|
+
const reusable = current.length === this._columns.length && current.every((control, index) => (
|
|
10416
|
+
/** @type {HTMLInputElement} */
|
|
10417
|
+
control.value === this._columns[index].id
|
|
10418
|
+
));
|
|
10419
|
+
if (reusable) {
|
|
10420
|
+
current.forEach((control, index) => {
|
|
10421
|
+
const input = (
|
|
10422
|
+
/** @type {HTMLInputElement} */
|
|
10423
|
+
control
|
|
10424
|
+
);
|
|
10425
|
+
const checked = !this._hiddenColumns.has(this._columns[index].id);
|
|
10426
|
+
input.checked = checked;
|
|
10427
|
+
input.disabled = checked && visible.length === 1;
|
|
10428
|
+
});
|
|
10429
|
+
return;
|
|
10430
|
+
}
|
|
10431
|
+
this._columnList.replaceChildren(...this._columns.map((column) => {
|
|
10432
|
+
const checked = !this._hiddenColumns.has(column.id);
|
|
10433
|
+
return h(
|
|
10434
|
+
"label",
|
|
10435
|
+
{ class: "zx-table__column-option" },
|
|
10436
|
+
h("input", {
|
|
10437
|
+
class: "zx-table__column-toggle",
|
|
10438
|
+
type: "checkbox",
|
|
10439
|
+
value: column.id,
|
|
10440
|
+
checked,
|
|
10441
|
+
disabled: checked && visible.length === 1
|
|
10442
|
+
}),
|
|
10443
|
+
h("span", {}, column.label)
|
|
10444
|
+
);
|
|
10445
|
+
}));
|
|
10446
|
+
if (focusColumn !== null) {
|
|
10447
|
+
const control = [...this._columnList.querySelectorAll(".zx-table__column-toggle")].find((candidate) => (
|
|
10448
|
+
/** @type {HTMLInputElement} */
|
|
10449
|
+
candidate.value === focusColumn
|
|
10450
|
+
));
|
|
10451
|
+
queueMicrotask(() => {
|
|
10452
|
+
if (control?.isConnected) control.focus();
|
|
10453
|
+
});
|
|
10454
|
+
}
|
|
10455
|
+
}
|
|
10456
|
+
/** @param {DragEvent} event @returns {void} */
|
|
10457
|
+
_handleRowDragStart(event) {
|
|
10458
|
+
const handle = (
|
|
10459
|
+
/** @type {Element|null} */
|
|
10460
|
+
event.target?.closest?.(".zx-table__row-handle")
|
|
10461
|
+
);
|
|
10462
|
+
const rowElement = handle?.closest("tr[data-row]");
|
|
10463
|
+
const meta = rowElement ? this._rowMeta.get(rowElement) : null;
|
|
10464
|
+
if (!handle || !meta || this._sort && this.options.sortMode === "local") {
|
|
10465
|
+
event.preventDefault();
|
|
10466
|
+
return;
|
|
10467
|
+
}
|
|
10468
|
+
this._dragId = meta.id;
|
|
10469
|
+
rowElement.dataset.dragging = "true";
|
|
10470
|
+
event.dataTransfer?.setData("text/plain", "zx-table-row");
|
|
10471
|
+
if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
|
|
10472
|
+
}
|
|
10473
|
+
/** @param {DragEvent} event @returns {void} */
|
|
10474
|
+
_handleRowDragOver(event) {
|
|
10475
|
+
if (this._dragId == null) return;
|
|
10476
|
+
const rowElement = (
|
|
10477
|
+
/** @type {Element|null} */
|
|
10478
|
+
event.target?.closest?.("tr[data-row]")
|
|
10479
|
+
);
|
|
10480
|
+
const meta = rowElement ? this._rowMeta.get(rowElement) : null;
|
|
10481
|
+
if (!meta || Object.is(meta.id, this._dragId) || !this._canMoveTogether(this._dragId, meta.id)) return;
|
|
10482
|
+
event.preventDefault();
|
|
10483
|
+
if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
|
|
10484
|
+
this._clearDropMarkers();
|
|
10485
|
+
const rectangle = rowElement.getBoundingClientRect();
|
|
10486
|
+
rowElement.dataset.drop = event.clientY >= rectangle.top + rectangle.height / 2 ? "after" : "before";
|
|
10487
|
+
}
|
|
10488
|
+
/** @param {DragEvent} event @returns {void} */
|
|
10489
|
+
_handleRowDrop(event) {
|
|
10490
|
+
if (this._dragId == null) return;
|
|
10491
|
+
const rowElement = (
|
|
10492
|
+
/** @type {Element|null} */
|
|
10493
|
+
event.target?.closest?.("tr[data-row]")
|
|
10494
|
+
);
|
|
10495
|
+
const meta = rowElement ? this._rowMeta.get(rowElement) : null;
|
|
10496
|
+
const position2 = rowElement?.dataset.drop === "after" ? "after" : "before";
|
|
10497
|
+
if (meta && this._canMoveTogether(this._dragId, meta.id)) {
|
|
10498
|
+
event.preventDefault();
|
|
10499
|
+
this.moveRow(this._dragId, meta.id, position2);
|
|
10500
|
+
}
|
|
10501
|
+
this._clearRowDrag();
|
|
10502
|
+
}
|
|
10503
|
+
/** @param {KeyboardEvent} event @returns {void} */
|
|
10504
|
+
_handleRowHandleKeydown(event) {
|
|
10505
|
+
const handle = (
|
|
10506
|
+
/** @type {Element|null} */
|
|
10507
|
+
event.target?.closest?.(".zx-table__row-handle")
|
|
10508
|
+
);
|
|
10509
|
+
const rowElement = handle?.closest("tr[data-row]");
|
|
10510
|
+
const meta = rowElement ? this._rowMeta.get(rowElement) : null;
|
|
10511
|
+
if (!handle || !meta) return;
|
|
10512
|
+
if (event.key === " " || event.key === "Enter") {
|
|
10513
|
+
event.preventDefault();
|
|
10514
|
+
this._grabbedId = Object.is(this._grabbedId, meta.id) ? null : meta.id;
|
|
10515
|
+
handle.setAttribute("aria-pressed", String(this._grabbedId != null));
|
|
10516
|
+
const status = this._rowMoveMessage ?? this._editMessage;
|
|
10517
|
+
if (status) status.textContent = this._grabbedId == null ? "Row dropped" : "Row grabbed. Use the arrow keys to move it.";
|
|
10518
|
+
return;
|
|
10519
|
+
}
|
|
10520
|
+
if (event.key === "Escape" && this._grabbedId != null) {
|
|
10521
|
+
event.preventDefault();
|
|
10522
|
+
this._grabbedId = null;
|
|
10523
|
+
handle.setAttribute("aria-pressed", "false");
|
|
10524
|
+
return;
|
|
10525
|
+
}
|
|
10526
|
+
if (!Object.is(this._grabbedId, meta.id) || !["ArrowUp", "ArrowDown"].includes(event.key)) return;
|
|
10527
|
+
event.preventDefault();
|
|
10528
|
+
const siblings = this._siblingIds(meta.id);
|
|
10529
|
+
const index = siblings.findIndex((id) => Object.is(id, meta.id));
|
|
10530
|
+
const targetId = siblings[index + (event.key === "ArrowUp" ? -1 : 1)];
|
|
10531
|
+
if (targetId !== void 0) this.moveRow(meta.id, targetId, event.key === "ArrowUp" ? "before" : "after");
|
|
10532
|
+
}
|
|
10533
|
+
/** @param {unknown} id @returns {unknown[]} */
|
|
10534
|
+
_siblingIds(id) {
|
|
10535
|
+
const row = this.getRow(id);
|
|
10536
|
+
if (!row) return [];
|
|
10537
|
+
const parent = this._hierarchy ? readRowValue(this._hierarchy.parentId, row) : null;
|
|
10538
|
+
return this._data.filter((candidate) => !this._hierarchy || sameHierarchyParent(readRowValue(this._hierarchy.parentId, candidate), parent)).map((candidate) => this._idFor(candidate));
|
|
10539
|
+
}
|
|
10540
|
+
/** @param {unknown} left @param {unknown} right @returns {boolean} */
|
|
10541
|
+
_canMoveTogether(left, right) {
|
|
10542
|
+
if (!this._hierarchy) return true;
|
|
10543
|
+
const a = this.getRow(left);
|
|
10544
|
+
const b = this.getRow(right);
|
|
10545
|
+
return Boolean(a && b && sameHierarchyParent(
|
|
10546
|
+
readRowValue(this._hierarchy.parentId, a),
|
|
10547
|
+
readRowValue(this._hierarchy.parentId, b)
|
|
10548
|
+
));
|
|
10549
|
+
}
|
|
10550
|
+
/** @param {unknown} id @returns {HTMLElement|null} */
|
|
10551
|
+
_rowHandle(id) {
|
|
10552
|
+
return (
|
|
10553
|
+
/** @type {HTMLElement|null} */
|
|
10554
|
+
this._rowElements.get(id)?.[0]?.querySelector(".zx-table__row-handle") ?? null
|
|
10555
|
+
);
|
|
10556
|
+
}
|
|
10557
|
+
/** @returns {void} */
|
|
10558
|
+
_clearDropMarkers() {
|
|
10559
|
+
for (const row of this._tbody.querySelectorAll("tr[data-drop]")) delete row.dataset.drop;
|
|
10560
|
+
}
|
|
10561
|
+
/** @returns {void} */
|
|
10562
|
+
_clearRowDrag() {
|
|
10563
|
+
for (const row of this._tbody.querySelectorAll("tr[data-dragging]")) delete row.dataset.dragging;
|
|
10564
|
+
this._clearDropMarkers();
|
|
10565
|
+
this._dragId = null;
|
|
10566
|
+
}
|
|
10567
|
+
/** @returns {string|null} */
|
|
10568
|
+
_hierarchyColumn() {
|
|
10569
|
+
if (!this._hierarchy) return null;
|
|
10570
|
+
return this._visibleColumns().some((column) => column.id === this._hierarchy.column) ? this._hierarchy.column : this._visibleColumns()[0]?.id ?? null;
|
|
10571
|
+
}
|
|
10149
10572
|
/** @returns {void} */
|
|
10150
10573
|
_renderColumns() {
|
|
10151
10574
|
const fragment2 = document.createDocumentFragment();
|
|
10575
|
+
if (this.options.rowReorder) fragment2.append(h("col", { class: "zx-table__reorder-column" }));
|
|
10152
10576
|
if (this.options.selectable === "multi") {
|
|
10153
10577
|
fragment2.append(h("col", { class: "zx-table__selection-column" }));
|
|
10154
10578
|
}
|
|
10155
|
-
const
|
|
10579
|
+
const columns = this._visibleColumns();
|
|
10580
|
+
const fractions = columns.map((column) => parseFraction(column.width));
|
|
10156
10581
|
const total = fractions.reduce((sum, value) => sum + value, 0);
|
|
10157
10582
|
this._table.dataset.layout = total > 0 ? "fixed" : "auto";
|
|
10158
|
-
|
|
10583
|
+
columns.forEach((column, index) => {
|
|
10159
10584
|
const col = h("col");
|
|
10160
10585
|
if (fractions[index] > 0) col.style.width = `${fractions[index] / total * 100}%`;
|
|
10161
10586
|
else if (column.width && column.width !== "auto") col.style.width = String(column.width);
|
|
@@ -10167,6 +10592,11 @@ var Table = class extends Component {
|
|
|
10167
10592
|
_renderHeader() {
|
|
10168
10593
|
const row = h("tr", { class: "zx-table__header-row" });
|
|
10169
10594
|
if (this._growStep) row.setAttribute("aria-rowindex", "1");
|
|
10595
|
+
if (this.options.rowReorder) row.append(h("th", {
|
|
10596
|
+
class: "zx-table__reorder-header",
|
|
10597
|
+
scope: "col",
|
|
10598
|
+
ariaLabel: "Row order"
|
|
10599
|
+
}));
|
|
10170
10600
|
if (this.options.selectable === "multi") {
|
|
10171
10601
|
this._selectAll = h("input", {
|
|
10172
10602
|
class: "zx-table__checkbox zx-table__select-all",
|
|
@@ -10192,7 +10622,7 @@ var Table = class extends Component {
|
|
|
10192
10622
|
this._selectAll = null;
|
|
10193
10623
|
}
|
|
10194
10624
|
this._headers = /* @__PURE__ */ new Map();
|
|
10195
|
-
for (const column of this.
|
|
10625
|
+
for (const column of this._visibleColumns()) {
|
|
10196
10626
|
const th = h("th", { scope: "col" });
|
|
10197
10627
|
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
10198
10628
|
if (align) th.dataset.align = align;
|
|
@@ -10232,7 +10662,7 @@ var Table = class extends Component {
|
|
|
10232
10662
|
{ class: "zx-table__empty-row" },
|
|
10233
10663
|
h("td", {
|
|
10234
10664
|
class: "zx-table__empty",
|
|
10235
|
-
colspan: this.
|
|
10665
|
+
colspan: this._visibleColumns().length + (this.options.selectable === "multi" ? 1 : 0) + (this.options.rowReorder ? 1 : 0)
|
|
10236
10666
|
}, this._emptyContent())
|
|
10237
10667
|
));
|
|
10238
10668
|
} else {
|
|
@@ -10241,6 +10671,7 @@ var Table = class extends Component {
|
|
|
10241
10671
|
});
|
|
10242
10672
|
}
|
|
10243
10673
|
this._tbody.replaceChildren(fragment2);
|
|
10674
|
+
this._table.setAttribute("aria-colcount", String(this._visibleColumns().length + (this.options.selectable === "multi" ? 1 : 0) + (this.options.rowReorder ? 1 : 0)));
|
|
10244
10675
|
if (this._growStep) this._table.setAttribute("aria-rowcount", String(projected.length + 1));
|
|
10245
10676
|
this._syncSelectAll();
|
|
10246
10677
|
this._syncGrowing();
|
|
@@ -10284,6 +10715,19 @@ var Table = class extends Component {
|
|
|
10284
10715
|
const elements = this._rowElements.get(id) ?? [];
|
|
10285
10716
|
elements.push(tr);
|
|
10286
10717
|
this._rowElements.set(id, elements);
|
|
10718
|
+
if (this.options.rowReorder) {
|
|
10719
|
+
const handle = h("button", {
|
|
10720
|
+
class: "zx-table__row-handle",
|
|
10721
|
+
type: "button",
|
|
10722
|
+
draggable: true,
|
|
10723
|
+
dataset: { rowHandle: "" },
|
|
10724
|
+
ariaLabel: `Move row ${index + 1}`,
|
|
10725
|
+
ariaPressed: String(Object.is(this._grabbedId, id)),
|
|
10726
|
+
disabled: Boolean(this._sort && this.options.sortMode === "local"),
|
|
10727
|
+
title: this._sort && this.options.sortMode === "local" ? "Clear sorting to reorder rows" : null
|
|
10728
|
+
}, icon("drag", { size: 14 }));
|
|
10729
|
+
tr.append(h("td", { class: "zx-table__reorder-cell" }, handle));
|
|
10730
|
+
}
|
|
10287
10731
|
if (this.options.selectable === "multi") {
|
|
10288
10732
|
const checkbox = h("input", {
|
|
10289
10733
|
class: "zx-table__checkbox zx-table__row-checkbox",
|
|
@@ -10293,7 +10737,7 @@ var Table = class extends Component {
|
|
|
10293
10737
|
});
|
|
10294
10738
|
tr.append(h("td", { class: "zx-table__selection-cell" }, checkbox));
|
|
10295
10739
|
}
|
|
10296
|
-
this.
|
|
10740
|
+
this._visibleColumns().forEach((column) => {
|
|
10297
10741
|
const cell = (
|
|
10298
10742
|
/** @type {HTMLTableCellElement} */
|
|
10299
10743
|
h("td")
|
|
@@ -10329,7 +10773,7 @@ var Table = class extends Component {
|
|
|
10329
10773
|
const content = h("span", { class: "zx-table__cell-content" });
|
|
10330
10774
|
if (value && typeof value === "object" && typeof value.nodeType === "number") content.append(value);
|
|
10331
10775
|
else if (value != null) content.append(document.createTextNode(String(value)));
|
|
10332
|
-
if (!this._hierarchy || column.id !== this.
|
|
10776
|
+
if (!this._hierarchy || column.id !== this._hierarchyColumn() || !tree) {
|
|
10333
10777
|
cell.replaceChildren(...content.childNodes);
|
|
10334
10778
|
return;
|
|
10335
10779
|
}
|
|
@@ -10360,6 +10804,7 @@ var Table = class extends Component {
|
|
|
10360
10804
|
if (!rowElement || !this._tbody.contains(rowElement)) return;
|
|
10361
10805
|
const meta = this._rowMeta.get(rowElement);
|
|
10362
10806
|
if (!meta) return;
|
|
10807
|
+
if (target.closest(".zx-table__row-handle")) return;
|
|
10363
10808
|
if (this._edit) {
|
|
10364
10809
|
this.commitEdit();
|
|
10365
10810
|
if (this._edit) return;
|
|
@@ -10379,6 +10824,14 @@ var Table = class extends Component {
|
|
|
10379
10824
|
);
|
|
10380
10825
|
return;
|
|
10381
10826
|
}
|
|
10827
|
+
if (isInteractiveCellContent(target)) return;
|
|
10828
|
+
if (this._editMode !== false && this._editTrigger === "single") {
|
|
10829
|
+
const cell = target?.closest('td[data-editable="true"]');
|
|
10830
|
+
if (cell && this._tbody.contains(cell)) {
|
|
10831
|
+
this.startEdit(meta.id, String(cell.dataset.column));
|
|
10832
|
+
return;
|
|
10833
|
+
}
|
|
10834
|
+
}
|
|
10382
10835
|
this.emit("rowclick", { ...meta, event });
|
|
10383
10836
|
if (this.options.selectable === "single" && !this._selected.has(meta.id)) {
|
|
10384
10837
|
this._selected = /* @__PURE__ */ new Set([meta.id]);
|
|
@@ -10399,7 +10852,8 @@ var Table = class extends Component {
|
|
|
10399
10852
|
if (!rowElement || !this._tbody.contains(rowElement)) return;
|
|
10400
10853
|
const meta = this._rowMeta.get(rowElement);
|
|
10401
10854
|
if (!meta) return;
|
|
10402
|
-
if (
|
|
10855
|
+
if (isInteractiveCellContent(target)) return;
|
|
10856
|
+
if (this._editMode !== false && this._editTrigger === "double") {
|
|
10403
10857
|
const cell = target?.closest('td[data-editable="true"]');
|
|
10404
10858
|
if (cell && this._tbody.contains(cell)) {
|
|
10405
10859
|
this.startEdit(meta.id, String(cell.dataset.column));
|
|
@@ -10701,13 +11155,14 @@ var Table = class extends Component {
|
|
|
10701
11155
|
* @returns {{id: unknown, columnId: string, index: number}|null} Next cell, or null at the end.
|
|
10702
11156
|
*/
|
|
10703
11157
|
_nextEditableCell(rowIndex, columnId, direction) {
|
|
10704
|
-
const
|
|
11158
|
+
const columns = this._visibleColumns();
|
|
11159
|
+
const columnCount = columns.length;
|
|
10705
11160
|
if (rowIndex < 0 || columnCount === 0) return null;
|
|
10706
11161
|
const visible = this._visibleData();
|
|
10707
11162
|
const startingId = this._idFor(this._data[rowIndex]);
|
|
10708
11163
|
let row = visible.findIndex((candidate) => Object.is(this._idFor(candidate), startingId));
|
|
10709
11164
|
if (row < 0) return null;
|
|
10710
|
-
let column =
|
|
11165
|
+
let column = columns.findIndex((candidate) => candidate.id === columnId);
|
|
10711
11166
|
const limit = visible.length * columnCount + columnCount;
|
|
10712
11167
|
for (let step = 0; step < limit; step += 1) {
|
|
10713
11168
|
column += direction;
|
|
@@ -10720,7 +11175,7 @@ var Table = class extends Component {
|
|
|
10720
11175
|
}
|
|
10721
11176
|
if (row < 0 || row >= visible.length) return null;
|
|
10722
11177
|
const candidateRow = visible[row];
|
|
10723
|
-
const candidateColumn =
|
|
11178
|
+
const candidateColumn = columns[column];
|
|
10724
11179
|
if (resolveEditable(candidateColumn, candidateRow) !== false) {
|
|
10725
11180
|
return {
|
|
10726
11181
|
id: this._idFor(candidateRow),
|
|
@@ -10963,6 +11418,53 @@ function sortHierarchyRows(rows, rowId, parentId, getValue, direction) {
|
|
|
10963
11418
|
}
|
|
10964
11419
|
return result;
|
|
10965
11420
|
}
|
|
11421
|
+
function reorderTableRows(rows, rowId, id, targetId, position2 = "before", parentId = null) {
|
|
11422
|
+
if (!Array.isArray(rows) || Object.is(id, targetId)) return null;
|
|
11423
|
+
const from = rows.findIndex((row) => Object.is(readRowValue(rowId, row), id));
|
|
11424
|
+
const target = rows.findIndex((row) => Object.is(readRowValue(rowId, row), targetId));
|
|
11425
|
+
if (from < 0 || target < 0) return null;
|
|
11426
|
+
if (parentId && !sameHierarchyParent(
|
|
11427
|
+
readRowValue(parentId, rows[from]),
|
|
11428
|
+
readRowValue(parentId, rows[target])
|
|
11429
|
+
)) return null;
|
|
11430
|
+
if (parentId) {
|
|
11431
|
+
const forest = hierarchyForest(rows, rowId, parentId);
|
|
11432
|
+
const movingNode = forest.nodes[from];
|
|
11433
|
+
const targetNode = forest.nodes[target];
|
|
11434
|
+
if (!movingNode || !targetNode || movingNode.parent !== targetNode.parent) return null;
|
|
11435
|
+
const branchNodes = (root) => {
|
|
11436
|
+
const result = [];
|
|
11437
|
+
const stack = [root];
|
|
11438
|
+
while (stack.length) {
|
|
11439
|
+
const node = (
|
|
11440
|
+
/** @type {TableHierarchyNode} */
|
|
11441
|
+
stack.pop()
|
|
11442
|
+
);
|
|
11443
|
+
result.push(node);
|
|
11444
|
+
for (let index = node.children.length - 1; index >= 0; index -= 1) stack.push(node.children[index]);
|
|
11445
|
+
}
|
|
11446
|
+
return result;
|
|
11447
|
+
};
|
|
11448
|
+
const moving2 = new Set(branchNodes(movingNode).map((node) => node.index));
|
|
11449
|
+
const targetBranch = new Set(branchNodes(targetNode).map((node) => node.index));
|
|
11450
|
+
const block = rows.filter((_row, index) => moving2.has(index));
|
|
11451
|
+
const remaining = rows.filter((_row, index) => !moving2.has(index));
|
|
11452
|
+
const remainingSourceIndexes = rows.map((_row, index) => index).filter((index) => !moving2.has(index));
|
|
11453
|
+
let insertion = remainingSourceIndexes.findIndex((index) => index === target);
|
|
11454
|
+
if (position2 === "after") {
|
|
11455
|
+
const targetPositions = remainingSourceIndexes.map((sourceIndex, index) => targetBranch.has(sourceIndex) ? index : -1).filter((index) => index >= 0);
|
|
11456
|
+
insertion = Math.max(...targetPositions) + 1;
|
|
11457
|
+
}
|
|
11458
|
+
if (insertion < 0) return null;
|
|
11459
|
+
remaining.splice(insertion, 0, ...block);
|
|
11460
|
+
return remaining;
|
|
11461
|
+
}
|
|
11462
|
+
const next = [...rows];
|
|
11463
|
+
const [moving] = next.splice(from, 1);
|
|
11464
|
+
const adjustedTarget = next.findIndex((row) => Object.is(readRowValue(rowId, row), targetId));
|
|
11465
|
+
next.splice(adjustedTarget + (position2 === "after" ? 1 : 0), 0, moving);
|
|
11466
|
+
return next;
|
|
11467
|
+
}
|
|
10966
11468
|
function resolveEditable(column, row) {
|
|
10967
11469
|
if (!column || typeof column !== "object") return false;
|
|
10968
11470
|
if (typeof column.editor === "function") {
|
|
@@ -11043,7 +11545,8 @@ function hierarchyForest(rows, rowId, parentId) {
|
|
|
11043
11545
|
for (const node of nodes) if (!byId.has(node.id)) byId.set(node.id, node);
|
|
11044
11546
|
const parentOf = /* @__PURE__ */ new Map();
|
|
11045
11547
|
for (const node of nodes) {
|
|
11046
|
-
const
|
|
11548
|
+
const parentValue = readRowValue(parentId, node.row);
|
|
11549
|
+
const parent = parentValue == null ? null : byId.get(parentValue) ?? null;
|
|
11047
11550
|
parentOf.set(node, parent === node ? null : parent);
|
|
11048
11551
|
}
|
|
11049
11552
|
for (const node of nodes) {
|
|
@@ -11072,6 +11575,9 @@ function hierarchyBranchIds(rows, rowId, parentId) {
|
|
|
11072
11575
|
function readRowValue(accessor, row) {
|
|
11073
11576
|
return typeof accessor === "function" ? accessor(row) : row?.[accessor];
|
|
11074
11577
|
}
|
|
11578
|
+
function sameHierarchyParent(left, right) {
|
|
11579
|
+
return left == null && right == null || Object.is(left, right);
|
|
11580
|
+
}
|
|
11075
11581
|
function normalizeHierarchy(option, columns) {
|
|
11076
11582
|
if (!option || typeof option !== "object") return null;
|
|
11077
11583
|
const parentId = option.parentId;
|
|
@@ -11091,6 +11597,23 @@ function normalizeEditMode(mode) {
|
|
|
11091
11597
|
function isInsideEditor(target) {
|
|
11092
11598
|
return Boolean(target?.closest?.(".zx-table__editor"));
|
|
11093
11599
|
}
|
|
11600
|
+
function isInteractiveCellContent(target) {
|
|
11601
|
+
const cell = target?.closest?.("td[data-column]");
|
|
11602
|
+
const interactive = target?.closest?.([
|
|
11603
|
+
"a[href]",
|
|
11604
|
+
"button",
|
|
11605
|
+
"input",
|
|
11606
|
+
"select",
|
|
11607
|
+
"textarea",
|
|
11608
|
+
"summary",
|
|
11609
|
+
'[contenteditable="true"]',
|
|
11610
|
+
'[role="button"]',
|
|
11611
|
+
'[role="link"]',
|
|
11612
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
11613
|
+
"[data-zx-table-no-edit]"
|
|
11614
|
+
].join(","));
|
|
11615
|
+
return Boolean(cell && interactive && interactive !== cell && cell.contains(interactive));
|
|
11616
|
+
}
|
|
11094
11617
|
function deferToEditor(target) {
|
|
11095
11618
|
if (target.closest("[popover]")) return true;
|
|
11096
11619
|
return target.getAttribute?.("aria-expanded") === "true";
|
|
@@ -11125,6 +11648,106 @@ function growStep(growing) {
|
|
|
11125
11648
|
return Number.isFinite(step) && step > 0 ? step : null;
|
|
11126
11649
|
}
|
|
11127
11650
|
|
|
11651
|
+
// src/components/app-icon/app-icon.js
|
|
11652
|
+
var AppIcon = class extends Component {
|
|
11653
|
+
static cssName = "app-icon";
|
|
11654
|
+
/** @type {Readonly<AppIconOptions>} */
|
|
11655
|
+
static defaults = {
|
|
11656
|
+
icon: null,
|
|
11657
|
+
color: null,
|
|
11658
|
+
size: 36,
|
|
11659
|
+
iconSize: "52%",
|
|
11660
|
+
label: null,
|
|
11661
|
+
badge: null,
|
|
11662
|
+
selected: false,
|
|
11663
|
+
glass: "subtle",
|
|
11664
|
+
class: []
|
|
11665
|
+
};
|
|
11666
|
+
/** @returns {HTMLElement} */
|
|
11667
|
+
render() {
|
|
11668
|
+
this._createdRoot = this.el === null;
|
|
11669
|
+
const root = (
|
|
11670
|
+
/** @type {HTMLElement} */
|
|
11671
|
+
this.el ?? h("span")
|
|
11672
|
+
);
|
|
11673
|
+
this.el = root;
|
|
11674
|
+
this._snapshot = this._createdRoot ? null : snapshotTarget(root);
|
|
11675
|
+
this._state = { ...this.options };
|
|
11676
|
+
this._appliedClasses = [];
|
|
11677
|
+
this._sync();
|
|
11678
|
+
return root;
|
|
11679
|
+
}
|
|
11680
|
+
/** Updates identity or presentation without replacing the root. @param {Partial<AppIconOptions>} values @returns {this} */
|
|
11681
|
+
set(values = {}) {
|
|
11682
|
+
if (!values || typeof values !== "object") return this;
|
|
11683
|
+
Object.assign(this._state, values);
|
|
11684
|
+
this._sync();
|
|
11685
|
+
return this;
|
|
11686
|
+
}
|
|
11687
|
+
/** Restores an enhanced target. @returns {void} */
|
|
11688
|
+
destroy() {
|
|
11689
|
+
const root = this.el;
|
|
11690
|
+
const snapshot3 = this._snapshot;
|
|
11691
|
+
super.destroy();
|
|
11692
|
+
if (!this._createdRoot && root) restoreTarget(root, snapshot3);
|
|
11693
|
+
}
|
|
11694
|
+
/** @returns {void} */
|
|
11695
|
+
_sync() {
|
|
11696
|
+
const state = this._state;
|
|
11697
|
+
this.el.classList.remove(...this._appliedClasses);
|
|
11698
|
+
this._appliedClasses = [state.class].flat().flatMap((value) => String(value ?? "").split(/\s+/)).filter(Boolean);
|
|
11699
|
+
this.el.classList.add(...this._appliedClasses);
|
|
11700
|
+
const size = cssLength(state.size, "36px");
|
|
11701
|
+
const glyphSize = cssLength(state.iconSize, "52%");
|
|
11702
|
+
this.el.style.setProperty("--zx-app-icon-size", size);
|
|
11703
|
+
this.el.style.setProperty("--zx-app-icon-glyph-size", glyphSize);
|
|
11704
|
+
if (isCssColor(state.color)) this.el.style.setProperty("--zx-app-icon-color", String(state.color));
|
|
11705
|
+
else this.el.style.removeProperty("--zx-app-icon-color");
|
|
11706
|
+
this.el.dataset.glass = normalizeGlass(state.glass);
|
|
11707
|
+
this.el.toggleAttribute("data-selected", Boolean(state.selected));
|
|
11708
|
+
const label = state.label == null ? "" : String(state.label).trim();
|
|
11709
|
+
if (label) {
|
|
11710
|
+
this.el.setAttribute("role", "img");
|
|
11711
|
+
this.el.setAttribute("aria-label", label);
|
|
11712
|
+
this.el.removeAttribute("aria-hidden");
|
|
11713
|
+
} else {
|
|
11714
|
+
this.el.removeAttribute("role");
|
|
11715
|
+
this.el.removeAttribute("aria-label");
|
|
11716
|
+
this.el.setAttribute("aria-hidden", "true");
|
|
11717
|
+
}
|
|
11718
|
+
const visual = resolveVisual(state.icon);
|
|
11719
|
+
const badge = state.badge == null || state.badge === "" ? null : h("span", {
|
|
11720
|
+
class: "zx-app-icon__badge",
|
|
11721
|
+
ariaHidden: "true"
|
|
11722
|
+
}, String(state.badge));
|
|
11723
|
+
this.el.replaceChildren(
|
|
11724
|
+
h("span", { class: "zx-app-icon__shine", ariaHidden: "true" }),
|
|
11725
|
+
h("span", { class: "zx-app-icon__glyph", ariaHidden: "true" }, visual),
|
|
11726
|
+
badge
|
|
11727
|
+
);
|
|
11728
|
+
}
|
|
11729
|
+
};
|
|
11730
|
+
function appIcon(options = {}) {
|
|
11731
|
+
return new AppIcon(null, options).toElement();
|
|
11732
|
+
}
|
|
11733
|
+
function resolveVisual(value) {
|
|
11734
|
+
const resolved = typeof value === "function" ? value() : value;
|
|
11735
|
+
if (typeof resolved === "string") return icon(resolved, { size: "1em" });
|
|
11736
|
+
return resolved && typeof resolved === "object" && typeof resolved.nodeType === "number" ? (
|
|
11737
|
+
/** @type {Node} */
|
|
11738
|
+
resolved
|
|
11739
|
+
) : null;
|
|
11740
|
+
}
|
|
11741
|
+
function cssLength(value, fallback) {
|
|
11742
|
+
if (typeof value === "number" && Number.isFinite(value)) return `${Math.max(1, value)}px`;
|
|
11743
|
+
const text3 = String(value ?? "").trim();
|
|
11744
|
+
return text3 && !/[;{}]/.test(text3) ? text3 : fallback;
|
|
11745
|
+
}
|
|
11746
|
+
function normalizeGlass(value) {
|
|
11747
|
+
if (value === false || value === "none") return "none";
|
|
11748
|
+
return value === "strong" ? "strong" : "subtle";
|
|
11749
|
+
}
|
|
11750
|
+
|
|
11128
11751
|
// src/components/launcher/launcher.js
|
|
11129
11752
|
var Launcher = class extends Component {
|
|
11130
11753
|
static cssName = "launcher";
|
|
@@ -12967,7 +13590,7 @@ function moduleIcon(name, options = {}) {
|
|
|
12967
13590
|
function moduleChip(name, options = {}) {
|
|
12968
13591
|
const {
|
|
12969
13592
|
size = 24,
|
|
12970
|
-
iconSize = "
|
|
13593
|
+
iconSize = "52%",
|
|
12971
13594
|
label = null,
|
|
12972
13595
|
title = false,
|
|
12973
13596
|
standard = false,
|
|
@@ -12975,25 +13598,28 @@ function moduleChip(name, options = {}) {
|
|
|
12975
13598
|
} = options;
|
|
12976
13599
|
const key = normalizeModuleName(name);
|
|
12977
13600
|
const info = moduleInfo(name);
|
|
12978
|
-
const background = color
|
|
12979
|
-
const chip =
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
13601
|
+
const background = isCssColor(color) ? color : info.color;
|
|
13602
|
+
const chip = appIcon({
|
|
13603
|
+
// AppIcon owns glyph sizing. Keep the provider glyph at 1em so the percentage is not applied
|
|
13604
|
+
// once to the wrapper and a second time to a Font Awesome <i>.
|
|
13605
|
+
icon: options.icon ?? moduleIcon(name, { size: "1em", standard }),
|
|
13606
|
+
size,
|
|
13607
|
+
iconSize,
|
|
13608
|
+
color: background,
|
|
13609
|
+
label,
|
|
13610
|
+
glass: options.glass ?? "subtle",
|
|
13611
|
+
class: ["zx-module-icon", options.class].flat().filter(Boolean)
|
|
13612
|
+
});
|
|
13613
|
+
chip.dataset.module = key;
|
|
13614
|
+
chip.style.setProperty("--zx-module-color", background);
|
|
13615
|
+
chip.style.setProperty("--zx-module-glyph", moduleGlyphColor(background));
|
|
13616
|
+
chip.style.setProperty("--zx-app-icon-glyph", moduleGlyphColor(background));
|
|
13617
|
+
if (title) chip.title = info.label;
|
|
12995
13618
|
return chip;
|
|
12996
13619
|
}
|
|
13620
|
+
function zeyosAppIcon(name, options = {}) {
|
|
13621
|
+
return moduleChip(name, options);
|
|
13622
|
+
}
|
|
12997
13623
|
|
|
12998
13624
|
// src/zeyos/launcher.js
|
|
12999
13625
|
var ZEYOS_LAUNCHER_APPLICATIONS = Object.freeze([
|
|
@@ -13347,6 +13973,7 @@ function buildZeyosEntitySelectConfig(client, resource, opts = {}) {
|
|
|
13347
13973
|
moduleKey = () => resource,
|
|
13348
13974
|
groupKey = null,
|
|
13349
13975
|
none = true,
|
|
13976
|
+
recent = [],
|
|
13350
13977
|
create = false,
|
|
13351
13978
|
renderIcon = defaultEntityIcon,
|
|
13352
13979
|
renderItem,
|
|
@@ -13366,6 +13993,7 @@ function buildZeyosEntitySelectConfig(client, resource, opts = {}) {
|
|
|
13366
13993
|
groupKey,
|
|
13367
13994
|
clearable: none === false ? Boolean(rest.clearable) : true
|
|
13368
13995
|
});
|
|
13996
|
+
base.recent = Array.isArray(recent) ? recent : [];
|
|
13369
13997
|
const renderModuleIcon = (item, selected = false) => {
|
|
13370
13998
|
if (renderIcon === null) return null;
|
|
13371
13999
|
const module = readRecord(item, moduleKey) ?? resource;
|
|
@@ -13416,7 +14044,7 @@ function zeyosEntitySelect(client, resource, opts = {}) {
|
|
|
13416
14044
|
const requestedValue = opts.value ?? null;
|
|
13417
14045
|
const select = (
|
|
13418
14046
|
/** @type {Select & {ready: Promise<Select>}} */
|
|
13419
|
-
|
|
14047
|
+
Select.entity(null, config2)
|
|
13420
14048
|
);
|
|
13421
14049
|
select.ready = hydrateInitialValue(select, client, resource, requestedValue);
|
|
13422
14050
|
return select;
|
|
@@ -13456,9 +14084,7 @@ function readRecord(item, reader) {
|
|
|
13456
14084
|
return null;
|
|
13457
14085
|
}
|
|
13458
14086
|
function defaultEntityIcon(_item, context) {
|
|
13459
|
-
|
|
13460
|
-
chip.replaceChildren(icon("square", { size: 10 }));
|
|
13461
|
-
return chip;
|
|
14087
|
+
return moduleChip(String(context.module ?? "default"), { size: 20 });
|
|
13462
14088
|
}
|
|
13463
14089
|
function defaultProjection(valueKey, labelKey, searchFields) {
|
|
13464
14090
|
const keys = [valueKey, labelKey, ...searchFields].filter((key) => typeof key === "string" && key);
|
|
@@ -13868,6 +14494,7 @@ export {
|
|
|
13868
14494
|
unixSecondsToDate,
|
|
13869
14495
|
useZeyosIcons,
|
|
13870
14496
|
zeyosActiveIdentifier,
|
|
14497
|
+
zeyosAppIcon,
|
|
13871
14498
|
zeyosEntitySelect,
|
|
13872
14499
|
zeyosForm,
|
|
13873
14500
|
zeyosLauncher,
|