flexdesk 0.17.18 → 0.18.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 +53 -0
- package/README.md +1 -0
- package/css/flexdesk.css +7544 -5916
- package/css/reset.css +1 -1
- package/css/tokens.css +23 -1
- package/dist/charts.js +10 -6
- package/dist/charts.js.map +1 -1
- package/dist/chunk-5W4EEKSK.js +778 -0
- package/dist/chunk-5W4EEKSK.js.map +7 -0
- package/dist/chunk-DNJ3N4T4.js +82 -0
- package/dist/chunk-DNJ3N4T4.js.map +7 -0
- package/dist/{chunk-REJ5HLIM.js → chunk-HYJYYEPK.js} +2 -2
- package/dist/{chunk-7U4IB65H.js → chunk-LLBJ2SJH.js} +5 -3
- package/dist/{chunk-7U4IB65H.js.map → chunk-LLBJ2SJH.js.map} +1 -1
- package/dist/{chunk-7OL6F2AM.js → chunk-P74F6I6P.js} +6 -4
- package/dist/{chunk-7OL6F2AM.js.map → chunk-P74F6I6P.js.map} +1 -1
- package/dist/chunk-PAI2ZUWV.js +260 -0
- package/dist/chunk-PAI2ZUWV.js.map +7 -0
- package/dist/chunk-Q7BALEPX.js +527 -0
- package/dist/chunk-Q7BALEPX.js.map +7 -0
- package/dist/chunk-QXAOTGCC.js +40 -0
- package/dist/chunk-QXAOTGCC.js.map +7 -0
- package/dist/{chunk-XJNADRGR.js → chunk-RKVYIXDC.js} +664 -91
- package/dist/chunk-RKVYIXDC.js.map +7 -0
- package/dist/{chunk-2Z2ENHR3.js → chunk-U5GKJUOC.js} +3 -3
- package/dist/{chunk-2Z2ENHR3.js.map → chunk-U5GKJUOC.js.map} +1 -1
- package/dist/chunk-UKP22RUG.js +219 -0
- package/dist/chunk-UKP22RUG.js.map +7 -0
- package/dist/chunk-VLOAI3HS.js +43 -0
- package/dist/chunk-VLOAI3HS.js.map +7 -0
- package/dist/{chunk-WUFLGETN.js → chunk-WVFGV5FT.js} +2 -39
- package/dist/{chunk-WUFLGETN.js.map → chunk-WVFGV5FT.js.map} +3 -3
- package/dist/{chunk-PGZ4EHSE.js → chunk-ZL3VKINP.js} +41 -390
- package/dist/chunk-ZL3VKINP.js.map +7 -0
- package/dist/editor.js +3 -2
- package/dist/editor.js.map +1 -1
- package/dist/flexdesk.css +7544 -5916
- package/dist/flow.js +29 -97
- package/dist/flow.js.map +3 -3
- package/dist/git.js +1356 -0
- package/dist/git.js.map +7 -0
- package/dist/reset.css +1 -1
- package/dist/tiles.js +20 -15
- package/dist/tiles.js.map +2 -2
- package/dist/tokens.css +23 -1
- package/dist/widgets.js +3967 -1188
- package/dist/widgets.js.map +4 -4
- package/dist/wm.js +120 -32
- package/dist/wm.js.map +2 -2
- package/docs/README.md +9 -4
- package/docs/best-practices.md +2 -2
- package/docs/components/chat-shell.md +198 -0
- package/docs/components/conversation.md +10 -0
- package/docs/components/filter-builder.md +246 -0
- package/docs/components/forms-and-dialogs.md +22 -0
- package/docs/components/git.md +355 -0
- package/docs/components/input-fields.md +167 -2
- package/docs/components/keymap.md +8 -0
- package/docs/components/menus.md +82 -2
- package/docs/components/panels-and-desktops.md +16 -5
- package/docs/components/shell.md +104 -1
- package/docs/components/workspace-picker.md +149 -0
- package/docs/concepts/building-and-packaging.md +2 -2
- package/docs/concepts/packages-and-entry-points.md +14 -13
- package/docs/concepts/state-guard.md +3 -3
- package/docs/quickstart.md +1 -1
- package/git.js +13 -0
- package/package.json +6 -1
- package/src/flow/kit/dom.js +28 -119
- package/src/flow/kit/step_picker.js +1 -1
- package/src/flow/kit/value_picker.js +1 -1
- package/src/flow/outline/menu.js +1 -1
- package/src/git/diff_viewer.js +212 -0
- package/src/git/diff_window.js +51 -0
- package/src/git/git_graph.js +401 -0
- package/src/git/git_ops.js +61 -0
- package/src/git/git_panel.js +755 -0
- package/src/git/index.js +9 -0
- package/src/git/line_diff.js +202 -0
- package/src/tiles/tile_base.js +5 -4
- package/src/tiling/desktops.js +10 -8
- package/src/tiling/keymap.js +6 -5
- package/src/tiling/kind_taxonomy.js +15 -2
- package/src/tiling/shell.js +124 -17
- package/src/tiling/tile_renderer.js +2 -3
- package/src/ui/components/action_dropdown.js +4 -78
- package/src/ui/components/anchored_layer.js +255 -0
- package/src/ui/components/chat_shell.js +920 -0
- package/src/ui/components/chat_state_machine.js +223 -0
- package/src/ui/components/choice_controls.js +45 -2
- package/src/ui/components/color_field.js +3 -2
- package/src/ui/components/color_list_field.js +3 -2
- package/src/ui/components/combobox.js +422 -0
- package/src/ui/components/conversation_view.js +17 -2
- package/src/ui/components/data_table.js +2 -2
- package/src/ui/components/filter_builder.js +766 -0
- package/src/ui/components/filter_model.js +614 -0
- package/src/ui/components/managed_window.js +24 -47
- package/src/ui/components/modal.js +79 -109
- package/src/ui/components/option_list.js +160 -0
- package/src/ui/components/popover.js +94 -0
- package/src/ui/components/recent_items.js +169 -0
- package/src/ui/components/select.js +322 -0
- package/src/ui/components/tag_input.js +77 -8
- package/src/ui/components/workspace_picker.js +1155 -0
- package/src/ui/utils/fire_event.js +17 -0
- package/src/ui/utils/focusable.js +25 -0
- package/src/ui/utils/modal_host.js +27 -0
- package/widgets.js +12 -2
- package/css/base.css +0 -10547
- package/css/overrides.css +0 -2596
- package/dist/chunk-7JI7HHSY.js +0 -107
- package/dist/chunk-7JI7HHSY.js.map +0 -7
- package/dist/chunk-MIW7D6WC.js +0 -526
- package/dist/chunk-MIW7D6WC.js.map +0 -7
- package/dist/chunk-PGZ4EHSE.js.map +0 -7
- package/dist/chunk-XJNADRGR.js.map +0 -7
- /package/dist/{chunk-REJ5HLIM.js.map → chunk-HYJYYEPK.js.map} +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectFocusable,
|
|
3
|
+
isInAnchoredLayer
|
|
4
|
+
} from "./chunk-Q7BALEPX.js";
|
|
1
5
|
import {
|
|
2
6
|
getSetting
|
|
3
7
|
} from "./chunk-HNU6MM2B.js";
|
|
@@ -21,23 +25,6 @@ var DEFAULT_ICON = "web_asset";
|
|
|
21
25
|
var _zIndexCounter = 0;
|
|
22
26
|
var _activeWindows = /* @__PURE__ */ new Map();
|
|
23
27
|
var _escAnswered = /* @__PURE__ */ new WeakSet();
|
|
24
|
-
function _collectFocusable(root) {
|
|
25
|
-
if (!root) return [];
|
|
26
|
-
const sel = [
|
|
27
|
-
"a[href]",
|
|
28
|
-
"button:not([disabled])",
|
|
29
|
-
'input:not([disabled]):not([type="hidden"])',
|
|
30
|
-
"select:not([disabled])",
|
|
31
|
-
"textarea:not([disabled])",
|
|
32
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
33
|
-
].join(",");
|
|
34
|
-
return Array.from(root.querySelectorAll(sel)).filter((el2) => {
|
|
35
|
-
if (el2.hidden) return false;
|
|
36
|
-
if (el2.closest("[hidden]")) return false;
|
|
37
|
-
const r = el2.getBoundingClientRect();
|
|
38
|
-
return r.width > 0 || r.height > 0;
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
28
|
var _stateCache = null;
|
|
42
29
|
function _loadState() {
|
|
43
30
|
if (_stateCache) return _stateCache;
|
|
@@ -93,14 +80,14 @@ function _focusFirstIn(root) {
|
|
|
93
80
|
'[contenteditable="true"]',
|
|
94
81
|
'[tabindex]:not([tabindex="-1"])'
|
|
95
82
|
].join(",");
|
|
96
|
-
for (const
|
|
97
|
-
if (
|
|
83
|
+
for (const el of root.querySelectorAll(sel)) {
|
|
84
|
+
if (el.hidden || el.closest("[hidden]")) continue;
|
|
98
85
|
try {
|
|
99
|
-
|
|
86
|
+
el.focus({ preventScroll: true });
|
|
100
87
|
} catch {
|
|
101
88
|
continue;
|
|
102
89
|
}
|
|
103
|
-
if (
|
|
90
|
+
if (el.ownerDocument.activeElement === el) return true;
|
|
104
91
|
}
|
|
105
92
|
return false;
|
|
106
93
|
}
|
|
@@ -327,11 +314,15 @@ var ManagedWindow = class {
|
|
|
327
314
|
this._clearTargetProperties();
|
|
328
315
|
document.removeEventListener("keydown", this._boundOnKeyDown);
|
|
329
316
|
this._teardownContainerResizeObserver();
|
|
330
|
-
|
|
331
|
-
detail: { id: this.id, container: this.container }
|
|
332
|
-
}));
|
|
317
|
+
this._announce("managed-window-closed", { id: this.id, container: this.container });
|
|
333
318
|
this._release();
|
|
334
319
|
}
|
|
320
|
+
/** Every window event goes out on the page's window, and a window takes only
|
|
321
|
+
* an event built by its own `CustomEvent`: Node's global one is refused
|
|
322
|
+
* under jsdom, in the middle of the close that fired it. */
|
|
323
|
+
_announce(name, detail) {
|
|
324
|
+
window.dispatchEvent(new window.CustomEvent(name, { detail }));
|
|
325
|
+
}
|
|
335
326
|
/** BUG-0053. A closed window leaves the registry and lets go of what it
|
|
336
327
|
* held: its content, its DOM and every consumer callback (an `onClose`
|
|
337
328
|
* typically captures its owner). Until now the registry kept all of it
|
|
@@ -376,14 +367,12 @@ var ManagedWindow = class {
|
|
|
376
367
|
if (this.backdropElement) {
|
|
377
368
|
this.backdropElement.style.display = "none";
|
|
378
369
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
}));
|
|
370
|
+
this._announce("managed-window-minimized", {
|
|
371
|
+
id: this.id,
|
|
372
|
+
title: this.title,
|
|
373
|
+
icon: this.icon,
|
|
374
|
+
container: this.container
|
|
375
|
+
});
|
|
387
376
|
if (!this.element) return;
|
|
388
377
|
this._cancelRestoreAnimation();
|
|
389
378
|
if (!getSetting("window.animateMinimize", true)) {
|
|
@@ -484,9 +473,7 @@ var ManagedWindow = class {
|
|
|
484
473
|
}
|
|
485
474
|
this.isMinimized = false;
|
|
486
475
|
this.bringToFront();
|
|
487
|
-
|
|
488
|
-
detail: { id: this.id, container: this.container }
|
|
489
|
-
}));
|
|
476
|
+
this._announce("managed-window-restored", { id: this.id, container: this.container });
|
|
490
477
|
}
|
|
491
478
|
/**
|
|
492
479
|
* Toggle maximize state.
|
|
@@ -547,9 +534,7 @@ var ManagedWindow = class {
|
|
|
547
534
|
this.element?.classList.toggle("twm-managed-window--maximized", this.isMaximized);
|
|
548
535
|
this._applyPosition();
|
|
549
536
|
this._saveCurrentState();
|
|
550
|
-
|
|
551
|
-
detail: { id: this.id, maximized: this.isMaximized, container: this.container }
|
|
552
|
-
}));
|
|
537
|
+
this._announce("managed-window-maximized", { id: this.id, maximized: this.isMaximized, container: this.container });
|
|
553
538
|
}
|
|
554
539
|
/**
|
|
555
540
|
* Find the taskbar button for this window.
|
|
@@ -864,9 +849,7 @@ var ManagedWindow = class {
|
|
|
864
849
|
this.height = bounds.height;
|
|
865
850
|
}
|
|
866
851
|
this._applyPosition();
|
|
867
|
-
|
|
868
|
-
detail: { id: this.id, container }
|
|
869
|
-
}));
|
|
852
|
+
this._announce("managed-window-moved", { id: this.id, container });
|
|
870
853
|
return true;
|
|
871
854
|
}
|
|
872
855
|
/** R1/R3. The container this drag started in, or null when the drag did
|
|
@@ -1243,9 +1226,7 @@ var ManagedWindow = class {
|
|
|
1243
1226
|
this.height = rect.height;
|
|
1244
1227
|
this._applyPosition();
|
|
1245
1228
|
this.element?.classList.add("twm-managed-window--snapped");
|
|
1246
|
-
|
|
1247
|
-
detail: { id: this.id, zone, container: this.container }
|
|
1248
|
-
}));
|
|
1229
|
+
this._announce("managed-window-snapped", { id: this.id, zone, container: this.container });
|
|
1249
1230
|
}
|
|
1250
1231
|
/** Restore the geometry a snap replaced. Called when a snapped window is
|
|
1251
1232
|
* picked up again, which is the gesture that means "un-snap". */
|
|
@@ -1329,7 +1310,8 @@ var ManagedWindow = class {
|
|
|
1329
1310
|
}
|
|
1330
1311
|
if (topWindow !== this) return;
|
|
1331
1312
|
if (e.key === "Tab" && this.modal && this.element) {
|
|
1332
|
-
|
|
1313
|
+
if (isInAnchoredLayer(document.activeElement)) return;
|
|
1314
|
+
const focusables = collectFocusable(this.element);
|
|
1333
1315
|
if (focusables.length === 0) {
|
|
1334
1316
|
e.preventDefault();
|
|
1335
1317
|
return;
|
|
@@ -1551,6 +1533,12 @@ var ToggleField = class {
|
|
|
1551
1533
|
}
|
|
1552
1534
|
};
|
|
1553
1535
|
|
|
1536
|
+
// src/ui/utils/fire_event.js
|
|
1537
|
+
function fireEvent(target, type, init) {
|
|
1538
|
+
const view = target.ownerDocument.defaultView;
|
|
1539
|
+
target.dispatchEvent(new view.CustomEvent(type, init));
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1554
1542
|
// src/ui/components/color_field.js
|
|
1555
1543
|
var HEX_RE = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
1556
1544
|
var RGB_RE = /^rgba?\(\s*([^)]*)\)$/i;
|
|
@@ -1691,15 +1679,15 @@ var ColorField = class {
|
|
|
1691
1679
|
this.swatch = null;
|
|
1692
1680
|
this.hex = null;
|
|
1693
1681
|
}
|
|
1694
|
-
#listen(
|
|
1695
|
-
|
|
1696
|
-
this._disposers.push(() =>
|
|
1682
|
+
#listen(el, type, fn) {
|
|
1683
|
+
el.addEventListener(type, fn);
|
|
1684
|
+
this._disposers.push(() => el.removeEventListener(type, fn));
|
|
1697
1685
|
}
|
|
1698
1686
|
/** Put `text` in the box and fire the box's own events, as typing would. */
|
|
1699
1687
|
#writeBox(text, commit) {
|
|
1700
1688
|
this.hex.value = text;
|
|
1701
|
-
this.hex
|
|
1702
|
-
if (commit) this.hex
|
|
1689
|
+
fireEvent(this.hex, "input", { bubbles: true });
|
|
1690
|
+
if (commit) fireEvent(this.hex, "change", { bubbles: true });
|
|
1703
1691
|
}
|
|
1704
1692
|
/** Swatch and invalid mark follow the box; `commit === null` is silent. */
|
|
1705
1693
|
#sync(commit) {
|
|
@@ -1710,351 +1698,14 @@ var ColorField = class {
|
|
|
1710
1698
|
}
|
|
1711
1699
|
};
|
|
1712
1700
|
|
|
1713
|
-
// src/ui/components/choice_controls.js
|
|
1714
|
-
var shownValue = (v) => v === void 0 ? "" : typeof v === "string" ? v : JSON.stringify(v);
|
|
1715
|
-
function el(tag, className, text) {
|
|
1716
|
-
const n = document.createElement(tag);
|
|
1717
|
-
if (className) n.className = className;
|
|
1718
|
-
if (text !== void 0 && text !== null) n.textContent = String(text);
|
|
1719
|
-
return n;
|
|
1720
|
-
}
|
|
1721
|
-
var isGroup = (o) => o !== null && typeof o === "object" && Array.isArray(o.options) && "group" in o;
|
|
1722
|
-
function choiceOption(o) {
|
|
1723
|
-
if (o === null || typeof o !== "object") {
|
|
1724
|
-
return { value: o, label: shownValue(o), description: null, disabled: false, reason: null };
|
|
1725
|
-
}
|
|
1726
|
-
return {
|
|
1727
|
-
value: o.value,
|
|
1728
|
-
label: o.label != null ? String(o.label) : shownValue(o.value),
|
|
1729
|
-
description: o.description != null ? String(o.description) : null,
|
|
1730
|
-
disabled: Boolean(o.disabled),
|
|
1731
|
-
reason: o.reason != null && o.reason !== "" ? String(o.reason) : null
|
|
1732
|
-
};
|
|
1733
|
-
}
|
|
1734
|
-
function flatChoices(options) {
|
|
1735
|
-
const out = [];
|
|
1736
|
-
for (const o of options || []) {
|
|
1737
|
-
if (isGroup(o)) for (const inner of o.options) out.push(choiceOption(inner));
|
|
1738
|
-
else out.push(choiceOption(o));
|
|
1739
|
-
}
|
|
1740
|
-
return out;
|
|
1741
|
-
}
|
|
1742
|
-
function groupHeads(options) {
|
|
1743
|
-
const heads = /* @__PURE__ */ new Map();
|
|
1744
|
-
let at = 0;
|
|
1745
|
-
for (const o of options || []) {
|
|
1746
|
-
if (!isGroup(o)) {
|
|
1747
|
-
at += 1;
|
|
1748
|
-
continue;
|
|
1749
|
-
}
|
|
1750
|
-
if (o.options.length) heads.set(at, String(o.group ?? ""));
|
|
1751
|
-
at += o.options.length;
|
|
1752
|
-
}
|
|
1753
|
-
return heads;
|
|
1754
|
-
}
|
|
1755
|
-
var groupHeading = (text) => el("div", "twm-choice__group", text);
|
|
1756
|
-
function sameChoice(v, value, loose = false) {
|
|
1757
|
-
if (v === value) return true;
|
|
1758
|
-
if (!loose || v === void 0 || value === void 0 || v === null || value === null) return false;
|
|
1759
|
-
return String(v) === String(value);
|
|
1760
|
-
}
|
|
1761
|
-
function choiceIndex(list, v, loose = false, from = 0) {
|
|
1762
|
-
for (let i = from; i < list.length; i += 1) if (list[i].value === v) return i;
|
|
1763
|
-
if (!loose) return -1;
|
|
1764
|
-
for (let i = from; i < list.length; i += 1) if (sameChoice(list[i].value, v, true)) return i;
|
|
1765
|
-
return -1;
|
|
1766
|
-
}
|
|
1767
|
-
function findChoice(list, v, loose = false) {
|
|
1768
|
-
const i = choiceIndex(list, v, loose);
|
|
1769
|
-
return i >= 0 ? list[i] : void 0;
|
|
1770
|
-
}
|
|
1771
|
-
var optionText = (o) => o.disabled && o.reason ? `${o.label} \u2014 ${o.reason}` : o.label;
|
|
1772
|
-
function selectBox(options, value, {
|
|
1773
|
-
empty = null,
|
|
1774
|
-
label = "",
|
|
1775
|
-
notFound = (v) => `${v} (not found)`,
|
|
1776
|
-
keepMissing = true,
|
|
1777
|
-
valueAttr = "index",
|
|
1778
|
-
loose = false,
|
|
1779
|
-
className = "twm-flow-input twm-flow-input--select"
|
|
1780
|
-
} = {}) {
|
|
1781
|
-
const box = el("select", className);
|
|
1782
|
-
if (label) box.setAttribute("aria-label", label);
|
|
1783
|
-
let entries = [];
|
|
1784
|
-
const add = (parent, o) => {
|
|
1785
|
-
const attr = valueAttr === "index" ? String(entries.length) : o.value === void 0 ? "" : String(o.value);
|
|
1786
|
-
const opt = el("option", "", optionText(o));
|
|
1787
|
-
opt.value = attr;
|
|
1788
|
-
if (o.disabled) {
|
|
1789
|
-
opt.disabled = true;
|
|
1790
|
-
if (o.reason) opt.title = o.reason;
|
|
1791
|
-
}
|
|
1792
|
-
parent.appendChild(opt);
|
|
1793
|
-
entries.push(o);
|
|
1794
|
-
};
|
|
1795
|
-
const firstEnabled = () => {
|
|
1796
|
-
const i = entries.findIndex((e) => !e.disabled);
|
|
1797
|
-
return i >= 0 ? i : 0;
|
|
1798
|
-
};
|
|
1799
|
-
const select = (v) => {
|
|
1800
|
-
const start = empty !== null ? 1 : 0;
|
|
1801
|
-
const at = choiceIndex(entries, v, loose, start);
|
|
1802
|
-
if (at < 0 || entries[at].disabled || entries[at].stray) return false;
|
|
1803
|
-
box.selectedIndex = at;
|
|
1804
|
-
return true;
|
|
1805
|
-
};
|
|
1806
|
-
const place = (v) => {
|
|
1807
|
-
if (select(v)) return;
|
|
1808
|
-
if (keepMissing && v !== void 0 && v !== null && v !== "") {
|
|
1809
|
-
add(box, {
|
|
1810
|
-
value: v,
|
|
1811
|
-
label: notFound(shownValue(v)),
|
|
1812
|
-
description: null,
|
|
1813
|
-
disabled: false,
|
|
1814
|
-
reason: null,
|
|
1815
|
-
stray: true
|
|
1816
|
-
});
|
|
1817
|
-
box.selectedIndex = entries.length - 1;
|
|
1818
|
-
return;
|
|
1819
|
-
}
|
|
1820
|
-
box.selectedIndex = empty !== null ? 0 : firstEnabled();
|
|
1821
|
-
};
|
|
1822
|
-
const fill = (opts, v) => {
|
|
1823
|
-
box.replaceChildren();
|
|
1824
|
-
entries = [];
|
|
1825
|
-
if (empty !== null) add(box, {
|
|
1826
|
-
value: void 0,
|
|
1827
|
-
label: String(empty),
|
|
1828
|
-
description: null,
|
|
1829
|
-
disabled: false,
|
|
1830
|
-
reason: null
|
|
1831
|
-
});
|
|
1832
|
-
for (const o of opts || []) {
|
|
1833
|
-
if (isGroup(o)) {
|
|
1834
|
-
const g = el("optgroup");
|
|
1835
|
-
g.label = String(o.group ?? "");
|
|
1836
|
-
for (const inner of o.options) add(g, choiceOption(inner));
|
|
1837
|
-
box.appendChild(g);
|
|
1838
|
-
} else {
|
|
1839
|
-
add(box, choiceOption(o));
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
place(v);
|
|
1843
|
-
};
|
|
1844
|
-
const entry = () => box.selectedIndex < 0 ? null : entries[box.selectedIndex] ?? null;
|
|
1845
|
-
const valueOf = () => entry()?.value;
|
|
1846
|
-
fill(options, value);
|
|
1847
|
-
return {
|
|
1848
|
-
box,
|
|
1849
|
-
valueOf,
|
|
1850
|
-
entry,
|
|
1851
|
-
select,
|
|
1852
|
-
setOptions(opts, v = valueOf()) {
|
|
1853
|
-
fill(opts, v);
|
|
1854
|
-
}
|
|
1855
|
-
};
|
|
1856
|
-
}
|
|
1857
|
-
function toggleChips({
|
|
1858
|
-
options,
|
|
1859
|
-
value,
|
|
1860
|
-
label,
|
|
1861
|
-
readOnly,
|
|
1862
|
-
onChange,
|
|
1863
|
-
notFound = (v) => `${v} (not found)`,
|
|
1864
|
-
keepMissing = true,
|
|
1865
|
-
loose = false
|
|
1866
|
-
}) {
|
|
1867
|
-
const root = el("div", "twm-flow-togglechips");
|
|
1868
|
-
root.setAttribute("role", "group");
|
|
1869
|
-
if (label) root.setAttribute("aria-label", label);
|
|
1870
|
-
let shown = [];
|
|
1871
|
-
let list = [];
|
|
1872
|
-
let chosen = /* @__PURE__ */ new Set();
|
|
1873
|
-
let strays = [];
|
|
1874
|
-
const emit = () => {
|
|
1875
|
-
const out = valueOf();
|
|
1876
|
-
onChange?.(out.length ? out : void 0);
|
|
1877
|
-
};
|
|
1878
|
-
const chipFor = (text, pressed, toggle, { stray = false, reason = null, disabled = false } = {}) => {
|
|
1879
|
-
const b = el("button", `twm-flow-togglechip${stray ? " twm-flow-togglechip--missing" : ""}`, text);
|
|
1880
|
-
b.type = "button";
|
|
1881
|
-
b.setAttribute("aria-pressed", pressed ? "true" : "false");
|
|
1882
|
-
b.disabled = Boolean(readOnly) || disabled;
|
|
1883
|
-
if (reason) {
|
|
1884
|
-
b.title = reason;
|
|
1885
|
-
b.appendChild(el("span", "twm-choice__reason", reason));
|
|
1886
|
-
}
|
|
1887
|
-
b.addEventListener("click", () => {
|
|
1888
|
-
const on = toggle();
|
|
1889
|
-
b.setAttribute("aria-pressed", on ? "true" : "false");
|
|
1890
|
-
emit();
|
|
1891
|
-
});
|
|
1892
|
-
return b;
|
|
1893
|
-
};
|
|
1894
|
-
const draw = (opts, stored) => {
|
|
1895
|
-
shown = opts || [];
|
|
1896
|
-
list = flatChoices(shown);
|
|
1897
|
-
const heads = groupHeads(shown);
|
|
1898
|
-
const wanted = Array.isArray(stored) ? stored : [];
|
|
1899
|
-
const offered = (v) => {
|
|
1900
|
-
const o = findChoice(list, v, loose);
|
|
1901
|
-
return o && !o.disabled ? o : void 0;
|
|
1902
|
-
};
|
|
1903
|
-
chosen = new Set(wanted.map(offered).filter(Boolean).map((o) => o.value));
|
|
1904
|
-
strays = keepMissing ? wanted.filter((v) => !offered(v)) : [];
|
|
1905
|
-
root.replaceChildren();
|
|
1906
|
-
list.forEach((o, i) => {
|
|
1907
|
-
if (heads.has(i)) root.appendChild(groupHeading(heads.get(i)));
|
|
1908
|
-
root.appendChild(chipFor(o.label, chosen.has(o.value), () => {
|
|
1909
|
-
if (o.disabled) return false;
|
|
1910
|
-
if (chosen.has(o.value)) chosen.delete(o.value);
|
|
1911
|
-
else chosen.add(o.value);
|
|
1912
|
-
return chosen.has(o.value);
|
|
1913
|
-
}, { disabled: o.disabled, reason: o.disabled ? o.reason : null }));
|
|
1914
|
-
});
|
|
1915
|
-
for (const v of [...strays]) {
|
|
1916
|
-
root.appendChild(chipFor(notFound(shownValue(v)), true, () => {
|
|
1917
|
-
const i = strays.indexOf(v);
|
|
1918
|
-
if (i >= 0) {
|
|
1919
|
-
strays.splice(i, 1);
|
|
1920
|
-
return false;
|
|
1921
|
-
}
|
|
1922
|
-
strays.push(v);
|
|
1923
|
-
return true;
|
|
1924
|
-
}, { stray: true }));
|
|
1925
|
-
}
|
|
1926
|
-
};
|
|
1927
|
-
const valueOf = () => [...list.filter((o) => chosen.has(o.value)).map((o) => o.value), ...strays];
|
|
1928
|
-
draw(options, value);
|
|
1929
|
-
return {
|
|
1930
|
-
el: root,
|
|
1931
|
-
valueOf,
|
|
1932
|
-
setValue: (stored) => draw(shown, stored),
|
|
1933
|
-
setOptions: (opts) => draw(opts, valueOf())
|
|
1934
|
-
};
|
|
1935
|
-
}
|
|
1936
|
-
function choiceList({
|
|
1937
|
-
options,
|
|
1938
|
-
value,
|
|
1939
|
-
name,
|
|
1940
|
-
label,
|
|
1941
|
-
readOnly,
|
|
1942
|
-
onChange,
|
|
1943
|
-
notFound = (v) => `${v} (not found)`,
|
|
1944
|
-
keepMissing = true,
|
|
1945
|
-
loose = false
|
|
1946
|
-
}) {
|
|
1947
|
-
const root = el("div", "twm-flow-choices");
|
|
1948
|
-
root.setAttribute("role", "radiogroup");
|
|
1949
|
-
if (label) root.setAttribute("aria-label", label);
|
|
1950
|
-
let list = [];
|
|
1951
|
-
let radios = [];
|
|
1952
|
-
const draw = (opts, current) => {
|
|
1953
|
-
list = flatChoices(opts);
|
|
1954
|
-
const heads = groupHeads(opts);
|
|
1955
|
-
radios = [];
|
|
1956
|
-
root.replaceChildren();
|
|
1957
|
-
const named = choiceIndex(list, current, loose);
|
|
1958
|
-
const at = named >= 0 && !list[named].disabled ? named : -1;
|
|
1959
|
-
list.forEach((o, i) => {
|
|
1960
|
-
if (heads.has(i)) root.appendChild(groupHeading(heads.get(i)));
|
|
1961
|
-
const row = el("label", `twm-flow-choice${o.disabled ? " twm-choice--disabled" : ""}`);
|
|
1962
|
-
const radio = el("input", "twm-flow-choice__radio");
|
|
1963
|
-
radio.type = "radio";
|
|
1964
|
-
radio.name = name;
|
|
1965
|
-
radio.checked = i === at;
|
|
1966
|
-
radio.disabled = Boolean(readOnly) || o.disabled;
|
|
1967
|
-
radio.addEventListener("change", () => {
|
|
1968
|
-
if (radio.checked) onChange?.(o.value);
|
|
1969
|
-
});
|
|
1970
|
-
radios.push(radio);
|
|
1971
|
-
const words = el("span", "twm-flow-choice__words");
|
|
1972
|
-
words.appendChild(el("span", "twm-flow-choice__label", o.label));
|
|
1973
|
-
if (o.description !== null) words.appendChild(el("span", "twm-flow-choice__sub", o.description));
|
|
1974
|
-
if (o.disabled && o.reason) words.appendChild(el("span", "twm-choice__reason", o.reason));
|
|
1975
|
-
row.append(radio, words);
|
|
1976
|
-
root.appendChild(row);
|
|
1977
|
-
});
|
|
1978
|
-
if (keepMissing && current !== void 0 && named < 0) {
|
|
1979
|
-
root.appendChild(el("p", "twm-flow-field__note", notFound(shownValue(current))));
|
|
1980
|
-
}
|
|
1981
|
-
};
|
|
1982
|
-
const checkedAt = () => radios.findIndex((r) => r.checked);
|
|
1983
|
-
const entry = () => list[checkedAt()] ?? null;
|
|
1984
|
-
const api = {
|
|
1985
|
-
el: root,
|
|
1986
|
-
focus: () => (radios.find((r) => r.checked && !r.disabled) || radios.find((r) => !r.disabled))?.focus({ preventScroll: true }),
|
|
1987
|
-
entry,
|
|
1988
|
-
valueOf: () => entry()?.value,
|
|
1989
|
-
select(v) {
|
|
1990
|
-
const named = choiceIndex(list, v, loose);
|
|
1991
|
-
const at = named >= 0 && !list[named].disabled ? named : -1;
|
|
1992
|
-
radios.forEach((r, i) => {
|
|
1993
|
-
r.checked = i === at;
|
|
1994
|
-
});
|
|
1995
|
-
return at >= 0;
|
|
1996
|
-
},
|
|
1997
|
-
setOptions(opts) {
|
|
1998
|
-
draw(opts, api.valueOf());
|
|
1999
|
-
}
|
|
2000
|
-
};
|
|
2001
|
-
draw(options, value);
|
|
2002
|
-
return api;
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
// src/ui/components/row_activation.js
|
|
2006
|
-
var ROW_CONTROL_SELECTOR = [
|
|
2007
|
-
"button",
|
|
2008
|
-
"a",
|
|
2009
|
-
"input",
|
|
2010
|
-
"select",
|
|
2011
|
-
"textarea",
|
|
2012
|
-
"label",
|
|
2013
|
-
"summary",
|
|
2014
|
-
'[contenteditable=""]',
|
|
2015
|
-
'[contenteditable="true"]',
|
|
2016
|
-
"[data-twm-action]"
|
|
2017
|
-
].join(", ");
|
|
2018
|
-
function isRowControl(target, scope = null) {
|
|
2019
|
-
const hit = target?.closest?.(ROW_CONTROL_SELECTOR);
|
|
2020
|
-
return !!hit && (!scope || scope.contains(hit));
|
|
2021
|
-
}
|
|
2022
|
-
function endsTextSelection(target, scope = null) {
|
|
2023
|
-
const doc = target?.ownerDocument || (typeof document !== "undefined" ? document : null);
|
|
2024
|
-
const sel = doc?.getSelection?.();
|
|
2025
|
-
if (!sel || sel.isCollapsed || !String(sel)) return false;
|
|
2026
|
-
if (!scope) return true;
|
|
2027
|
-
const inside = (node) => !!node && scope.contains(node);
|
|
2028
|
-
return inside(sel.anchorNode) || inside(sel.focusNode);
|
|
2029
|
-
}
|
|
2030
|
-
function isRowActivation(ev, gesture = "click", { scope = null } = {}) {
|
|
2031
|
-
const target = ev?.target;
|
|
2032
|
-
if (!target?.closest) return false;
|
|
2033
|
-
if (isRowControl(target, scope)) return false;
|
|
2034
|
-
if (gesture === "click") {
|
|
2035
|
-
if ((ev.detail ?? 0) > 1) return false;
|
|
2036
|
-
if (endsTextSelection(target, scope)) return false;
|
|
2037
|
-
}
|
|
2038
|
-
return true;
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
1701
|
export {
|
|
2042
1702
|
DEFAULT_WINDOW_STORAGE_KEY,
|
|
2043
1703
|
DEFAULT_MAX_SAVED_WINDOWS,
|
|
2044
1704
|
ManagedWindow,
|
|
2045
1705
|
ToggleField,
|
|
1706
|
+
fireEvent,
|
|
2046
1707
|
isHexColor,
|
|
2047
1708
|
normalizeHex,
|
|
2048
|
-
ColorField
|
|
2049
|
-
shownValue,
|
|
2050
|
-
flatChoices,
|
|
2051
|
-
findChoice,
|
|
2052
|
-
selectBox,
|
|
2053
|
-
toggleChips,
|
|
2054
|
-
choiceList,
|
|
2055
|
-
ROW_CONTROL_SELECTOR,
|
|
2056
|
-
isRowControl,
|
|
2057
|
-
endsTextSelection,
|
|
2058
|
-
isRowActivation
|
|
1709
|
+
ColorField
|
|
2059
1710
|
};
|
|
2060
|
-
//# sourceMappingURL=chunk-
|
|
1711
|
+
//# sourceMappingURL=chunk-ZL3VKINP.js.map
|