@zeyos/zx 4.3.4 → 4.4.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 +155 -0
- package/README.md +7 -0
- package/dist/types/components/activity-item/activity-item.d.ts +351 -0
- package/dist/types/components/activity-list/activity-list.d.ts +195 -0
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +28 -0
- package/dist/types/components/button/button.d.ts +8 -0
- package/dist/types/components/calendar/calendar.d.ts +19 -0
- package/dist/types/components/card/card.d.ts +7 -0
- package/dist/types/components/card-view/card-view.d.ts +11 -3
- package/dist/types/components/card-view/record-card.d.ts +7 -1
- package/dist/types/components/code-editor/code-editor.d.ts +160 -0
- package/dist/types/components/code-editor/field-adapter.d.ts +5 -0
- package/dist/types/components/context-menu/context-menu.d.ts +18 -2
- package/dist/types/components/date-picker/date-picker.d.ts +8 -0
- package/dist/types/components/date-picker/time-picker.d.ts +7 -0
- package/dist/types/components/dialog/dialog.d.ts +29 -0
- package/dist/types/components/entity-ref/entity-ref.d.ts +331 -0
- package/dist/types/components/file-item/file-item.d.ts +234 -0
- package/dist/types/components/file-list/file-list.d.ts +171 -0
- package/dist/types/components/filter/filter.d.ts +91 -36
- package/dist/types/components/filter-panel/filter-panel.d.ts +449 -0
- package/dist/types/components/kanban-view/kanban-card.d.ts +138 -0
- package/dist/types/components/kanban-view/kanban-view.d.ts +170 -4
- package/dist/types/components/launcher/launcher.d.ts +19 -12
- package/dist/types/components/list-toolbar/list-toolbar.d.ts +599 -0
- package/dist/types/components/menu-button/menu-button.d.ts +4 -37
- package/dist/types/components/message/message.d.ts +7 -0
- package/dist/types/components/modal/modal.d.ts +48 -0
- package/dist/types/components/navigation-bar/navigation-bar.d.ts +105 -21
- package/dist/types/components/panel/panel.d.ts +7 -0
- package/dist/types/components/search/search.d.ts +7 -0
- package/dist/types/components/select/select.d.ts +4 -0
- package/dist/types/components/sort-control/sort-control.d.ts +105 -0
- package/dist/types/components/stat-tile/stat-tile.d.ts +277 -0
- package/dist/types/components/tabbox/tabbox.d.ts +7 -0
- package/dist/types/components/table/table.d.ts +144 -0
- package/dist/types/components/table-view/table-view.d.ts +11 -5
- package/dist/types/components/timebox/timebox.d.ts +7 -0
- package/dist/types/components/value-list/value-list.d.ts +8 -0
- package/dist/types/components/view/record-view.d.ts +96 -5
- package/dist/types/core/icons.d.ts +17 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/internal/app-rail.d.ts +10 -0
- package/dist/types/internal/menu-items.d.ts +134 -0
- package/dist/zx-zeyos.esm.js +616 -77
- package/dist/zx-zeyos.esm.min.js +8 -1
- package/dist/zx.css +2085 -238
- package/dist/zx.esm.js +6704 -1542
- package/dist/zx.esm.min.js +10 -3
- package/dist/zx.global.js +6704 -1542
- package/dist/zx.global.min.js +10 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +1479 -127
- package/docs/llms.md +315 -10
- package/docs/llms.txt +11 -5
- package/package.json +1 -1
- package/src/components/activity-item/activity-item.css +137 -0
- package/src/components/activity-item/activity-item.js +599 -0
- package/src/components/activity-list/activity-list.css +64 -0
- package/src/components/activity-list/activity-list.js +375 -0
- package/src/components/app-rail/app-rail.css +227 -19
- package/src/components/app-sidebar/app-sidebar.css +414 -24
- package/src/components/app-sidebar/app-sidebar.js +65 -5
- package/src/components/button/button.css +8 -0
- package/src/components/button/button.js +6 -1
- package/src/components/calendar/calendar.js +33 -3
- package/src/components/card/card.js +12 -1
- package/src/components/card-view/card-view.css +1 -0
- package/src/components/card-view/card-view.js +25 -9
- package/src/components/card-view/record-card.js +7 -3
- package/src/components/code-editor/code-editor.css +67 -0
- package/src/components/code-editor/code-editor.js +288 -0
- package/src/components/code-editor/field-adapter.js +34 -0
- package/src/components/context-menu/context-menu.css +80 -3
- package/src/components/context-menu/context-menu.js +22 -30
- package/src/components/date-picker/date-picker.js +22 -8
- package/src/components/date-picker/month-picker.js +3 -3
- package/src/components/date-picker/time-picker.js +20 -8
- package/src/components/dialog/dialog.js +88 -66
- package/src/components/dropdown/dropdown.js +2 -2
- package/src/components/entity-ref/entity-ref.css +182 -0
- package/src/components/entity-ref/entity-ref.js +496 -0
- package/src/components/file-item/file-item.css +88 -0
- package/src/components/file-item/file-item.js +371 -0
- package/src/components/file-list/file-list.css +51 -0
- package/src/components/file-list/file-list.js +320 -0
- package/src/components/filter/filter.css +27 -1
- package/src/components/filter/filter.js +199 -45
- package/src/components/filter-panel/filter-panel.css +104 -0
- package/src/components/filter-panel/filter-panel.js +964 -0
- package/src/components/kanban-view/kanban-card.js +239 -0
- package/src/components/kanban-view/kanban-view.css +194 -0
- package/src/components/kanban-view/kanban-view.js +251 -8
- package/src/components/launcher/launcher.js +59 -27
- package/src/components/list-toolbar/list-toolbar.css +189 -0
- package/src/components/list-toolbar/list-toolbar.js +851 -0
- package/src/components/menu-button/menu-button.css +80 -3
- package/src/components/menu-button/menu-button.js +21 -37
- package/src/components/message/message.css +5 -2
- package/src/components/message/message.js +13 -2
- package/src/components/modal/modal.css +15 -0
- package/src/components/modal/modal.js +141 -0
- package/src/components/navigation-bar/navigation-bar.css +77 -2
- package/src/components/navigation-bar/navigation-bar.js +171 -4
- package/src/components/panel/panel.js +13 -2
- package/src/components/search/search.js +17 -5
- package/src/components/select/field-adapter.js +4 -1
- package/src/components/select/select.js +3 -0
- package/src/components/sort-control/sort-control.css +17 -0
- package/src/components/sort-control/sort-control.js +140 -0
- package/src/components/stat-tile/stat-tile.css +213 -0
- package/src/components/stat-tile/stat-tile.js +590 -0
- package/src/components/tabbox/tabbox.js +12 -1
- package/src/components/table/table.css +51 -2
- package/src/components/table/table.js +298 -19
- package/src/components/table-view/table-view.css +8 -2
- package/src/components/table-view/table-view.js +21 -6
- package/src/components/tag-picker/tag-picker.css +3 -1
- package/src/components/timebox/timebox.js +18 -5
- package/src/components/value-list/value-list.js +22 -6
- package/src/components/view/record-view.css +5 -0
- package/src/components/view/record-view.js +100 -7
- package/src/core/icons.js +74 -5
- package/src/index.js +25 -0
- package/src/internal/app-rail.js +19 -1
- package/src/internal/menu-items.js +142 -0
- package/styles/print.css +192 -0
- package/styles/zx.css +11 -0
package/dist/zx-zeyos.esm.js
CHANGED
|
@@ -1800,6 +1800,271 @@ function registerChecklistFieldAdapter() {
|
|
|
1800
1800
|
});
|
|
1801
1801
|
}
|
|
1802
1802
|
|
|
1803
|
+
// src/components/code-editor/code-editor.js
|
|
1804
|
+
var CodeEditor = class extends Component {
|
|
1805
|
+
static cssName = "code-editor";
|
|
1806
|
+
/** @type {CodeEditorOptions} */
|
|
1807
|
+
static defaults = {
|
|
1808
|
+
value: "",
|
|
1809
|
+
name: "",
|
|
1810
|
+
language: "text",
|
|
1811
|
+
label: "Code editor",
|
|
1812
|
+
placeholder: "",
|
|
1813
|
+
rows: 12,
|
|
1814
|
+
indent: " ",
|
|
1815
|
+
wrap: "off",
|
|
1816
|
+
spellcheck: false,
|
|
1817
|
+
readOnly: false,
|
|
1818
|
+
disabled: false,
|
|
1819
|
+
status: true
|
|
1820
|
+
};
|
|
1821
|
+
/** @returns {HTMLElement} */
|
|
1822
|
+
render() {
|
|
1823
|
+
this._createdRoot = this.el === null;
|
|
1824
|
+
const root = (
|
|
1825
|
+
/** @type {HTMLElement} */
|
|
1826
|
+
this.el ?? h("div")
|
|
1827
|
+
);
|
|
1828
|
+
this.el = root;
|
|
1829
|
+
this._initialChildren = this._createdRoot ? [] : [...root.childNodes];
|
|
1830
|
+
this._initialAttributes = new Map(["data-language", "data-readonly", "data-disabled"].map((name) => [name, root.getAttribute(name)]));
|
|
1831
|
+
this._language = normalizeLanguage(this.options.language);
|
|
1832
|
+
this._languageLabel = h("span", { class: "zx-code-editor__language" }, this._language);
|
|
1833
|
+
this._position = h("span", {
|
|
1834
|
+
class: "zx-code-editor__position",
|
|
1835
|
+
role: "status",
|
|
1836
|
+
ariaLive: "polite"
|
|
1837
|
+
});
|
|
1838
|
+
this._header = h(
|
|
1839
|
+
"div",
|
|
1840
|
+
{ class: "zx-code-editor__header" },
|
|
1841
|
+
this._languageLabel,
|
|
1842
|
+
this.options.status ? this._position : null
|
|
1843
|
+
);
|
|
1844
|
+
this._input = /** @type {HTMLTextAreaElement} */
|
|
1845
|
+
h("textarea", {
|
|
1846
|
+
class: "zx-code-editor__input",
|
|
1847
|
+
name: this.options.name ? String(this.options.name) : void 0,
|
|
1848
|
+
ariaLabel: String(this.options.label ?? "Code editor"),
|
|
1849
|
+
placeholder: String(this.options.placeholder ?? ""),
|
|
1850
|
+
rows: normalizeRows(this.options.rows),
|
|
1851
|
+
wrap: normalizeWrap(this.options.wrap),
|
|
1852
|
+
spellcheck: Boolean(this.options.spellcheck),
|
|
1853
|
+
readOnly: Boolean(this.options.readOnly),
|
|
1854
|
+
disabled: Boolean(this.options.disabled),
|
|
1855
|
+
autocomplete: "off",
|
|
1856
|
+
autocapitalize: "off"
|
|
1857
|
+
});
|
|
1858
|
+
this._input.value = String(this.options.value ?? "");
|
|
1859
|
+
root.dataset.language = this._language;
|
|
1860
|
+
root.dataset.readonly = String(Boolean(this.options.readOnly));
|
|
1861
|
+
root.dataset.disabled = String(Boolean(this.options.disabled));
|
|
1862
|
+
root.replaceChildren(this._header, this._input);
|
|
1863
|
+
this.listen(this._input, "keydown", (event) => this._handleKeydown(event));
|
|
1864
|
+
this.listen(this._input, "input", () => {
|
|
1865
|
+
this._updatePosition();
|
|
1866
|
+
this.emit("input", { value: this.getValue() });
|
|
1867
|
+
});
|
|
1868
|
+
this.listen(this._input, "change", () => this.emit("change", { value: this.getValue() }));
|
|
1869
|
+
for (const type of ["click", "keyup", "select", "focus"]) {
|
|
1870
|
+
this.listen(this._input, type, () => this._updatePosition());
|
|
1871
|
+
}
|
|
1872
|
+
this._updatePosition();
|
|
1873
|
+
return root;
|
|
1874
|
+
}
|
|
1875
|
+
/** @returns {string} */
|
|
1876
|
+
getValue() {
|
|
1877
|
+
return this._input.value;
|
|
1878
|
+
}
|
|
1879
|
+
/**
|
|
1880
|
+
* Replaces the editor text.
|
|
1881
|
+
* @param {unknown} value New value.
|
|
1882
|
+
* @param {{silent?:boolean}} [options={}] Suppress the `change` event.
|
|
1883
|
+
* @returns {this}
|
|
1884
|
+
*/
|
|
1885
|
+
setValue(value, { silent = false } = {}) {
|
|
1886
|
+
const next = String(value ?? "");
|
|
1887
|
+
if (this._input.value === next) return this;
|
|
1888
|
+
this._input.value = next;
|
|
1889
|
+
this._updatePosition();
|
|
1890
|
+
if (!silent) this.emit("change", { value: next });
|
|
1891
|
+
return this;
|
|
1892
|
+
}
|
|
1893
|
+
/** @param {unknown} language New language identifier. @returns {this} */
|
|
1894
|
+
setLanguage(language2) {
|
|
1895
|
+
this._language = normalizeLanguage(language2);
|
|
1896
|
+
this.el.dataset.language = this._language;
|
|
1897
|
+
this._languageLabel.textContent = this._language;
|
|
1898
|
+
return this;
|
|
1899
|
+
}
|
|
1900
|
+
/** @returns {this} */
|
|
1901
|
+
focus() {
|
|
1902
|
+
this._input.focus();
|
|
1903
|
+
return this;
|
|
1904
|
+
}
|
|
1905
|
+
/** @returns {this} */
|
|
1906
|
+
enable() {
|
|
1907
|
+
this._input.disabled = false;
|
|
1908
|
+
this.el.dataset.disabled = "false";
|
|
1909
|
+
return this;
|
|
1910
|
+
}
|
|
1911
|
+
/** @returns {this} */
|
|
1912
|
+
disable() {
|
|
1913
|
+
this._input.disabled = true;
|
|
1914
|
+
this.el.dataset.disabled = "true";
|
|
1915
|
+
return this;
|
|
1916
|
+
}
|
|
1917
|
+
/** @param {boolean} value Read-only state. @returns {this} */
|
|
1918
|
+
setReadOnly(value) {
|
|
1919
|
+
this._input.readOnly = Boolean(value);
|
|
1920
|
+
this.el.dataset.readonly = String(Boolean(value));
|
|
1921
|
+
return this;
|
|
1922
|
+
}
|
|
1923
|
+
/** @param {KeyboardEvent} event @returns {void} */
|
|
1924
|
+
_handleKeydown(event) {
|
|
1925
|
+
if (event.key !== "Tab" || event.altKey || event.ctrlKey || event.metaKey || this._input.readOnly || this._input.disabled) return;
|
|
1926
|
+
const indent = String(this.options.indent ?? " ");
|
|
1927
|
+
if (!indent) return;
|
|
1928
|
+
event.preventDefault();
|
|
1929
|
+
const result = indentSelection(
|
|
1930
|
+
this._input.value,
|
|
1931
|
+
this._input.selectionStart ?? 0,
|
|
1932
|
+
this._input.selectionEnd ?? 0,
|
|
1933
|
+
indent,
|
|
1934
|
+
event.shiftKey
|
|
1935
|
+
);
|
|
1936
|
+
if (result.value === this._input.value) return;
|
|
1937
|
+
this._input.value = result.value;
|
|
1938
|
+
this._input.setSelectionRange(result.start, result.end);
|
|
1939
|
+
this._updatePosition();
|
|
1940
|
+
this.emit("input", { value: this.getValue() });
|
|
1941
|
+
}
|
|
1942
|
+
/** @returns {void} */
|
|
1943
|
+
_updatePosition() {
|
|
1944
|
+
if (!this.options.status) return;
|
|
1945
|
+
const position2 = editorPosition(
|
|
1946
|
+
this._input.value,
|
|
1947
|
+
this._input.selectionStart ?? 0,
|
|
1948
|
+
this._input.selectionEnd ?? 0
|
|
1949
|
+
);
|
|
1950
|
+
this._position.textContent = position2.lines > 1 ? `Ln ${position2.line}, Col ${position2.column} \xB7 ${position2.lines} lines selected` : `Ln ${position2.line}, Col ${position2.column}`;
|
|
1951
|
+
}
|
|
1952
|
+
/** @returns {void} */
|
|
1953
|
+
destroy() {
|
|
1954
|
+
if (!this._createdRoot) {
|
|
1955
|
+
this.el.replaceChildren(...this._initialChildren);
|
|
1956
|
+
for (const [name, value] of this._initialAttributes) {
|
|
1957
|
+
if (value === null) this.el.removeAttribute(name);
|
|
1958
|
+
else this.el.setAttribute(name, value);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
super.destroy();
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
function indentSelection(value, start, end, indent = " ", outdent = false) {
|
|
1965
|
+
const source = String(value ?? "");
|
|
1966
|
+
const unit = String(indent ?? "");
|
|
1967
|
+
const from = clampIndex(start, source.length);
|
|
1968
|
+
const to = clampIndex(end, source.length);
|
|
1969
|
+
if (!unit) return { value: source, start: from, end: to };
|
|
1970
|
+
if (from === to && !outdent) {
|
|
1971
|
+
return {
|
|
1972
|
+
value: source.slice(0, from) + unit + source.slice(to),
|
|
1973
|
+
start: from + unit.length,
|
|
1974
|
+
end: from + unit.length
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
const lineStart = source.lastIndexOf("\n", Math.max(0, from - 1)) + 1;
|
|
1978
|
+
let lineEnd = source.indexOf("\n", to);
|
|
1979
|
+
if (lineEnd < 0) lineEnd = source.length;
|
|
1980
|
+
const block = source.slice(lineStart, lineEnd);
|
|
1981
|
+
const lines = block.split("\n");
|
|
1982
|
+
let removedFirst = 0;
|
|
1983
|
+
let delta = 0;
|
|
1984
|
+
const transformed = lines.map((line, index) => {
|
|
1985
|
+
if (!outdent) {
|
|
1986
|
+
delta += unit.length;
|
|
1987
|
+
return unit + line;
|
|
1988
|
+
}
|
|
1989
|
+
const removed = removableIndent(line, unit);
|
|
1990
|
+
if (index === 0) removedFirst = removed;
|
|
1991
|
+
delta -= removed;
|
|
1992
|
+
return line.slice(removed);
|
|
1993
|
+
}).join("\n");
|
|
1994
|
+
const nextStart = outdent ? Math.max(lineStart, from - Math.min(removedFirst, from - lineStart)) : from + unit.length;
|
|
1995
|
+
return {
|
|
1996
|
+
value: source.slice(0, lineStart) + transformed + source.slice(lineEnd),
|
|
1997
|
+
start: nextStart,
|
|
1998
|
+
end: Math.max(nextStart, to + delta)
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
function editorPosition(value, start, end = start) {
|
|
2002
|
+
const source = String(value ?? "");
|
|
2003
|
+
const from = clampIndex(start, source.length);
|
|
2004
|
+
const to = clampIndex(end, source.length);
|
|
2005
|
+
const before = source.slice(0, from);
|
|
2006
|
+
return {
|
|
2007
|
+
line: before.split("\n").length,
|
|
2008
|
+
column: from - before.lastIndexOf("\n"),
|
|
2009
|
+
lines: source.slice(from, to).split("\n").length
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
function removableIndent(line, indent) {
|
|
2013
|
+
if (line.startsWith(indent)) return indent.length;
|
|
2014
|
+
if (indent === " ") return line.startsWith(" ") ? 1 : Math.min(/^ +/.exec(line)?.[0].length ?? 0, 2);
|
|
2015
|
+
return Math.min(/^\s+/.exec(line)?.[0].length ?? 0, indent.length);
|
|
2016
|
+
}
|
|
2017
|
+
function normalizeLanguage(value) {
|
|
2018
|
+
const language2 = String(value ?? "text").trim().toLowerCase();
|
|
2019
|
+
return /^[a-z0-9][a-z0-9+_.-]*$/.test(language2) ? language2 : "text";
|
|
2020
|
+
}
|
|
2021
|
+
function normalizeRows(value) {
|
|
2022
|
+
const rows = Number(value);
|
|
2023
|
+
return Number.isFinite(rows) ? Math.max(2, Math.min(100, Math.round(rows))) : 12;
|
|
2024
|
+
}
|
|
2025
|
+
function normalizeWrap(value) {
|
|
2026
|
+
return ["off", "soft", "hard"].includes(String(value)) ? (
|
|
2027
|
+
/** @type {'off'|'soft'|'hard'} */
|
|
2028
|
+
value
|
|
2029
|
+
) : "off";
|
|
2030
|
+
}
|
|
2031
|
+
function clampIndex(value, length) {
|
|
2032
|
+
const number = Number(value);
|
|
2033
|
+
return Math.max(0, Math.min(length, Number.isFinite(number) ? Math.round(number) : 0));
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
// src/components/code-editor/field-adapter.js
|
|
2037
|
+
function registerCodeEditorFieldAdapter() {
|
|
2038
|
+
Field.register("code", (field, options) => {
|
|
2039
|
+
const editor = field.own(new CodeEditor(null, {
|
|
2040
|
+
label: options.label ? String(options.label) : "Code editor",
|
|
2041
|
+
placeholder: options.placeholder,
|
|
2042
|
+
readOnly: Boolean(options.props?.readOnly),
|
|
2043
|
+
disabled: Boolean(options.disabled),
|
|
2044
|
+
...options.props ?? {},
|
|
2045
|
+
value: options.value
|
|
2046
|
+
}));
|
|
2047
|
+
let setting = false;
|
|
2048
|
+
editor.on("input", (event) => {
|
|
2049
|
+
if (!setting) field.emit("change", { value: event.detail.value });
|
|
2050
|
+
});
|
|
2051
|
+
return {
|
|
2052
|
+
el: editor.el,
|
|
2053
|
+
get: () => editor.getValue(),
|
|
2054
|
+
set: (value) => {
|
|
2055
|
+
setting = true;
|
|
2056
|
+
try {
|
|
2057
|
+
editor.setValue(value, { silent: true });
|
|
2058
|
+
} finally {
|
|
2059
|
+
setting = false;
|
|
2060
|
+
}
|
|
2061
|
+
},
|
|
2062
|
+
focus: () => editor.focus(),
|
|
2063
|
+
setDisabled: (value) => value ? editor.disable() : editor.enable()
|
|
2064
|
+
};
|
|
2065
|
+
});
|
|
2066
|
+
}
|
|
2067
|
+
|
|
1803
2068
|
// src/core/date.js
|
|
1804
2069
|
var MONTHS = [
|
|
1805
2070
|
"January",
|
|
@@ -2085,6 +2350,8 @@ function loadFontAwesomeKit(kit) {
|
|
|
2085
2350
|
// src/core/icons.js
|
|
2086
2351
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2087
2352
|
var icons = Object.freeze({
|
|
2353
|
+
"arrow-up-wide-short": ["0 0 576 512", "M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3 96 448c0 17.7 14.3 32 32 32s32-14.3 32-32l0-301.7 32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480l32 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-32 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-160 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l224 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L320 32c-17.7 0-32 14.3-32 32s14.3 32 32 32z"],
|
|
2354
|
+
"arrow-down-wide-short": ["0 0 576 512", "M151.6 469.6C145.5 476.2 137 480 128 480s-17.5-3.8-23.6-10.4l-88-96c-11.9-13-11.1-33.3 2-45.2s33.3-11.1 45.2 2L96 365.7 96 64c0-17.7 14.3-32 32-32s32 14.3 32 32l0 301.7 32.4-35.4c11.9-13 32.2-13.9 45.2-2s13.9 32.2 2 45.2l-88 96zM320 480c-17.7 0-32-14.3-32-32s14.3-32 32-32l32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l96 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-96 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l160 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-160 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l224 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L320 96z"],
|
|
2088
2355
|
"chevron-down": ["0 0 512 512", "M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"],
|
|
2089
2356
|
"chevron-up": ["0 0 512 512", "M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z"],
|
|
2090
2357
|
"chevron-left": ["0 0 320 512", "M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"],
|
|
@@ -2180,11 +2447,21 @@ function icon(name, options = {}) {
|
|
|
2180
2447
|
}
|
|
2181
2448
|
function builtinIcon(name, options) {
|
|
2182
2449
|
const entry = extraGlyphs[name] ?? icons[name];
|
|
2183
|
-
if (!entry)
|
|
2450
|
+
if (!entry) {
|
|
2451
|
+
if (options.strict) throw new RangeError(`Unknown icon: ${name}`);
|
|
2452
|
+
warnMissingIcon(name);
|
|
2453
|
+
return missingIcon(name, options);
|
|
2454
|
+
}
|
|
2184
2455
|
const [viewBox, pathData] = entry;
|
|
2456
|
+
const svg = iconSvg(viewBox, options);
|
|
2457
|
+
const path = document.createElementNS(SVG_NS, "path");
|
|
2458
|
+
path.setAttribute("d", pathData);
|
|
2459
|
+
svg.append(path);
|
|
2460
|
+
return svg;
|
|
2461
|
+
}
|
|
2462
|
+
function iconSvg(viewBox, options) {
|
|
2185
2463
|
const { size = 16 } = options;
|
|
2186
2464
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2187
|
-
const path = document.createElementNS(SVG_NS, "path");
|
|
2188
2465
|
svg.setAttribute("class", classList("zx-icon", options.class));
|
|
2189
2466
|
svg.setAttribute("viewBox", viewBox);
|
|
2190
2467
|
svg.setAttribute("width", String(size));
|
|
@@ -2192,10 +2469,20 @@ function builtinIcon(name, options) {
|
|
|
2192
2469
|
svg.setAttribute("fill", "currentColor");
|
|
2193
2470
|
svg.setAttribute("focusable", "false");
|
|
2194
2471
|
applyLabel(svg, options.label ?? null);
|
|
2195
|
-
path.setAttribute("d", pathData);
|
|
2196
|
-
svg.append(path);
|
|
2197
2472
|
return svg;
|
|
2198
2473
|
}
|
|
2474
|
+
var PLACEHOLDER_VIEW_BOX = "0 0 512 512";
|
|
2475
|
+
function missingIcon(name, options) {
|
|
2476
|
+
const svg = iconSvg(PLACEHOLDER_VIEW_BOX, options);
|
|
2477
|
+
svg.setAttribute("data-zx-icon-missing", name);
|
|
2478
|
+
return svg;
|
|
2479
|
+
}
|
|
2480
|
+
var warnedMissing = /* @__PURE__ */ new Set();
|
|
2481
|
+
function warnMissingIcon(name) {
|
|
2482
|
+
if (warnedMissing.has(name)) return;
|
|
2483
|
+
warnedMissing.add(name);
|
|
2484
|
+
console.warn(`[zx.icon] Unknown icon "${name}" \u2014 rendered an empty placeholder. Add it with registerIcons(), or render Font Awesome with useFontAwesome().`);
|
|
2485
|
+
}
|
|
2199
2486
|
function faIcon(classes, options) {
|
|
2200
2487
|
const { size = 16 } = options;
|
|
2201
2488
|
const element = document.createElement("i");
|
|
@@ -2239,15 +2526,15 @@ var TimePicker = class extends Component {
|
|
|
2239
2526
|
const content = h("div", {
|
|
2240
2527
|
class: "zx-time-picker__segments",
|
|
2241
2528
|
role: "group",
|
|
2242
|
-
ariaLabel: "Time"
|
|
2529
|
+
ariaLabel: this._message("timePicker.label", "Time")
|
|
2243
2530
|
});
|
|
2244
2531
|
this._content = content;
|
|
2245
|
-
this._addSpin(content, "h", "Hour", 23);
|
|
2532
|
+
this._addSpin(content, "h", this._message("timePicker.hour", "Hour"), 23);
|
|
2246
2533
|
content.append(h("span", { class: "zx-time-picker__separator", ariaHidden: "true" }, ":"));
|
|
2247
|
-
this._addSpin(content, "m", "Minute", 59);
|
|
2534
|
+
this._addSpin(content, "m", this._message("timePicker.minute", "Minute"), 59);
|
|
2248
2535
|
if (this.options.seconds) {
|
|
2249
2536
|
content.append(h("span", { class: "zx-time-picker__separator", ariaHidden: "true" }, ":"));
|
|
2250
|
-
this._addSpin(content, "s", "Second", 59);
|
|
2537
|
+
this._addSpin(content, "s", this._message("timePicker.second", "Second"), 59);
|
|
2251
2538
|
}
|
|
2252
2539
|
root.append(content);
|
|
2253
2540
|
if (this.options.clock) {
|
|
@@ -2256,7 +2543,7 @@ var TimePicker = class extends Component {
|
|
|
2256
2543
|
ref: "clockToggle",
|
|
2257
2544
|
class: "zx-icon-btn zx-time-picker__clock-toggle",
|
|
2258
2545
|
type: "button",
|
|
2259
|
-
ariaLabel: "Pick the time on a clock",
|
|
2546
|
+
ariaLabel: this._message("timePicker.clock", "Pick the time on a clock"),
|
|
2260
2547
|
ariaExpanded: "false",
|
|
2261
2548
|
ariaControls: clockId
|
|
2262
2549
|
}, icon("clock", { size: 15 })));
|
|
@@ -2403,7 +2690,7 @@ var TimePicker = class extends Component {
|
|
|
2403
2690
|
ref: "headHour",
|
|
2404
2691
|
class: "zx-time-picker__clock-unit",
|
|
2405
2692
|
type: "button",
|
|
2406
|
-
ariaLabel: "Select the hour",
|
|
2693
|
+
ariaLabel: this._message("timePicker.selectHour", "Select the hour"),
|
|
2407
2694
|
dataset: { unit: "h" }
|
|
2408
2695
|
}),
|
|
2409
2696
|
h("span", { class: "zx-time-picker__clock-colon", ariaHidden: "true" }, ":"),
|
|
@@ -2411,7 +2698,7 @@ var TimePicker = class extends Component {
|
|
|
2411
2698
|
ref: "headMinute",
|
|
2412
2699
|
class: "zx-time-picker__clock-unit",
|
|
2413
2700
|
type: "button",
|
|
2414
|
-
ariaLabel: "Select the minutes",
|
|
2701
|
+
ariaLabel: this._message("timePicker.selectMinutes", "Select the minutes"),
|
|
2415
2702
|
dataset: { unit: "m" }
|
|
2416
2703
|
})
|
|
2417
2704
|
),
|
|
@@ -2469,7 +2756,7 @@ var TimePicker = class extends Component {
|
|
|
2469
2756
|
this.refs.headMinute.textContent = pad2(this._display.m);
|
|
2470
2757
|
this.refs.headHour.setAttribute("aria-pressed", String(hours));
|
|
2471
2758
|
this.refs.headMinute.setAttribute("aria-pressed", String(!hours));
|
|
2472
|
-
this.refs.dial.setAttribute("aria-label", hours ? "Hour" : "Minutes");
|
|
2759
|
+
this.refs.dial.setAttribute("aria-label", hours ? this._message("timePicker.hour", "Hour") : this._message("timePicker.minutes", "Minutes"));
|
|
2473
2760
|
if (!this._clockOpen) return;
|
|
2474
2761
|
const selected = hours ? this._display.h : this._display.m;
|
|
2475
2762
|
const marks = hours ? hourMarks() : minuteMarks();
|
|
@@ -2504,6 +2791,16 @@ var TimePicker = class extends Component {
|
|
|
2504
2791
|
element.setAttribute("aria-checked", String(checked));
|
|
2505
2792
|
element.tabIndex = checked ? 0 : -1;
|
|
2506
2793
|
}
|
|
2794
|
+
/**
|
|
2795
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
2796
|
+
* @param {string} key Message key.
|
|
2797
|
+
* @param {string} fallback English default.
|
|
2798
|
+
* @returns {string}
|
|
2799
|
+
*/
|
|
2800
|
+
_message(key, fallback) {
|
|
2801
|
+
const message = this.msg(key);
|
|
2802
|
+
return message === key ? fallback : message;
|
|
2803
|
+
}
|
|
2507
2804
|
};
|
|
2508
2805
|
function hourMarks() {
|
|
2509
2806
|
const marks = [];
|
|
@@ -2590,7 +2887,7 @@ var DatePicker = class extends Component {
|
|
|
2590
2887
|
ref: "previous",
|
|
2591
2888
|
class: "zx-date-picker__nav",
|
|
2592
2889
|
type: "button",
|
|
2593
|
-
ariaLabel: "Previous month"
|
|
2890
|
+
ariaLabel: this._message("datePicker.previousMonth", "Previous month")
|
|
2594
2891
|
}, icon("chevron-left")),
|
|
2595
2892
|
h("button", {
|
|
2596
2893
|
ref: "heading",
|
|
@@ -2603,7 +2900,7 @@ var DatePicker = class extends Component {
|
|
|
2603
2900
|
ref: "next",
|
|
2604
2901
|
class: "zx-date-picker__nav",
|
|
2605
2902
|
type: "button",
|
|
2606
|
-
ariaLabel: "Next month"
|
|
2903
|
+
ariaLabel: this._message("datePicker.nextMonth", "Next month")
|
|
2607
2904
|
}, icon("chevron-right"))
|
|
2608
2905
|
),
|
|
2609
2906
|
h(
|
|
@@ -2620,14 +2917,14 @@ var DatePicker = class extends Component {
|
|
|
2620
2917
|
ref: "quickPrevious",
|
|
2621
2918
|
class: "zx-date-picker__nav",
|
|
2622
2919
|
type: "button",
|
|
2623
|
-
ariaLabel: "Previous year"
|
|
2920
|
+
ariaLabel: this._message("datePicker.previousYear", "Previous year")
|
|
2624
2921
|
}, icon("chevron-left")),
|
|
2625
2922
|
h("span", { ref: "quickYear", class: "zx-date-picker__quick-year", ariaLive: "polite" }),
|
|
2626
2923
|
h("button", {
|
|
2627
2924
|
ref: "quickNext",
|
|
2628
2925
|
class: "zx-date-picker__nav",
|
|
2629
2926
|
type: "button",
|
|
2630
|
-
ariaLabel: "Next year"
|
|
2927
|
+
ariaLabel: this._message("datePicker.nextYear", "Next year")
|
|
2631
2928
|
}, icon("chevron-right"))
|
|
2632
2929
|
),
|
|
2633
2930
|
h("div", { ref: "quickGrid", class: "zx-date-picker__quick-grid", role: "grid" })
|
|
@@ -2638,7 +2935,7 @@ var DatePicker = class extends Component {
|
|
|
2638
2935
|
ref: "grid",
|
|
2639
2936
|
class: "zx-date-picker__grid",
|
|
2640
2937
|
role: "grid",
|
|
2641
|
-
ariaLabel: "Calendar"
|
|
2938
|
+
ariaLabel: this._message("datePicker.calendar", "Calendar")
|
|
2642
2939
|
},
|
|
2643
2940
|
h("thead", { ref: "weekdays" }),
|
|
2644
2941
|
h("tbody", { ref: "days" })
|
|
@@ -2736,7 +3033,7 @@ var DatePicker = class extends Component {
|
|
|
2736
3033
|
row.append(h("th", {
|
|
2737
3034
|
class: "zx-date-picker__week-heading",
|
|
2738
3035
|
scope: "col",
|
|
2739
|
-
ariaLabel: "Week number"
|
|
3036
|
+
ariaLabel: this._message("datePicker.weekNumber", "Week number")
|
|
2740
3037
|
}, "#"));
|
|
2741
3038
|
}
|
|
2742
3039
|
const sunday = new Date(2023, 0, 1);
|
|
@@ -2756,7 +3053,10 @@ var DatePicker = class extends Component {
|
|
|
2756
3053
|
const offset = (first.getDay() - this._weekStart + 7) % 7;
|
|
2757
3054
|
const start = addDays(first, -offset);
|
|
2758
3055
|
this.refs.heading.textContent = formatDate(first, "%B %Y");
|
|
2759
|
-
this.refs.heading.setAttribute(
|
|
3056
|
+
this.refs.heading.setAttribute(
|
|
3057
|
+
"aria-label",
|
|
3058
|
+
this._message("datePicker.chooseMonthYear", "Choose month and year, %1", formatDate(first, "%B %Y"))
|
|
3059
|
+
);
|
|
2760
3060
|
const rows = [];
|
|
2761
3061
|
for (let week = 0; week < 6; week += 1) {
|
|
2762
3062
|
const rowStart = addDays(start, week * 7);
|
|
@@ -2765,7 +3065,7 @@ var DatePicker = class extends Component {
|
|
|
2765
3065
|
row.append(h("th", {
|
|
2766
3066
|
class: "zx-date-picker__week",
|
|
2767
3067
|
scope: "row",
|
|
2768
|
-
ariaLabel:
|
|
3068
|
+
ariaLabel: this._message("datePicker.week", "Week %1", isoWeekNumber(rowStart))
|
|
2769
3069
|
}, String(isoWeekNumber(rowStart))));
|
|
2770
3070
|
}
|
|
2771
3071
|
for (let column = 0; column < 7; column += 1) {
|
|
@@ -2970,6 +3270,17 @@ var DatePicker = class extends Component {
|
|
|
2970
3270
|
_buttonForDate(date) {
|
|
2971
3271
|
return this.refs.days.querySelector(`[data-date="${formatDate(date, "%Y-%m-%d")}"]`);
|
|
2972
3272
|
}
|
|
3273
|
+
/**
|
|
3274
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
3275
|
+
* @param {string} key Message key.
|
|
3276
|
+
* @param {string} fallback Built-in text, with `%1`-style placeholders.
|
|
3277
|
+
* @param {...unknown} args Interpolation values.
|
|
3278
|
+
* @returns {string}
|
|
3279
|
+
*/
|
|
3280
|
+
_message(key, fallback, ...args) {
|
|
3281
|
+
const message = this.msg(key, ...args);
|
|
3282
|
+
return message === key ? printf(fallback, args) : message;
|
|
3283
|
+
}
|
|
2973
3284
|
};
|
|
2974
3285
|
function validDate(value) {
|
|
2975
3286
|
return value instanceof Date && !Number.isNaN(value.getTime()) ? new Date(value.getTime()) : null;
|
|
@@ -3031,21 +3342,21 @@ var MonthPicker = class extends DatePicker {
|
|
|
3031
3342
|
ref: "previousYear",
|
|
3032
3343
|
class: "zx-month-picker__nav",
|
|
3033
3344
|
type: "button",
|
|
3034
|
-
ariaLabel: "Previous year"
|
|
3345
|
+
ariaLabel: this._message("monthPicker.previousYear", "Previous year")
|
|
3035
3346
|
}, icon("chevron-left")),
|
|
3036
3347
|
h("span", { ref: "year", class: "zx-month-picker__year", ariaLive: "polite" }),
|
|
3037
3348
|
h("button", {
|
|
3038
3349
|
ref: "nextYear",
|
|
3039
3350
|
class: "zx-month-picker__nav",
|
|
3040
3351
|
type: "button",
|
|
3041
|
-
ariaLabel: "Next year"
|
|
3352
|
+
ariaLabel: this._message("monthPicker.nextYear", "Next year")
|
|
3042
3353
|
}, icon("chevron-right"))
|
|
3043
3354
|
),
|
|
3044
3355
|
h("div", {
|
|
3045
3356
|
ref: "grid",
|
|
3046
3357
|
class: "zx-month-picker__grid",
|
|
3047
3358
|
role: "grid",
|
|
3048
|
-
ariaLabel: "Choose month"
|
|
3359
|
+
ariaLabel: this._message("monthPicker.chooseMonth", "Choose month")
|
|
3049
3360
|
})
|
|
3050
3361
|
);
|
|
3051
3362
|
this._content = content;
|
|
@@ -6594,6 +6905,7 @@ var Select = class _Select extends Component {
|
|
|
6594
6905
|
value: null,
|
|
6595
6906
|
disabled: false,
|
|
6596
6907
|
placeholder: "",
|
|
6908
|
+
label: "",
|
|
6597
6909
|
clearable: false,
|
|
6598
6910
|
filter: false,
|
|
6599
6911
|
searchKeys: null,
|
|
@@ -6635,6 +6947,7 @@ var Select = class _Select extends Component {
|
|
|
6635
6947
|
class: "zx-select__input",
|
|
6636
6948
|
type: "text",
|
|
6637
6949
|
role: "combobox",
|
|
6950
|
+
ariaLabel: String(this.options.label || this.options.placeholder || "Select"),
|
|
6638
6951
|
autocomplete: "off",
|
|
6639
6952
|
spellcheck: false,
|
|
6640
6953
|
ariaExpanded: "false",
|
|
@@ -7553,7 +7866,10 @@ function registerSelectFieldAdapter() {
|
|
|
7553
7866
|
Field.register("zxselect", (field, options) => {
|
|
7554
7867
|
const props = options.props ?? {};
|
|
7555
7868
|
const preset = props.preset;
|
|
7556
|
-
const selectOptions = { ...props, value: options.value };
|
|
7869
|
+
const selectOptions = { ...props, value: options.value, label: options.label || props.label, placeholder: props.placeholder ?? options.placeholder };
|
|
7870
|
+
field.listen(field.el, "click", (event) => {
|
|
7871
|
+
if (event.target.closest?.(".zx-field__label")) field.adapter.focus();
|
|
7872
|
+
});
|
|
7557
7873
|
delete selectOptions.preset;
|
|
7558
7874
|
const select = field.own(preset === "priority" ? Select.priority(null, selectOptions) : preset === "status" ? Select.status(null, selectOptions) : new Select(null, selectOptions));
|
|
7559
7875
|
field.listen(select.el, "change", (event) => event.stopImmediatePropagation());
|
|
@@ -8793,7 +9109,7 @@ var Timebox = class extends Component {
|
|
|
8793
9109
|
const content = h("div", {
|
|
8794
9110
|
class: "zx-timebox__content",
|
|
8795
9111
|
role: "group",
|
|
8796
|
-
ariaLabel: this.options.seconds ? "Duration in hours, minutes, and seconds" : "Duration in hours and minutes"
|
|
9112
|
+
ariaLabel: this.options.seconds ? this._message("timebox.durationWithSeconds", "Duration in hours, minutes, and seconds") : this._message("timebox.duration", "Duration in hours and minutes")
|
|
8797
9113
|
});
|
|
8798
9114
|
this._content = content;
|
|
8799
9115
|
if (this.options.signed) {
|
|
@@ -8801,7 +9117,7 @@ var Timebox = class extends Component {
|
|
|
8801
9117
|
ref: "sign",
|
|
8802
9118
|
class: "zx-timebox__sign",
|
|
8803
9119
|
type: "button",
|
|
8804
|
-
ariaLabel: "Toggle duration sign",
|
|
9120
|
+
ariaLabel: this._message("timebox.toggleSign", "Toggle duration sign"),
|
|
8805
9121
|
ariaPressed: "false"
|
|
8806
9122
|
}, "+"));
|
|
8807
9123
|
this.listen(this.refs.sign, "click", () => {
|
|
@@ -8811,12 +9127,12 @@ var Timebox = class extends Component {
|
|
|
8811
9127
|
this._emitChange();
|
|
8812
9128
|
});
|
|
8813
9129
|
}
|
|
8814
|
-
this._addSegment(content, "hours", "Hours", false);
|
|
9130
|
+
this._addSegment(content, "hours", this._message("timebox.hours", "Hours"), false);
|
|
8815
9131
|
content.append(h("span", { class: "zx-timebox__separator", ariaHidden: "true" }, ":"));
|
|
8816
|
-
this._addSegment(content, "minutes", "Minutes", true);
|
|
9132
|
+
this._addSegment(content, "minutes", this._message("timebox.minutes", "Minutes"), true);
|
|
8817
9133
|
if (this.options.seconds) {
|
|
8818
9134
|
content.append(h("span", { class: "zx-timebox__separator", ariaHidden: "true" }, ":"));
|
|
8819
|
-
this._addSegment(content, "seconds", "Seconds", true);
|
|
9135
|
+
this._addSegment(content, "seconds", this._message("timebox.seconds", "Seconds"), true);
|
|
8820
9136
|
}
|
|
8821
9137
|
root.append(content);
|
|
8822
9138
|
this.set(this.options.value, this.options.unit, { silent: true });
|
|
@@ -8942,6 +9258,16 @@ var Timebox = class extends Component {
|
|
|
8942
9258
|
_emitChange() {
|
|
8943
9259
|
this.emit("change", { value: this.get(this.options.unit) });
|
|
8944
9260
|
}
|
|
9261
|
+
/**
|
|
9262
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
9263
|
+
* @param {string} key Message key.
|
|
9264
|
+
* @param {string} fallback English default.
|
|
9265
|
+
* @returns {string}
|
|
9266
|
+
*/
|
|
9267
|
+
_message(key, fallback) {
|
|
9268
|
+
const message = this.msg(key);
|
|
9269
|
+
return message === key ? fallback : message;
|
|
9270
|
+
}
|
|
8945
9271
|
};
|
|
8946
9272
|
function finiteNumber2(value) {
|
|
8947
9273
|
const number = Number(value);
|
|
@@ -9154,14 +9480,14 @@ var ValueList = class extends Component {
|
|
|
9154
9480
|
this._list = h("ul", {
|
|
9155
9481
|
class: "zx-value-list__list",
|
|
9156
9482
|
role: "listbox",
|
|
9157
|
-
ariaLabel: "Values",
|
|
9483
|
+
ariaLabel: this._message("valueList.values", "Values"),
|
|
9158
9484
|
ariaOrientation: "horizontal"
|
|
9159
9485
|
});
|
|
9160
9486
|
this._input = h("input", {
|
|
9161
9487
|
class: "zx-value-list__input",
|
|
9162
9488
|
type: "text",
|
|
9163
9489
|
placeholder: String(this.options.placeholder ?? ""),
|
|
9164
|
-
ariaLabel: "Add value",
|
|
9490
|
+
ariaLabel: this._message("valueList.add", "Add value"),
|
|
9165
9491
|
ariaDescribedby: instructionsId
|
|
9166
9492
|
});
|
|
9167
9493
|
this._status = h("div", {
|
|
@@ -9172,7 +9498,10 @@ var ValueList = class extends Component {
|
|
|
9172
9498
|
this._instructions = h("span", {
|
|
9173
9499
|
class: "zx-value-list__instructions",
|
|
9174
9500
|
id: instructionsId
|
|
9175
|
-
},
|
|
9501
|
+
}, this._message(
|
|
9502
|
+
"valueList.instructions",
|
|
9503
|
+
"Press Enter to add. Focus a value and press Ctrl plus Left or Right to reorder."
|
|
9504
|
+
));
|
|
9176
9505
|
this._ownedNodes.push(this._list, this._input, this._status, this._instructions);
|
|
9177
9506
|
root.append(this._list, this._input, this._status, this._instructions);
|
|
9178
9507
|
this.listen(this._input, "keydown", (event) => this._handleInputKeydown(event));
|
|
@@ -9221,13 +9550,13 @@ var ValueList = class extends Component {
|
|
|
9221
9550
|
const normalized = String(value ?? "").trim();
|
|
9222
9551
|
if (!normalized) return false;
|
|
9223
9552
|
if (this.options.unique && this._values.includes(normalized)) {
|
|
9224
|
-
this._showError("This value already exists.");
|
|
9553
|
+
this._showError(this._message("valueList.duplicate", "This value already exists."));
|
|
9225
9554
|
return false;
|
|
9226
9555
|
}
|
|
9227
9556
|
if (typeof this.options.validate === "function") {
|
|
9228
9557
|
const result = this.options.validate(normalized);
|
|
9229
9558
|
if (result !== true) {
|
|
9230
|
-
this._showError(typeof result === "string" ? result : "This value is not valid.");
|
|
9559
|
+
this._showError(typeof result === "string" ? result : this._message("valueList.invalid", "This value is not valid."));
|
|
9231
9560
|
return false;
|
|
9232
9561
|
}
|
|
9233
9562
|
}
|
|
@@ -9292,7 +9621,7 @@ var ValueList = class extends Component {
|
|
|
9292
9621
|
draggable: Boolean(this.options.sortable) && !this._disabled,
|
|
9293
9622
|
ariaSelected: "false",
|
|
9294
9623
|
ariaDisabled: String(this._disabled),
|
|
9295
|
-
ariaLabel: this.options.deletable ?
|
|
9624
|
+
ariaLabel: this.options.deletable ? this._message("valueList.removable", "%1. Press Delete to remove.", value) : value,
|
|
9296
9625
|
dataset: { index }
|
|
9297
9626
|
}, h("span", { class: "zx-value-list__value" }, value), this.options.deletable ? h("span", {
|
|
9298
9627
|
class: "zx-value-list__remove",
|
|
@@ -9388,6 +9717,17 @@ var ValueList = class extends Component {
|
|
|
9388
9717
|
this._status.textContent = message;
|
|
9389
9718
|
this._input.setAttribute("aria-invalid", "true");
|
|
9390
9719
|
}
|
|
9720
|
+
/**
|
|
9721
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
9722
|
+
* @param {string} key Message key.
|
|
9723
|
+
* @param {string} fallback Built-in text, with `%1`-style placeholders.
|
|
9724
|
+
* @param {...unknown} args Interpolation values.
|
|
9725
|
+
* @returns {string}
|
|
9726
|
+
*/
|
|
9727
|
+
_message(key, fallback, ...args) {
|
|
9728
|
+
const message = this.msg(key, ...args);
|
|
9729
|
+
return message === key ? printf(fallback, args) : message;
|
|
9730
|
+
}
|
|
9391
9731
|
/** @returns {void} */
|
|
9392
9732
|
destroy() {
|
|
9393
9733
|
for (const node of this._ownedNodes ?? []) node.remove();
|
|
@@ -9631,6 +9971,8 @@ var Table = class extends Component {
|
|
|
9631
9971
|
height: null,
|
|
9632
9972
|
emptyText: null,
|
|
9633
9973
|
rowClass: null,
|
|
9974
|
+
rowKind: null,
|
|
9975
|
+
rowKinds: null,
|
|
9634
9976
|
zebra: true,
|
|
9635
9977
|
editMode: false,
|
|
9636
9978
|
editTrigger: "double",
|
|
@@ -9660,6 +10002,10 @@ var Table = class extends Component {
|
|
|
9660
10002
|
this._original = created ? null : snapshotTarget(root);
|
|
9661
10003
|
this._columns = normalizeTableColumns(this.options.columns);
|
|
9662
10004
|
this._data = Array.isArray(this.options.data) ? [...this.options.data] : [];
|
|
10005
|
+
this._rowKind = normalizeRowKind(this.options.rowKind);
|
|
10006
|
+
this._rowKinds = normalizeRowKinds(this.options.rowKinds);
|
|
10007
|
+
this._spanning = this._hasSpanningRow();
|
|
10008
|
+
this._sortWarned = false;
|
|
9663
10009
|
this._selected = /* @__PURE__ */ new Set();
|
|
9664
10010
|
this._selectionAnchorId = null;
|
|
9665
10011
|
this._sort = normalizeSort(this.options.sort, this._columns);
|
|
@@ -10035,6 +10381,7 @@ var Table = class extends Component {
|
|
|
10035
10381
|
const row = this.getRow(id);
|
|
10036
10382
|
const target = this.getRow(targetId);
|
|
10037
10383
|
if (!row || !target || Object.is(id, targetId)) return this;
|
|
10384
|
+
if (this._isSpanningRow(row)) return this;
|
|
10038
10385
|
const next = reorderTableRows(this._data, this.options.rowId, id, targetId, position2, this._hierarchy?.parentId);
|
|
10039
10386
|
if (!next) return this;
|
|
10040
10387
|
const event = this.emit("rowmove", { row, id, target, targetId, position: position2 });
|
|
@@ -10071,6 +10418,10 @@ var Table = class extends Component {
|
|
|
10071
10418
|
/**
|
|
10072
10419
|
* Activates a column sort. Local mode stably reorders data; server mode only updates the
|
|
10073
10420
|
* header state and emits the request event.
|
|
10421
|
+
*
|
|
10422
|
+
* Inert while the data holds a spanning row: a sort would scatter the positions out of the
|
|
10423
|
+
* sections that group them, in either sort mode. The header withholds its controls for the same
|
|
10424
|
+
* reason, so nothing on screen invites the call.
|
|
10074
10425
|
* @param {string} id Column id.
|
|
10075
10426
|
* @param {TableSortDirection} [dir] Direction; omitted toggles the current column.
|
|
10076
10427
|
* @param {{silent?: boolean}} [options={}] Event options.
|
|
@@ -10079,6 +10430,13 @@ var Table = class extends Component {
|
|
|
10079
10430
|
* @fires Table#editcancel
|
|
10080
10431
|
*/
|
|
10081
10432
|
setSort(id, dir, options = {}) {
|
|
10433
|
+
if (this._spanning) {
|
|
10434
|
+
if (!this._sortWarned) {
|
|
10435
|
+
this._sortWarned = true;
|
|
10436
|
+
console.warn("[zx.Table] setSort() is inert while the data contains spanning rowKinds rows: sorting would scatter the rows out of the sections that group them.");
|
|
10437
|
+
}
|
|
10438
|
+
return this;
|
|
10439
|
+
}
|
|
10082
10440
|
this._abortEdit({ focus: false });
|
|
10083
10441
|
const column = this._columns.find((candidate) => candidate.id === id);
|
|
10084
10442
|
if (!column) throw new RangeError(`Unknown table column: ${id}`);
|
|
@@ -10130,7 +10488,7 @@ var Table = class extends Component {
|
|
|
10130
10488
|
*/
|
|
10131
10489
|
setSelection(ids) {
|
|
10132
10490
|
if (!Array.isArray(ids)) throw new TypeError("Table selection must be an array of row ids");
|
|
10133
|
-
const valid =
|
|
10491
|
+
const valid = this._selectableIds();
|
|
10134
10492
|
const next = /* @__PURE__ */ new Set();
|
|
10135
10493
|
if (this.options.selectable !== false) {
|
|
10136
10494
|
for (const id of ids) {
|
|
@@ -10242,6 +10600,7 @@ var Table = class extends Component {
|
|
|
10242
10600
|
if (!requested) return this;
|
|
10243
10601
|
const current = this._data.find((candidate) => Object.is(this._idFor(candidate), rowId));
|
|
10244
10602
|
if (current === void 0) return this;
|
|
10603
|
+
if (this._isSpanningRow(current)) return this;
|
|
10245
10604
|
const column = this._editMode === "row" && this._hiddenColumns.has(requested.id) ? this._visibleColumns().find((candidate) => resolveEditable(candidate, current) !== false) ?? null : requested;
|
|
10246
10605
|
if (!column || resolveEditable(column, current) === false) return this;
|
|
10247
10606
|
const activeColumnId = column.id;
|
|
@@ -10530,6 +10889,41 @@ var Table = class extends Component {
|
|
|
10530
10889
|
_visibleColumns() {
|
|
10531
10890
|
return this._columns.filter((column) => !this._hiddenColumns.has(column.id));
|
|
10532
10891
|
}
|
|
10892
|
+
/**
|
|
10893
|
+
* Whether a row draws as one cell across the table instead of as a record.
|
|
10894
|
+
* @param {TableRow} row Row to classify.
|
|
10895
|
+
* @returns {boolean}
|
|
10896
|
+
*/
|
|
10897
|
+
_isSpanningRow(row) {
|
|
10898
|
+
if (this._rowKind === null || this._rowKinds === null) return false;
|
|
10899
|
+
return isSpanningRow(row, this._rowKind, this._rowKinds);
|
|
10900
|
+
}
|
|
10901
|
+
/**
|
|
10902
|
+
* Whether any row in the current data — not only the rendered prefix — spans. This is what
|
|
10903
|
+
* withholds the sort controls, and the reader must not be offered a control that the next
|
|
10904
|
+
* `growBy()` would have to take away again.
|
|
10905
|
+
* @returns {boolean}
|
|
10906
|
+
*/
|
|
10907
|
+
_hasSpanningRow() {
|
|
10908
|
+
return hasSpanningRow(this._data, this._rowKind, this._rowKinds);
|
|
10909
|
+
}
|
|
10910
|
+
/**
|
|
10911
|
+
* How many cells one row occupies: every visible column plus the structural columns the table
|
|
10912
|
+
* renders beside them. Shared by the spanning cell and the empty-state cell so the two can never
|
|
10913
|
+
* disagree about the table's width.
|
|
10914
|
+
* @returns {number}
|
|
10915
|
+
*/
|
|
10916
|
+
_spanColspan() {
|
|
10917
|
+
return tableSpanColspan(this._visibleColumns().length, {
|
|
10918
|
+
selectable: this.options.selectable,
|
|
10919
|
+
rowReorder: this.options.rowReorder
|
|
10920
|
+
});
|
|
10921
|
+
}
|
|
10922
|
+
/** @returns {TableRow[]} Rendered rows that can carry a selection; spanning rows cannot. */
|
|
10923
|
+
_selectableData() {
|
|
10924
|
+
const visible = this._visibleData();
|
|
10925
|
+
return this._rowKind === null ? visible : visible.filter((row) => !this._isSpanningRow(row));
|
|
10926
|
+
}
|
|
10533
10927
|
/** @returns {HTMLElement} */
|
|
10534
10928
|
_createColumnControls() {
|
|
10535
10929
|
const list = h("div", { class: "zx-table__column-list" });
|
|
@@ -10542,7 +10936,12 @@ var Table = class extends Component {
|
|
|
10542
10936
|
const details = h(
|
|
10543
10937
|
"details",
|
|
10544
10938
|
{ class: "zx-table__column-controls" },
|
|
10545
|
-
h(
|
|
10939
|
+
h(
|
|
10940
|
+
"summary",
|
|
10941
|
+
{ class: "zx-button zx-button--sm" },
|
|
10942
|
+
icon("fields", { size: 13 }),
|
|
10943
|
+
this._message("table.columns", "Columns", [])
|
|
10944
|
+
),
|
|
10546
10945
|
list
|
|
10547
10946
|
);
|
|
10548
10947
|
this._renderColumnControls();
|
|
@@ -10577,7 +10976,7 @@ var Table = class extends Component {
|
|
|
10577
10976
|
{
|
|
10578
10977
|
class: "zx-table__column-order",
|
|
10579
10978
|
role: "group",
|
|
10580
|
-
ariaLabel:
|
|
10979
|
+
ariaLabel: this._message("table.moveColumn", "Move %1", [column.label])
|
|
10581
10980
|
},
|
|
10582
10981
|
h("button", {
|
|
10583
10982
|
class: "zx-table__column-move",
|
|
@@ -10850,9 +11249,9 @@ var Table = class extends Component {
|
|
|
10850
11249
|
row.append(selectionHeader);
|
|
10851
11250
|
this.listen(this._selectAll, "click", () => {
|
|
10852
11251
|
if (this._selectAll.checked) {
|
|
10853
|
-
for (const dataRow of this.
|
|
11252
|
+
for (const dataRow of this._selectableData()) this._selected.add(this._idFor(dataRow));
|
|
10854
11253
|
} else {
|
|
10855
|
-
for (const dataRow of this.
|
|
11254
|
+
for (const dataRow of this._selectableData()) this._selected.delete(this._idFor(dataRow));
|
|
10856
11255
|
}
|
|
10857
11256
|
this._selectionAnchorId = null;
|
|
10858
11257
|
this._syncSelection();
|
|
@@ -10862,12 +11261,13 @@ var Table = class extends Component {
|
|
|
10862
11261
|
this._selectAll = null;
|
|
10863
11262
|
}
|
|
10864
11263
|
this._headers = /* @__PURE__ */ new Map();
|
|
11264
|
+
this._headerSpanning = this._spanning;
|
|
10865
11265
|
for (const column of this._visibleColumns()) {
|
|
10866
11266
|
const th = h("th", { scope: "col" });
|
|
10867
11267
|
const align = column.align ?? (isNumericColumn(column) ? "end" : null);
|
|
10868
11268
|
if (align) th.dataset.align = align;
|
|
10869
11269
|
if (column.headerTitle) th.title = column.headerTitle;
|
|
10870
|
-
if (column.sortable) {
|
|
11270
|
+
if (column.sortable && !this._spanning) {
|
|
10871
11271
|
const button = h("button", {
|
|
10872
11272
|
class: "zx-table__sort-button",
|
|
10873
11273
|
type: "button"
|
|
@@ -10889,6 +11289,8 @@ var Table = class extends Component {
|
|
|
10889
11289
|
/** @returns {void} @fires Table#editcancel */
|
|
10890
11290
|
_renderBody() {
|
|
10891
11291
|
this._abortEdit({ focus: false });
|
|
11292
|
+
this._spanning = this._hasSpanningRow();
|
|
11293
|
+
if (this._headers && this._spanning !== this._headerSpanning) this._renderHeader();
|
|
10892
11294
|
const fragment2 = document.createDocumentFragment();
|
|
10893
11295
|
this._rowMeta = /* @__PURE__ */ new WeakMap();
|
|
10894
11296
|
this._rowElements = /* @__PURE__ */ new Map();
|
|
@@ -10900,10 +11302,7 @@ var Table = class extends Component {
|
|
|
10900
11302
|
fragment2.append(h(
|
|
10901
11303
|
"tr",
|
|
10902
11304
|
{ class: "zx-table__empty-row" },
|
|
10903
|
-
h("td", {
|
|
10904
|
-
class: "zx-table__empty",
|
|
10905
|
-
colspan: this._visibleColumns().length + (this.options.selectable === "multi" ? 1 : 0) + (this.options.rowReorder ? 1 : 0)
|
|
10906
|
-
}, this._emptyContent())
|
|
11305
|
+
h("td", { class: "zx-table__empty", colspan: this._spanColspan() }, this._emptyContent())
|
|
10907
11306
|
));
|
|
10908
11307
|
} else {
|
|
10909
11308
|
this._visibleEntries().forEach((entry, visibleIndex) => {
|
|
@@ -10946,7 +11345,14 @@ var Table = class extends Component {
|
|
|
10946
11345
|
if (this._growStep) tr.setAttribute("aria-rowindex", String(tree.visibleIndex + 2));
|
|
10947
11346
|
const rowClass = typeof this.options.rowClass === "function" ? this.options.rowClass(row) : "";
|
|
10948
11347
|
if (rowClass) tr.classList.add(...String(rowClass).split(/\s+/).filter(Boolean));
|
|
10949
|
-
|
|
11348
|
+
const kind = this._rowKind === null ? null : resolveRowKind(row, this._rowKind);
|
|
11349
|
+
const kindSpec = kind === null ? null : resolveRowKindSpec(this._rowKinds, kind);
|
|
11350
|
+
const spanning = Boolean(kindSpec?.span);
|
|
11351
|
+
if (kind !== null) tr.dataset.rowKind = kind;
|
|
11352
|
+
if (kindSpec?.class) tr.classList.add(...String(kindSpec.class).split(/\s+/).filter(Boolean));
|
|
11353
|
+
if (this.options.selectable !== false && !spanning) {
|
|
11354
|
+
tr.setAttribute("aria-selected", String(this._selected.has(id)));
|
|
11355
|
+
}
|
|
10950
11356
|
if (this._hierarchy) {
|
|
10951
11357
|
tr.setAttribute("aria-level", String(tree.depth + 1));
|
|
10952
11358
|
if (tree.hasChildren) tr.setAttribute("aria-expanded", String(this._expanded.has(id)));
|
|
@@ -10955,6 +11361,23 @@ var Table = class extends Component {
|
|
|
10955
11361
|
const elements = this._rowElements.get(id) ?? [];
|
|
10956
11362
|
elements.push(tr);
|
|
10957
11363
|
this._rowElements.set(id, elements);
|
|
11364
|
+
if (spanning) {
|
|
11365
|
+
tr.dataset.span = "true";
|
|
11366
|
+
const cell = (
|
|
11367
|
+
/** @type {HTMLTableCellElement} */
|
|
11368
|
+
h("th", {
|
|
11369
|
+
class: "zx-table__section-cell",
|
|
11370
|
+
scope: "colgroup",
|
|
11371
|
+
colspan: this._spanColspan()
|
|
11372
|
+
})
|
|
11373
|
+
);
|
|
11374
|
+
const content = spanRowContent(row, kindSpec, this._visibleColumns(), index);
|
|
11375
|
+
if (content && typeof content === "object" && typeof content.nodeType === "number") {
|
|
11376
|
+
cell.append(content);
|
|
11377
|
+
} else if (content != null) cell.append(document.createTextNode(String(content)));
|
|
11378
|
+
tr.append(cell);
|
|
11379
|
+
return tr;
|
|
11380
|
+
}
|
|
10958
11381
|
if (this.options.rowReorder) {
|
|
10959
11382
|
const handle = h("button", {
|
|
10960
11383
|
class: "zx-table__row-handle",
|
|
@@ -11073,7 +11496,7 @@ var Table = class extends Component {
|
|
|
11073
11496
|
}
|
|
11074
11497
|
}
|
|
11075
11498
|
this.emit("rowclick", { ...meta, event });
|
|
11076
|
-
if (this.options.selectable === "single" && !this._selected.has(meta.id)) {
|
|
11499
|
+
if (this.options.selectable === "single" && !this._selected.has(meta.id) && !this._isSpanningRow(meta.row)) {
|
|
11077
11500
|
this._selected = /* @__PURE__ */ new Set([meta.id]);
|
|
11078
11501
|
this._selectionAnchorId = meta.id;
|
|
11079
11502
|
this._syncSelection();
|
|
@@ -11416,6 +11839,7 @@ var Table = class extends Component {
|
|
|
11416
11839
|
if (row < 0 || row >= visible.length) return null;
|
|
11417
11840
|
const candidateRow = visible[row];
|
|
11418
11841
|
const candidateColumn = columns[column];
|
|
11842
|
+
if (this._isSpanningRow(candidateRow)) continue;
|
|
11419
11843
|
if (resolveEditable(candidateColumn, candidateRow) !== false) {
|
|
11420
11844
|
return {
|
|
11421
11845
|
id: this._idFor(candidateRow),
|
|
@@ -11497,6 +11921,7 @@ var Table = class extends Component {
|
|
|
11497
11921
|
const start = Math.min(anchorIndex, currentIndex);
|
|
11498
11922
|
const end = Math.max(anchorIndex, currentIndex);
|
|
11499
11923
|
for (let index = start; index <= end; index += 1) {
|
|
11924
|
+
if (this._isSpanningRow(visible[index])) continue;
|
|
11500
11925
|
const id = this._idFor(visible[index]);
|
|
11501
11926
|
if (checked) this._selected.add(id);
|
|
11502
11927
|
else this._selected.delete(id);
|
|
@@ -11515,6 +11940,7 @@ var Table = class extends Component {
|
|
|
11515
11940
|
for (const [id, rows] of this._rowElements) {
|
|
11516
11941
|
const selected = this._selected.has(id);
|
|
11517
11942
|
for (const row of rows) {
|
|
11943
|
+
if (row.hasAttribute("data-span")) continue;
|
|
11518
11944
|
row.setAttribute("aria-selected", String(selected));
|
|
11519
11945
|
const checkbox = row.querySelector(".zx-table__row-checkbox");
|
|
11520
11946
|
if (checkbox) checkbox.checked = selected;
|
|
@@ -11525,7 +11951,7 @@ var Table = class extends Component {
|
|
|
11525
11951
|
/** @returns {void} */
|
|
11526
11952
|
_syncSelectAll() {
|
|
11527
11953
|
if (!this._selectAll) return;
|
|
11528
|
-
const visible = this.
|
|
11954
|
+
const visible = this._selectableData();
|
|
11529
11955
|
const selectedRows = visible.reduce(
|
|
11530
11956
|
(count, row) => count + Number(this._selected.has(this._idFor(row))),
|
|
11531
11957
|
0
|
|
@@ -11538,13 +11964,15 @@ var Table = class extends Component {
|
|
|
11538
11964
|
_syncSortHeader() {
|
|
11539
11965
|
if (!this._headers) return;
|
|
11540
11966
|
for (const [id, header] of this._headers) {
|
|
11541
|
-
if (this._sort?.id === id)
|
|
11542
|
-
|
|
11967
|
+
if (!this._spanning && this._sort?.id === id) {
|
|
11968
|
+
header.setAttribute("aria-sort", this._sort.dir === "asc" ? "ascending" : "descending");
|
|
11969
|
+
} else header.removeAttribute("aria-sort");
|
|
11543
11970
|
}
|
|
11544
11971
|
}
|
|
11545
11972
|
/** @returns {void} */
|
|
11546
11973
|
_sortData() {
|
|
11547
|
-
|
|
11974
|
+
this._spanning = this._hasSpanningRow();
|
|
11975
|
+
if (!this._sort || this._spanning) return;
|
|
11548
11976
|
const column = this._columns.find((candidate) => candidate.id === this._sort.id);
|
|
11549
11977
|
if (!column) return;
|
|
11550
11978
|
const getValue = typeof column.sortValue === "function" ? column.sortValue : (row) => row?.[column.id];
|
|
@@ -11577,9 +12005,17 @@ var Table = class extends Component {
|
|
|
11577
12005
|
const valid = new Set(branches);
|
|
11578
12006
|
for (const id of this._expanded) if (!valid.has(id)) this._expanded.delete(id);
|
|
11579
12007
|
}
|
|
12008
|
+
/** @returns {Set<unknown>} Ids of every row in the data that may hold a selection. */
|
|
12009
|
+
_selectableIds() {
|
|
12010
|
+
const ids = /* @__PURE__ */ new Set();
|
|
12011
|
+
for (const row of this._data) {
|
|
12012
|
+
if (!this._isSpanningRow(row)) ids.add(this._idFor(row));
|
|
12013
|
+
}
|
|
12014
|
+
return ids;
|
|
12015
|
+
}
|
|
11580
12016
|
/** @returns {boolean} Whether selection changed. */
|
|
11581
12017
|
_pruneSelection() {
|
|
11582
|
-
const valid =
|
|
12018
|
+
const valid = this._selectableIds();
|
|
11583
12019
|
const previousSize = this._selected.size;
|
|
11584
12020
|
for (const id of this._selected) if (!valid.has(id)) this._selected.delete(id);
|
|
11585
12021
|
if (!valid.has(this._selectionAnchorId)) this._selectionAnchorId = null;
|
|
@@ -11599,6 +12035,34 @@ var Table = class extends Component {
|
|
|
11599
12035
|
this.emit("datachange", { rows: this.getData() });
|
|
11600
12036
|
}
|
|
11601
12037
|
};
|
|
12038
|
+
function resolveRowKind(row, rowKind) {
|
|
12039
|
+
if (rowKind == null || rowKind === "") return null;
|
|
12040
|
+
const raw2 = typeof rowKind === "function" ? rowKind(row) : row?.[rowKind];
|
|
12041
|
+
return raw2 == null ? null : String(raw2);
|
|
12042
|
+
}
|
|
12043
|
+
function resolveRowKindSpec(rowKinds, kind) {
|
|
12044
|
+
if (kind === null || rowKinds == null || typeof rowKinds !== "object") return null;
|
|
12045
|
+
if (!Object.prototype.hasOwnProperty.call(rowKinds, kind)) return null;
|
|
12046
|
+
const spec = rowKinds[kind];
|
|
12047
|
+
return spec && typeof spec === "object" ? spec : null;
|
|
12048
|
+
}
|
|
12049
|
+
function isSpanningRow(row, rowKind, rowKinds) {
|
|
12050
|
+
return Boolean(resolveRowKindSpec(rowKinds, resolveRowKind(row, rowKind))?.span);
|
|
12051
|
+
}
|
|
12052
|
+
function hasSpanningRow(rows, rowKind, rowKinds) {
|
|
12053
|
+
if (!Array.isArray(rows) || rowKind == null || rowKinds == null) return false;
|
|
12054
|
+
return rows.some((row) => isSpanningRow(row, rowKind, rowKinds));
|
|
12055
|
+
}
|
|
12056
|
+
function tableSpanColspan(columnCount, structure = {}) {
|
|
12057
|
+
const columns = Number.isFinite(Number(columnCount)) ? Math.max(0, Math.trunc(Number(columnCount))) : 0;
|
|
12058
|
+
const extras = (structure.selectable === "multi" ? 1 : 0) + (structure.rowReorder ? 1 : 0);
|
|
12059
|
+
return Math.max(1, columns + extras);
|
|
12060
|
+
}
|
|
12061
|
+
function spanRowContent(row, spec, visibleColumns, index = 0) {
|
|
12062
|
+
if (typeof spec?.render === "function") return spec.render(row, index);
|
|
12063
|
+
const first = visibleColumns?.[0];
|
|
12064
|
+
return first ? row?.[first.id] : null;
|
|
12065
|
+
}
|
|
11602
12066
|
function formatTableCell(column, row, index = 0) {
|
|
11603
12067
|
if (typeof column?.render === "function") return column.render(row, index);
|
|
11604
12068
|
const value = row?.[column?.id];
|
|
@@ -11827,6 +12291,20 @@ function normalizeHierarchy(option, columns) {
|
|
|
11827
12291
|
if (!column) return null;
|
|
11828
12292
|
return { ...option, parentId, column };
|
|
11829
12293
|
}
|
|
12294
|
+
function normalizeRowKind(option) {
|
|
12295
|
+
if (typeof option === "function") return (
|
|
12296
|
+
/** @type {(row: TableRow) => unknown} */
|
|
12297
|
+
option
|
|
12298
|
+
);
|
|
12299
|
+
return typeof option === "string" && option !== "" ? option : null;
|
|
12300
|
+
}
|
|
12301
|
+
function normalizeRowKinds(option) {
|
|
12302
|
+
if (!option || typeof option !== "object" || Array.isArray(option)) return null;
|
|
12303
|
+
return (
|
|
12304
|
+
/** @type {Record<string, TableRowKind>} */
|
|
12305
|
+
option
|
|
12306
|
+
);
|
|
12307
|
+
}
|
|
11830
12308
|
function initialExpanded(option) {
|
|
11831
12309
|
return new Set(Array.isArray(option) ? option : []);
|
|
11832
12310
|
}
|
|
@@ -12063,14 +12541,20 @@ var Launcher = class extends Component {
|
|
|
12063
12541
|
debounce: 250,
|
|
12064
12542
|
minQuery: 0,
|
|
12065
12543
|
maxResults: 100,
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12544
|
+
/*
|
|
12545
|
+
* The six labels default to null rather than to their English text so that an application
|
|
12546
|
+
* which installs a translator and passes no labels still gets a translated launcher. The
|
|
12547
|
+
* documented default is what `_message()` falls back to, so an untranslated application
|
|
12548
|
+
* renders exactly the same words as before.
|
|
12549
|
+
*/
|
|
12550
|
+
placeholder: null,
|
|
12551
|
+
label: null,
|
|
12552
|
+
closeLabel: null,
|
|
12553
|
+
resultsLabel: null,
|
|
12554
|
+
emptyText: null,
|
|
12555
|
+
loadingText: null,
|
|
12072
12556
|
shortcut: "mod+k",
|
|
12073
|
-
hints:
|
|
12557
|
+
hints: null,
|
|
12074
12558
|
scope: null
|
|
12075
12559
|
};
|
|
12076
12560
|
/**
|
|
@@ -12109,6 +12593,7 @@ var Launcher = class extends Component {
|
|
|
12109
12593
|
this._busy = false;
|
|
12110
12594
|
this._destroyed = false;
|
|
12111
12595
|
const listId = uid("zx-launcher-results");
|
|
12596
|
+
const label = String(this.options.label ?? this._message("launcher.label", "Launcher"));
|
|
12112
12597
|
const input = h("input", {
|
|
12113
12598
|
ref: "input",
|
|
12114
12599
|
class: "zx-launcher__input",
|
|
@@ -12119,15 +12604,15 @@ var Launcher = class extends Component {
|
|
|
12119
12604
|
ariaAutocomplete: "list",
|
|
12120
12605
|
ariaControls: listId,
|
|
12121
12606
|
ariaExpanded: "false",
|
|
12122
|
-
ariaLabel:
|
|
12123
|
-
placeholder: this.options.placeholder,
|
|
12607
|
+
ariaLabel: label,
|
|
12608
|
+
placeholder: this.options.placeholder ?? this._message("launcher.placeholder", "Search applications and records"),
|
|
12124
12609
|
value: this._query
|
|
12125
12610
|
});
|
|
12126
12611
|
const close = h("button", {
|
|
12127
12612
|
ref: "close",
|
|
12128
12613
|
class: "zx-icon-btn zx-launcher__close",
|
|
12129
12614
|
type: "button",
|
|
12130
|
-
ariaLabel: this.options.closeLabel
|
|
12615
|
+
ariaLabel: this.options.closeLabel ?? this._message("launcher.close", "Close launcher")
|
|
12131
12616
|
}, icon("x"));
|
|
12132
12617
|
const status = h("div", {
|
|
12133
12618
|
ref: "status",
|
|
@@ -12140,14 +12625,18 @@ var Launcher = class extends Component {
|
|
|
12140
12625
|
class: "zx-launcher__results",
|
|
12141
12626
|
id: listId,
|
|
12142
12627
|
role: "listbox",
|
|
12143
|
-
ariaLabel: this.options.resultsLabel
|
|
12628
|
+
ariaLabel: this.options.resultsLabel ?? this._message("launcher.results", "Launcher results")
|
|
12144
12629
|
});
|
|
12145
12630
|
const shortcut = this.options.shortcut === "mod+k" ? h("kbd", {
|
|
12146
12631
|
class: "zx-launcher__shortcut",
|
|
12147
12632
|
ariaHidden: "true"
|
|
12148
12633
|
}, launcherShortcutLabel()) : null;
|
|
12149
|
-
const footer = launcherHints(this.options.hints
|
|
12150
|
-
|
|
12634
|
+
const footer = launcherHints(this.options.hints, {
|
|
12635
|
+
move: this._message("launcher.hintMove", "Move"),
|
|
12636
|
+
open: this._message("launcher.hintOpen", "Open"),
|
|
12637
|
+
close: this._message("launcher.hintClose", "Close")
|
|
12638
|
+
});
|
|
12639
|
+
dialog.setAttribute("aria-label", label);
|
|
12151
12640
|
dialog.replaceChildren(
|
|
12152
12641
|
h(
|
|
12153
12642
|
"div",
|
|
@@ -12439,9 +12928,13 @@ var Launcher = class extends Component {
|
|
|
12439
12928
|
}
|
|
12440
12929
|
/** @returns {void} */
|
|
12441
12930
|
_renderStatus() {
|
|
12442
|
-
if (this._busy)
|
|
12443
|
-
|
|
12444
|
-
else this.
|
|
12931
|
+
if (this._busy) {
|
|
12932
|
+
this.refs.status.textContent = String(this.options.loadingText ?? this._message("launcher.loading", "Searching\u2026"));
|
|
12933
|
+
} else if (this._results.length === 0) {
|
|
12934
|
+
this.refs.status.textContent = String(this.options.emptyText ?? this._message("launcher.empty", "No results"));
|
|
12935
|
+
} else {
|
|
12936
|
+
this.refs.status.textContent = "";
|
|
12937
|
+
}
|
|
12445
12938
|
this.refs.status.hidden = !this.refs.status.textContent;
|
|
12446
12939
|
}
|
|
12447
12940
|
/** @returns {void} */
|
|
@@ -12534,6 +13027,16 @@ var Launcher = class extends Component {
|
|
|
12534
13027
|
event.preventDefault();
|
|
12535
13028
|
this.open();
|
|
12536
13029
|
}
|
|
13030
|
+
/**
|
|
13031
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
13032
|
+
* @param {string} key Message key.
|
|
13033
|
+
* @param {string} fallback English default.
|
|
13034
|
+
* @returns {string}
|
|
13035
|
+
*/
|
|
13036
|
+
_message(key, fallback) {
|
|
13037
|
+
const message = this.msg(key);
|
|
13038
|
+
return message === key ? fallback : message;
|
|
13039
|
+
}
|
|
12537
13040
|
};
|
|
12538
13041
|
function launcherShortcutLabel() {
|
|
12539
13042
|
const platform = String(
|
|
@@ -12542,15 +13045,15 @@ function launcherShortcutLabel() {
|
|
|
12542
13045
|
);
|
|
12543
13046
|
return /mac|iphone|ipad/i.test(platform) ? "\u2318 K" : "Ctrl K";
|
|
12544
13047
|
}
|
|
12545
|
-
function launcherHints(hints) {
|
|
13048
|
+
function launcherHints(hints, defaults) {
|
|
12546
13049
|
if (hints === false) return null;
|
|
12547
13050
|
const labels = hints && typeof hints === "object" ? hints : {};
|
|
12548
13051
|
return h(
|
|
12549
13052
|
"footer",
|
|
12550
13053
|
{ class: "zx-launcher__hints", ariaHidden: "true" },
|
|
12551
|
-
h("span", {}, h("kbd", {}, "\u2191\u2193\u2190\u2192"), labels.move ??
|
|
12552
|
-
h("span", {}, h("kbd", {}, "\u21B5"), labels.open ??
|
|
12553
|
-
h("span", {}, h("kbd", {}, "Esc"), labels.close ??
|
|
13054
|
+
h("span", {}, h("kbd", {}, "\u2191\u2193\u2190\u2192"), labels.move ?? defaults.move),
|
|
13055
|
+
h("span", {}, h("kbd", {}, "\u21B5"), labels.open ?? defaults.open),
|
|
13056
|
+
h("span", {}, h("kbd", {}, "Esc"), labels.close ?? defaults.close)
|
|
12554
13057
|
);
|
|
12555
13058
|
}
|
|
12556
13059
|
function launcherItemIcon(item) {
|
|
@@ -12970,8 +13473,8 @@ var Message = class _Message extends Component {
|
|
|
12970
13473
|
const close = h("button", {
|
|
12971
13474
|
class: "zx-icon-btn zx-message__close",
|
|
12972
13475
|
type: "button",
|
|
12973
|
-
ariaLabel: "Close message",
|
|
12974
|
-
title: "Close"
|
|
13476
|
+
ariaLabel: this._message("message.close", "Close message"),
|
|
13477
|
+
title: this._message("message.closeTitle", "Close")
|
|
12975
13478
|
}, icon("x", { size: 14 }));
|
|
12976
13479
|
node.append(close);
|
|
12977
13480
|
this.listen(close, "click", () => this._close(entry));
|
|
@@ -13039,6 +13542,16 @@ var Message = class _Message extends Component {
|
|
|
13039
13542
|
this._entries.delete(entry);
|
|
13040
13543
|
this._queue.remove(entry);
|
|
13041
13544
|
}
|
|
13545
|
+
/**
|
|
13546
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
13547
|
+
* @param {string} key Message key.
|
|
13548
|
+
* @param {string} fallback English default.
|
|
13549
|
+
* @returns {string}
|
|
13550
|
+
*/
|
|
13551
|
+
_message(key, fallback) {
|
|
13552
|
+
const message = this.msg(key);
|
|
13553
|
+
return message === key ? fallback : message;
|
|
13554
|
+
}
|
|
13042
13555
|
/** @param {Element|string|null|undefined} scope @returns {Message} */
|
|
13043
13556
|
static #floatingRegion(scope2) {
|
|
13044
13557
|
const host = overlayHost(scope2 ?? null);
|
|
@@ -13506,7 +14019,7 @@ var Calendar = class extends Component {
|
|
|
13506
14019
|
ref: "views",
|
|
13507
14020
|
class: "zx-calendar__views",
|
|
13508
14021
|
role: "group",
|
|
13509
|
-
ariaLabel: "Calendar view"
|
|
14022
|
+
ariaLabel: this._message("calendar.viewSwitch", "Calendar view")
|
|
13510
14023
|
}, this._views.map((view) => h("button", {
|
|
13511
14024
|
type: "button",
|
|
13512
14025
|
class: "zx-calendar__view-button",
|
|
@@ -13954,7 +14467,7 @@ var Calendar = class extends Component {
|
|
|
13954
14467
|
eventCount: String(count)
|
|
13955
14468
|
},
|
|
13956
14469
|
ariaCurrent: sameCalendarDay(day, this._now()) ? "date" : null,
|
|
13957
|
-
ariaLabel:
|
|
14470
|
+
ariaLabel: this._dayCountLabel(day, count),
|
|
13958
14471
|
disabled: this.options.disabled
|
|
13959
14472
|
}, this._format(day, { day: "numeric" })));
|
|
13960
14473
|
}
|
|
@@ -14024,7 +14537,7 @@ var Calendar = class extends Component {
|
|
|
14024
14537
|
activity: String(Math.min(3, count))
|
|
14025
14538
|
},
|
|
14026
14539
|
ariaCurrent: sameCalendarDay(day, this._now()) ? "date" : null,
|
|
14027
|
-
ariaLabel:
|
|
14540
|
+
ariaLabel: this._dayCountLabel(day, count),
|
|
14028
14541
|
disabled: this.options.disabled
|
|
14029
14542
|
}, String(day.getDate())));
|
|
14030
14543
|
}
|
|
@@ -14755,6 +15268,31 @@ var Calendar = class extends Component {
|
|
|
14755
15268
|
if (!this._destroyed) this.refs.status.textContent = message;
|
|
14756
15269
|
});
|
|
14757
15270
|
}
|
|
15271
|
+
/**
|
|
15272
|
+
* Names a month or year cell by its date and how many events it holds. Singular and plural are
|
|
15273
|
+
* separate keys because a language that inflects the noun cannot reach it from one template.
|
|
15274
|
+
* @param {Date} day Day the cell stands for.
|
|
15275
|
+
* @param {number} count Events on that day.
|
|
15276
|
+
* @returns {string}
|
|
15277
|
+
*/
|
|
15278
|
+
_dayCountLabel(day, count) {
|
|
15279
|
+
const date = this._format(day, { dateStyle: "full" });
|
|
15280
|
+
return count === 1 ? this._message("calendar.dayEvent", "%1, %2 event", date, count) : this._message("calendar.dayEvents", "%1, %2 events", date, count);
|
|
15281
|
+
}
|
|
15282
|
+
/**
|
|
15283
|
+
* Resolves a message through the host translator, falling back to the built-in English text.
|
|
15284
|
+
*
|
|
15285
|
+
* Distinct from `msg()`: the built-in `msg` option answers the calendar's own vocabulary, so a
|
|
15286
|
+
* dotted key falls past it to the host translator, which is what these strings never had.
|
|
15287
|
+
* @param {string} key Message key.
|
|
15288
|
+
* @param {string} fallback Built-in text, with `%1`-style placeholders.
|
|
15289
|
+
* @param {...unknown} args Interpolation values.
|
|
15290
|
+
* @returns {string}
|
|
15291
|
+
*/
|
|
15292
|
+
_message(key, fallback, ...args) {
|
|
15293
|
+
const message = this.msg(key, ...args);
|
|
15294
|
+
return message === key ? printf(fallback, args) : message;
|
|
15295
|
+
}
|
|
14758
15296
|
};
|
|
14759
15297
|
function normalizeViews(value) {
|
|
14760
15298
|
if (!Array.isArray(value) || value.length === 0) throw new TypeError("Calendar views must be a non-empty array");
|
|
@@ -15373,6 +15911,7 @@ function isEmpty(value) {
|
|
|
15373
15911
|
function registerFieldAdapters() {
|
|
15374
15912
|
registerSelectFieldAdapter();
|
|
15375
15913
|
registerChecklistFieldAdapter();
|
|
15914
|
+
registerCodeEditorFieldAdapter();
|
|
15376
15915
|
registerDateboxFieldAdapters();
|
|
15377
15916
|
registerDatePickerFieldAdapters();
|
|
15378
15917
|
registerDateRangeFieldAdapter();
|