@sylwellsoftware/fray 0.2.0 → 0.3.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.
Files changed (46) hide show
  1. package/README.md +79 -11
  2. package/dist/Components/Placeholder.d.ts +1 -1
  3. package/dist/Components/Placeholder.d.ts.map +1 -1
  4. package/dist/Components/controlUtils.d.ts.map +1 -1
  5. package/dist/Components/data/filterState.d.ts +38 -0
  6. package/dist/Components/data/filterState.d.ts.map +1 -0
  7. package/dist/Components/data/listview/listview.d.ts +16 -5
  8. package/dist/Components/data/listview/listview.d.ts.map +1 -1
  9. package/dist/Components/data/selectionhandler.d.ts +24 -5
  10. package/dist/Components/data/selectionhandler.d.ts.map +1 -1
  11. package/dist/Components/data/table/DataTable.d.ts +36 -30
  12. package/dist/Components/data/table/DataTable.d.ts.map +1 -1
  13. package/dist/Components/data/table/FilterPanel.d.ts +8 -1
  14. package/dist/Components/data/table/FilterPanel.d.ts.map +1 -1
  15. package/dist/Components/data/table/TableHeaderCell.d.ts.map +1 -1
  16. package/dist/Components/data/table/tableDataSource.d.ts +49 -0
  17. package/dist/Components/data/table/tableDataSource.d.ts.map +1 -0
  18. package/dist/Components/data/table/tableQuery.d.ts +6 -2
  19. package/dist/Components/data/table/tableQuery.d.ts.map +1 -1
  20. package/dist/Components/data/treeview/treeModel.d.ts +23 -0
  21. package/dist/Components/data/treeview/treeModel.d.ts.map +1 -0
  22. package/dist/Components/data/treeview/treeview.d.ts +1 -1
  23. package/dist/Components/data/treeview/treeview.d.ts.map +1 -1
  24. package/dist/Components/dialog/dialog.d.ts +1 -1
  25. package/dist/Components/dialog/dialog.d.ts.map +1 -1
  26. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts +1 -1
  27. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts.map +1 -1
  28. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts +2 -2
  29. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts.map +1 -1
  30. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts +2 -2
  31. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts.map +1 -1
  32. package/dist/index.d.ts +14 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2676 -726
  35. package/dist/index.js.map +1 -1
  36. package/dist/util/filterMode.d.ts +6 -4
  37. package/dist/util/filterMode.d.ts.map +1 -1
  38. package/package.json +4 -9
  39. package/styles/structural.css +9 -3
  40. package/EXPERIMENTAL.md +0 -75
  41. package/dist/button-CqDGmkBt.js +0 -212
  42. package/dist/button-CqDGmkBt.js.map +0 -1
  43. package/dist/experimental.d.ts +0 -16
  44. package/dist/experimental.d.ts.map +0 -1
  45. package/dist/experimental.js +0 -1399
  46. package/dist/experimental.js.map +0 -1
@@ -1,1399 +0,0 @@
1
- var ie = Object.defineProperty;
2
- var ne = (t, r, e) => r in t ? ie(t, r, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[r] = e;
3
- var o = (t, r, e) => ne(t, typeof r != "symbol" ? r + "" : r, e);
4
- import { C as w, j as c, c as x, a as b, i as U } from "./jsx-dev-runtime-DukiDpV9.js";
5
- import { Emitter as g, FetchState as m, DerivedEmitter as oe, QueryArg as V, LiveQuery as ae, RestQueryHandler as le } from "@sylwellsoftware/glue";
6
- import { c as I, C as F, F as K, i as W, a as de, b as ce, B as Q } from "./button-CqDGmkBt.js";
7
- class E extends w {
8
- render() {
9
- const r = he(this.props.width ?? 65), e = this.Host;
10
- return /* @__PURE__ */ c(e, { style: { width: `${r}%` }, "aria-hidden": "true" });
11
- }
12
- }
13
- o(E, "hostName", "placeholder"), o(E, "standaloneHostName", "loading-placeholder"), o(E, "baseStyles", [
14
- ["&::after", ["after", "working"]]
15
- ]), o(E, "css", x`
16
- & {
17
- display: block;
18
- min-width: 3rem;
19
- height: 1em;
20
- overflow: hidden;
21
- background: currentColor;
22
- border-radius: var(--ui-border-radius);
23
- opacity: 0.18;
24
- position: relative;
25
- }
26
-
27
- @keyframes fray-placeholder-progress {
28
- from { background-position: 0 0; }
29
- to { background-position: 2rem 0; }
30
- }
31
- `);
32
- function he(t) {
33
- const r = Number(t);
34
- if (!Number.isFinite(r)) throw new TypeError("Placeholder width must be numeric");
35
- return Math.min(100, Math.max(10, r));
36
- }
37
- class J {
38
- constructor({
39
- getItems: r,
40
- getKey: e = z,
41
- selectedItemsEmitter: s,
42
- owner: i = null
43
- }) {
44
- o(this, "getItems");
45
- o(this, "getKey");
46
- o(this, "selectedItemsEmitter");
47
- o(this, "selectedItems$");
48
- o(this, "ownsSelectedItemsEmitter");
49
- o(this, "rows", []);
50
- o(this, "rowCleanups", []);
51
- o(this, "activeIndex", 0);
52
- o(this, "anchorIndex", null);
53
- o(this, "dragStartIndex", null);
54
- o(this, "dragOriginEvent", null);
55
- o(this, "dragMoved", !1);
56
- o(this, "dragCleanup", null);
57
- o(this, "suppressNextClick", !1);
58
- o(this, "suppressClickTimer", null);
59
- o(this, "destroyed", !1);
60
- o(this, "ownedSelectedItemsEmitter");
61
- if (typeof r != "function")
62
- throw new TypeError("Selection handler getItems must be a function");
63
- if (typeof e != "function")
64
- throw new TypeError("Selection handler getKey must be a function");
65
- this.getItems = r, this.getKey = e, this.ownedSelectedItemsEmitter = s == null ? new g([], { owner: i, purpose: "selected items" }) : null, this.selectedItemsEmitter = s ?? this.ownedSelectedItemsEmitter, this.selectedItems$ = this.selectedItemsEmitter, this.ownsSelectedItemsEmitter = this.ownedSelectedItemsEmitter != null;
66
- }
67
- rowsUpdated(r) {
68
- this.destroyed || (this.releaseRows(), this.rows = Array.from(r ?? []), this.rows.forEach((e, s) => this.wireRow(e, s)), this.activeIndex = fe(this.activeIndex, this.rows.length), this.reconcileSelectedItems(), this.syncRows());
69
- }
70
- wireRow(r, e) {
71
- const s = (l) => this.handleClick(e, l), i = (l) => this.handleKeyDown(e, l), n = (l) => this.handleMouseDown(e, l, r), a = (l) => this.handleMouseEnter(e, l);
72
- r.addEventListener("click", s), r.addEventListener("keydown", i), r.addEventListener("mousedown", n), r.addEventListener("mouseenter", a), this.rowCleanups.push(() => {
73
- r.removeEventListener("click", s), r.removeEventListener("keydown", i), r.removeEventListener("mousedown", n), r.removeEventListener("mouseenter", a);
74
- });
75
- }
76
- handleClick(r, e) {
77
- var s;
78
- if (e.preventDefault(), this.suppressNextClick) {
79
- this.clearClickSuppression();
80
- return;
81
- }
82
- this.activeIndex = r, this.selectIndex(r, e), (s = this.rows[r]) == null || s.focus();
83
- }
84
- handleMouseDown(r, e, s) {
85
- if (e.button !== 0 || !this.supportsDragSelection()) return;
86
- this.finishDrag(!1), this.clearClickSuppression(), this.dragStartIndex = r, this.dragOriginEvent = e, this.dragMoved = !1;
87
- const i = s.ownerDocument, n = () => this.finishDrag(this.dragMoved);
88
- i.addEventListener("mouseup", n), this.dragCleanup = () => i.removeEventListener("mouseup", n);
89
- }
90
- handleMouseEnter(r, e) {
91
- var s;
92
- this.dragStartIndex != null && (r === this.dragStartIndex && !this.dragMoved || r === this.activeIndex && this.dragMoved || (e.preventDefault(), this.dragMoved = !0, this.activeIndex = r, this.selectDragRange(this.dragStartIndex, r, this.dragOriginEvent ?? e), (s = this.rows[r]) == null || s.focus()));
93
- }
94
- handleKeyDown(r, e) {
95
- var n;
96
- const s = this.rows.length - 1;
97
- let i;
98
- if (e.key === "ArrowDown") i = Math.min(r + 1, s);
99
- else if (e.key === "ArrowUp") i = Math.max(r - 1, 0);
100
- else if (e.key === "Home") i = 0;
101
- else if (e.key === "End") i = s;
102
- else if (e.key === " " || e.key === "Enter") {
103
- e.preventDefault(), this.activeIndex = r, this.selectIndex(r, e);
104
- return;
105
- } else return;
106
- e.preventDefault(), this.activeIndex = i, this.onKeyboardMove(i, e), this.syncRows(), (n = this.rows[i]) == null || n.focus();
107
- }
108
- onKeyboardMove(r, e) {
109
- this.selectIndex(r, e);
110
- }
111
- supportsDragSelection() {
112
- return !1;
113
- }
114
- selectDragRange(r, e, s) {
115
- }
116
- selectIndex(r, e) {
117
- }
118
- setSelectedItems(r, e = "selection changed") {
119
- this.selectedItemsEmitter.set(r, e), this.syncRows();
120
- }
121
- getSelectedItems() {
122
- return this.selectedItemsEmitter.get() ?? [];
123
- }
124
- getSelectedItemsEmitter() {
125
- return this.selectedItemsEmitter;
126
- }
127
- reconcileSelectedItems() {
128
- const r = this.getSelectedItems();
129
- if (r.length === 0) return;
130
- const e = new Set(r.map((i, n) => this.getKey(i, n))), s = this.getItems().filter((i, n) => e.has(this.getKey(i, n)));
131
- (s.length !== r.length || s.some((i, n) => !Object.is(i, r[n]))) && this.selectedItemsEmitter.set([...s], "selection reconciled with rows");
132
- }
133
- syncRows() {
134
- const r = new Set(this.getSelectedItems().map((s, i) => this.getKey(s, i))), e = this.getItems();
135
- this.rows.forEach((s, i) => {
136
- const n = e[i], a = n !== void 0 && r.has(this.getKey(n, i));
137
- s.classList.toggle("selected", a), s.setAttribute("aria-selected", String(a)), s.tabIndex = i === this.activeIndex ? 0 : -1;
138
- });
139
- }
140
- releaseRows() {
141
- for (const r of this.rowCleanups.splice(0)) r();
142
- this.rows = [];
143
- }
144
- finishDrag(r) {
145
- var e;
146
- (e = this.dragCleanup) == null || e.call(this), this.dragCleanup = null, this.dragStartIndex = null, this.dragOriginEvent = null, this.dragMoved = !1, r && (this.suppressNextClick = !0, this.suppressClickTimer != null && clearTimeout(this.suppressClickTimer), this.suppressClickTimer = setTimeout(() => this.clearClickSuppression(), 0));
147
- }
148
- clearClickSuppression() {
149
- this.suppressNextClick = !1, this.suppressClickTimer != null && clearTimeout(this.suppressClickTimer), this.suppressClickTimer = null;
150
- }
151
- destroy() {
152
- var r;
153
- this.destroyed || (this.destroyed = !0, this.finishDrag(!1), this.clearClickSuppression(), this.releaseRows(), (r = this.ownedSelectedItemsEmitter) == null || r.dispose());
154
- }
155
- }
156
- class ue extends J {
157
- selectIndex(r) {
158
- const e = this.getItems()[r];
159
- e !== void 0 && (this.anchorIndex = r, this.setSelectedItems([e], "single selection changed"));
160
- }
161
- }
162
- class pe extends J {
163
- selectIndex(r, e) {
164
- const s = this.getItems(), i = s[r];
165
- if (i !== void 0) {
166
- if (e.shiftKey && this.anchorIndex != null) {
167
- const n = Math.min(this.anchorIndex, r), a = Math.max(this.anchorIndex, r), l = s.slice(n, a + 1), d = L(e) ? P(this.getSelectedItems(), l, this.getKey) : [...l];
168
- this.setSelectedItems(d, "range selection changed");
169
- return;
170
- }
171
- if (L(e) || "key" in e && e.key === " ") {
172
- const n = this.getSelectedItems(), a = this.getKey(i, r), d = n.some((h, u) => Object.is(this.getKey(h, u), a)) ? n.filter((h, u) => !Object.is(this.getKey(h, u), a)) : [...n, i];
173
- this.anchorIndex = r, this.setSelectedItems(d, "multi selection toggled");
174
- return;
175
- }
176
- this.anchorIndex = r, this.setSelectedItems([i], "multi selection changed");
177
- }
178
- }
179
- onKeyboardMove(r, e) {
180
- e.shiftKey && this.selectIndex(r, e);
181
- }
182
- supportsDragSelection() {
183
- return !0;
184
- }
185
- selectDragRange(r, e, s) {
186
- const i = this.getItems(), n = Math.min(r, e), a = Math.max(r, e), l = i.slice(n, a + 1), d = L(s) ? P(this.getSelectedItems(), l, this.getKey) : [...l];
187
- this.anchorIndex = r, this.setSelectedItems(d, "drag selection changed");
188
- }
189
- }
190
- function Y(t) {
191
- return t.multiSelect ? new pe(t) : new ue(t);
192
- }
193
- function z(t, r) {
194
- if (t != null && typeof t == "object") {
195
- const e = Reflect.get(t, "id");
196
- if (e != null) return e;
197
- }
198
- if (typeof t == "string" || typeof t == "number") return t;
199
- throw new TypeError(
200
- `Selection item at index ${r} needs an id or an explicit itemKey/rowKey`
201
- );
202
- }
203
- function L(t) {
204
- return !!(t.ctrlKey || t.metaKey);
205
- }
206
- function fe(t, r) {
207
- return r <= 0 ? 0 : Math.min(Math.max(t, 0), r - 1);
208
- }
209
- function P(t, r, e) {
210
- const s = [...t], i = new Set(t.map((n, a) => e(n, a)));
211
- for (const n of r) {
212
- const a = e(n, s.length);
213
- i.has(a) || (i.add(a), s.push(n));
214
- }
215
- return s;
216
- }
217
- class D extends w {
218
- constructor(e = {}) {
219
- super(e);
220
- o(this, "itemsEmitter");
221
- o(this, "items$");
222
- o(this, "selectedItemsEmitter");
223
- o(this, "selectedItems$");
224
- o(this, "getItemKey");
225
- o(this, "selectionHandler");
226
- o(this, "ownedItemsEmitter");
227
- o(this, "ownedSelectedItemsEmitter");
228
- ye(e.items) ? (this.itemsEmitter = e.items, this.ownedItemsEmitter = null) : (this.ownedItemsEmitter = new g(e.items ?? [], {
229
- owner: this,
230
- purpose: "list items"
231
- }), this.itemsEmitter = this.ownedItemsEmitter), this.items$ = this.itemsEmitter, this.ownedSelectedItemsEmitter = e.selectedItemsEmitter == null ? new g([], { owner: this, purpose: "selected list items" }) : null, this.selectedItemsEmitter = e.selectedItemsEmitter ?? this.ownedSelectedItemsEmitter, this.selectedItems$ = this.selectedItemsEmitter, this.getItemKey = me(e.itemKey), this.selectionHandler = Y({
232
- owner: this,
233
- multiSelect: e.multiSelect ?? !1,
234
- selectedItemsEmitter: this.selectedItemsEmitter,
235
- getItems: () => this.itemsEmitter.get(),
236
- getKey: this.getItemKey
237
- });
238
- }
239
- initialize() {
240
- this.watch(this.itemsEmitter, this.selectedItemsEmitter);
241
- }
242
- render() {
243
- const e = this.itemsEmitter.get();
244
- if (!Array.isArray(e)) throw new TypeError("ListView items must be an array");
245
- const s = this.itemsEmitter.getFetchState(), i = this.itemsEmitter.getError(), n = s === m.Initial || s === m.Loading, a = new Set(this.selectedItemsEmitter.get().map((d, h) => this.getItemKey(d, h))), l = this.Host;
246
- return /* @__PURE__ */ b(
247
- l,
248
- {
249
- className: I(this.props) || null,
250
- children: [
251
- s === m.Error ? /* @__PURE__ */ c("p", { role: "alert", "data-part": "error", children: we(i, "Unable to load items") }) : null,
252
- n && e.length === 0 ? /* @__PURE__ */ b("div", { role: "status", "data-part": "loading", children: [
253
- /* @__PURE__ */ c("span", { children: "Loading items…" }),
254
- Array.from({ length: this.props.placeholderCount ?? 5 }, (d, h) => /* @__PURE__ */ c("div", { "data-part": "placeholder-row", children: /* @__PURE__ */ c(E, { width: 45 + h * 7 }) }, `placeholder-${h}`))
255
- ] }) : null,
256
- s === m.Ready && e.length === 0 ? /* @__PURE__ */ c("p", { role: "status", "data-part": "empty", children: "No items" }) : null,
257
- e.length > 0 ? /* @__PURE__ */ c(
258
- "div",
259
- {
260
- role: "listbox",
261
- "data-part": "list",
262
- "aria-label": this.props.label ?? "Items",
263
- "aria-busy": n ? "true" : null,
264
- "aria-multiselectable": this.props.multiSelect ? "true" : null,
265
- children: e.map((d, h) => {
266
- const u = this.getItemKey(d, h), f = a.has(u), p = this.props.renderItem ? this.props.renderItem(d, h) : ge(d);
267
- return /* @__PURE__ */ c(
268
- "div",
269
- {
270
- role: "option",
271
- "data-part": "row",
272
- "data-fray-selectable-row": "",
273
- "data-index": h,
274
- "aria-selected": String(f),
275
- tabIndex: h === 0 ? 0 : -1,
276
- children: p
277
- },
278
- String(u)
279
- );
280
- })
281
- }
282
- ) : null
283
- ]
284
- }
285
- );
286
- }
287
- afterUpdate(e) {
288
- const s = e instanceof Element ? e.querySelectorAll("[data-fray-selectable-row]") : [];
289
- this.selectionHandler.rowsUpdated(s);
290
- }
291
- getSelectedItems() {
292
- return this.selectionHandler.getSelectedItems();
293
- }
294
- getSelectedItemsEmitter() {
295
- return this.selectedItemsEmitter;
296
- }
297
- onDestroy() {
298
- var e, s;
299
- this.selectionHandler.destroy(), (e = this.ownedItemsEmitter) == null || e.dispose(), (s = this.ownedSelectedItemsEmitter) == null || s.dispose();
300
- }
301
- }
302
- o(D, "dependencies", [E]), o(D, "hostName", "list-view"), o(D, "standaloneHostName", "list-view"), o(D, "baseStyles", [
303
- ["&", "inputlike"],
304
- ['& > [data-part="list"] > [data-part="row"]', "inputline"]
305
- ]), o(D, "css", x`
306
- & {
307
- display: flex;
308
- flex-direction: column;
309
- overflow-y: auto;
310
- min-height: 0;
311
- }
312
-
313
- & > [data-part="list"],
314
- & > [data-part="loading"] {
315
- display: flex;
316
- flex-direction: column;
317
- }
318
-
319
- & > [data-part="list"] > [data-part="row"] {
320
- cursor: default;
321
- user-select: none;
322
- }
323
-
324
- & > [data-part="list"] > [data-part="row"]:hover,
325
- & > [data-part="list"] > [data-part="row"]:focus-visible {
326
- background: var(--button-background-hover);
327
- outline: 2px solid var(--ui-accent-color);
328
- outline-offset: -2px;
329
- }
330
-
331
- & > [data-part="list"] > [data-part="row"][aria-selected="true"] {
332
- color: var(--toggle-selected-text);
333
- background: var(--toggle-selected-bg);
334
- }
335
-
336
- & > [data-part="empty"],
337
- & > [data-part="error"] {
338
- margin: 0;
339
- padding: var(--ui-padding);
340
- }
341
-
342
- & > [data-part="error"] {
343
- color: var(--error-color);
344
- }
345
- `);
346
- function me(t) {
347
- if (t == null) return z;
348
- if (typeof t == "function") return t;
349
- if (typeof t == "string" && t.length > 0)
350
- return (r, e) => {
351
- if (r == null || typeof r != "object" && typeof r != "function")
352
- throw new TypeError(`ListView item at index ${e} lacks ${t}`);
353
- const s = Reflect.get(r, t);
354
- if (s == null)
355
- throw new TypeError(`ListView item at index ${e} lacks ${t}`);
356
- return s;
357
- };
358
- throw new TypeError("ListView itemKey must be a function or property name");
359
- }
360
- function ye(t) {
361
- return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function";
362
- }
363
- function ge(t) {
364
- if (t != null && (typeof t == "object" || typeof t == "function")) {
365
- const r = Reflect.get(t, "label");
366
- if (be(r)) return r;
367
- }
368
- return String(t);
369
- }
370
- function be(t) {
371
- return t == null || typeof t == "string" || typeof t == "number";
372
- }
373
- function we(t, r) {
374
- return t instanceof Error ? t.message : t == null ? r : String(t);
375
- }
376
- class T extends w {
377
- constructor(e = {}) {
378
- super(e);
379
- o(this, "optionsEmitter");
380
- this.optionsEmitter = ve(e.options) ? e.options : null;
381
- }
382
- initialize() {
383
- this.optionsEmitter && this.watch(this.optionsEmitter);
384
- }
385
- render() {
386
- var h, u, f;
387
- const e = ((h = this.optionsEmitter) == null ? void 0 : h.get()) ?? (Array.isArray(this.props.options) ? this.props.options : []);
388
- if (!Array.isArray(e))
389
- throw new TypeError("FilterPanel options must be an array or emitter of arrays");
390
- const s = ((u = this.optionsEmitter) == null ? void 0 : u.getFetchState()) ?? m.Ready, i = (f = this.optionsEmitter) == null ? void 0 : f.getError(), n = Se(this.props.filters), a = this.props.filterModes ?? F.symbols, l = this.props.defaultSemanticState ?? K.Neutral, d = this.Host;
391
- return s === m.Error ? /* @__PURE__ */ c(
392
- d,
393
- {
394
- className: I(this.props) || null,
395
- role: "alert",
396
- "data-state": "error",
397
- children: ke(i, "Unable to load filter options")
398
- }
399
- ) : (s === m.Initial || s === m.Loading) && e.length === 0 ? /* @__PURE__ */ c(
400
- d,
401
- {
402
- className: I(this.props) || null,
403
- role: "status",
404
- "data-state": "loading",
405
- children: "Loading filter options…"
406
- }
407
- ) : /* @__PURE__ */ c(
408
- d,
409
- {
410
- className: I(this.props) || null,
411
- role: "group",
412
- "aria-label": this.props.label ?? "Filter options",
413
- children: e.length === 0 ? /* @__PURE__ */ c("span", { children: "No filter options" }) : e.map((p) => {
414
- const y = X(p), S = Ie(p), C = n.get(y) ?? l;
415
- return /* @__PURE__ */ c(
416
- Ee,
417
- {
418
- label: S,
419
- defaultValue: C,
420
- symbols: a,
421
- onChange: (q, v) => {
422
- var R, M;
423
- v == null || v.stopPropagation();
424
- const k = new Map(n);
425
- q === K.Neutral ? k.delete(y) : k.set(y, q), (M = (R = this.props).onChange) == null || M.call(R, k, v);
426
- }
427
- },
428
- `${String(y)}:${String(C)}`
429
- );
430
- })
431
- }
432
- );
433
- }
434
- }
435
- o(T, "dependencies", [F]), o(T, "hostName", "filter-panel"), o(T, "standaloneHostName", "filter-panel"), o(T, "css", x`
436
- & {
437
- position: absolute;
438
- z-index: 1000;
439
- inset-block-start: 100%;
440
- inset-inline-end: 0;
441
- display: flex;
442
- min-width: 12rem;
443
- padding: var(--ui-padding);
444
- flex-flow: column nowrap;
445
- align-items: stretch;
446
- color: var(--panel-color);
447
- background: var(--panel-bg);
448
- border: var(--panel-border);
449
- border-radius: var(--panel-radius);
450
- box-shadow: var(--panel-shadow);
451
- }
452
- `);
453
- const Ee = F;
454
- function Se(t) {
455
- if (t == null) return /* @__PURE__ */ new Map();
456
- if (t instanceof Map) return new Map(t);
457
- if (Array.isArray(t)) return new Map(t);
458
- throw new TypeError("FilterPanel filters must be a Map or tuple array");
459
- }
460
- function X(t) {
461
- if (typeof t == "string" || typeof t == "number") return t;
462
- if (t != null && typeof t == "object") {
463
- const r = Reflect.get(t, "value");
464
- if (typeof r == "string" || typeof r == "number") return r;
465
- }
466
- throw new TypeError("Filter options must be strings, numbers, or value/label objects");
467
- }
468
- function Ie(t) {
469
- if (t != null && typeof t == "object") {
470
- const r = Reflect.get(t, "label");
471
- if (r != null) return xe(r) ? r : String(r);
472
- }
473
- return String(X(t));
474
- }
475
- function xe(t) {
476
- return typeof t == "string" || typeof t == "number";
477
- }
478
- function ve(t) {
479
- return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function";
480
- }
481
- function ke(t, r) {
482
- return t instanceof Error ? t.message : t == null ? r : String(t);
483
- }
484
- class N extends w {
485
- constructor() {
486
- super(...arguments);
487
- o(this, "filterVisible", !1);
488
- o(this, "onGlobalClick", (e) => {
489
- this.filterVisible && this.dom instanceof Node && e.target instanceof Node && !this.dom.contains(e.target) && (this.filterVisible = !1, this.update());
490
- });
491
- }
492
- initialize() {
493
- this.watch(this.props.sortEmitter, this.props.filtersEmitter), this.props.filterOptions != null && this.listen(document, "click", this.onGlobalClick);
494
- }
495
- toggleSort() {
496
- if (!this.props.sortable) return;
497
- const e = this.props.sortEmitter.get();
498
- let s;
499
- (e == null ? void 0 : e.field) !== this.props.field ? s = { field: this.props.field, direction: "asc" } : e.direction === "asc" ? s = { field: this.props.field, direction: "desc" } : s = null, this.props.sortEmitter.set(s, "table sort changed");
500
- }
501
- toggleFilterPanel(e) {
502
- e.stopPropagation(), this.filterVisible = !this.filterVisible, this.update();
503
- }
504
- updateFilters(e, s) {
505
- var n, a;
506
- const i = { ...this.props.filtersEmitter.get() };
507
- e.size === 0 ? delete i[this.props.field] : i[this.props.field] = [...e.entries()], this.props.filtersEmitter.set(i, "table filters changed"), (a = (n = this.props).onFilterChange) == null || a.call(n, i, s);
508
- }
509
- render() {
510
- const e = this.props.sortEmitter.get(), s = (e == null ? void 0 : e.field) === this.props.field ? e.direction : null, i = new Map(
511
- (this.props.filtersEmitter.get()[this.props.field] ?? []).filter(Te)
512
- ), n = this.props.label ?? String(this.props.field), a = `Filter ${String(n)}`;
513
- let l = null;
514
- return this.filterVisible && this.props.filterOptions != null && (l = /* @__PURE__ */ c(
515
- T,
516
- {
517
- label: a,
518
- options: this.props.filterOptions,
519
- filters: i,
520
- onChange: (d, h) => this.updateFilters(d, h),
521
- ...this.props.filterModes == null ? {} : { filterModes: this.props.filterModes },
522
- ...this.props.defaultSemanticState == null ? {} : { defaultSemanticState: this.props.defaultSemanticState }
523
- },
524
- "filter-panel"
525
- )), /* @__PURE__ */ b(
526
- "th",
527
- {
528
- scope: "col",
529
- "data-fray-component": "table-header-cell",
530
- "aria-sort": s === "asc" ? "ascending" : s === "desc" ? "descending" : "none",
531
- children: [
532
- this.props.sortable ? /* @__PURE__ */ b(
533
- "button",
534
- {
535
- type: "button",
536
- "data-part": "sort",
537
- onClick: () => this.toggleSort(),
538
- children: [
539
- n,
540
- s === "asc" ? " ▲" : s === "desc" ? " ▼" : ""
541
- ]
542
- }
543
- ) : /* @__PURE__ */ c("span", { "data-part": "label", children: n }),
544
- this.props.filterOptions == null ? null : /* @__PURE__ */ c(
545
- "button",
546
- {
547
- type: "button",
548
- "data-part": "filter-toggle",
549
- "aria-label": a,
550
- "aria-expanded": String(this.filterVisible),
551
- onClick: (d) => this.toggleFilterPanel(d),
552
- children: "Filter"
553
- }
554
- ),
555
- l
556
- ]
557
- }
558
- );
559
- }
560
- }
561
- o(N, "dependencies", [T]), o(N, "baseStyles", [
562
- ['th[data-fray-component="table-header-cell"]', "noselect"],
563
- ['th[data-fray-component="table-header-cell"] > [data-part="sort"]', ["uiline", "button"]],
564
- ['th[data-fray-component="table-header-cell"] > [data-part="filter-toggle"]', ["uiline", "button"]]
565
- ]), o(N, "css", x`
566
- th[data-fray-component="table-header-cell"] {
567
- position: relative;
568
- text-align: start;
569
- color: var(
570
- --fray-table-header-color,
571
- var(--fray-section-header-color, var(--fray-header-color))
572
- );
573
- background: var(
574
- --fray-table-header-background,
575
- var(--fray-section-header-background, var(--fray-header-background))
576
- );
577
- border-block-end: var(--fray-section-header-border, var(--fray-header-border));
578
- box-shadow: var(--fray-section-header-shadow, var(--fray-header-shadow));
579
- }
580
-
581
- th[data-fray-component="table-header-cell"] > [data-part="sort"],
582
- th[data-fray-component="table-header-cell"] > [data-part="filter-toggle"] {
583
- width: auto;
584
- font-family: inherit;
585
- color: inherit;
586
- background: var(
587
- --fray-table-header-button-background,
588
- var(--fray-button-background)
589
- );
590
- }
591
-
592
- th[data-fray-component="table-header-cell"] > [data-part="filter-toggle"] {
593
- margin-inline-start: var(--ui-padding-h);
594
- font-size: 0.75em;
595
- }
596
- `);
597
- function Te(t) {
598
- return typeof t[0] == "string" || typeof t[0] == "number";
599
- }
600
- class H extends w {
601
- render() {
602
- return /* @__PURE__ */ c("thead", { "data-fray-component": "table-header", children: /* @__PURE__ */ c("tr", { children: this.props.columns.map((r) => /* @__PURE__ */ c(
603
- N,
604
- {
605
- field: r.field,
606
- sortEmitter: this.props.sortEmitter,
607
- filtersEmitter: this.props.filtersEmitter,
608
- ...r.label == null ? {} : { label: r.label },
609
- ...r.sortable == null ? {} : { sortable: r.sortable },
610
- ...r.filterOptions == null ? {} : { filterOptions: r.filterOptions },
611
- ...this.props.filterModes == null ? {} : { filterModes: this.props.filterModes },
612
- ...this.props.defaultSemanticState == null ? {} : { defaultSemanticState: this.props.defaultSemanticState },
613
- ...this.props.onFilterChange == null ? {} : { onFilterChange: this.props.onFilterChange }
614
- },
615
- String(r.field)
616
- )) }) });
617
- }
618
- }
619
- o(H, "dependencies", [N]);
620
- function Ke(t, { sort: r = null, filters: e = {} } = {}) {
621
- qe(t), r != null && (Z(r), t.searchParams.set("sort", `${r.field}:${r.direction}`));
622
- for (const [s, i] of Object.entries(e))
623
- for (const [n, a] of i) {
624
- if (!De(a))
625
- throw new TypeError(`Unknown filter mode for ${s}: ${String(a)}`);
626
- t.searchParams.append(
627
- "filter",
628
- `${s}:${a}:${JSON.stringify(n)}`
629
- );
630
- }
631
- return t;
632
- }
633
- function Ce(t, r, e) {
634
- if (!Array.isArray(t)) throw new TypeError("Local table data must be an array");
635
- const s = t.filter((n) => Re(n, e));
636
- if (r == null) return s;
637
- Z(r);
638
- const i = r.direction === "asc" ? 1 : -1;
639
- return [...s].sort((n, a) => Ne($(n, r.field), $(a, r.field)) * i);
640
- }
641
- function Re(t, r) {
642
- for (const [e, s] of Object.entries(r)) {
643
- const i = $(t, e);
644
- if (s.filter(([, d]) => d === K.Deny).some(([d]) => Object.is(d, i))) return !1;
645
- const a = s.filter(([, d]) => d === K.Require);
646
- if (a.length > 0 && !a.some(([d]) => Object.is(d, i))) return !1;
647
- const l = s.filter(([, d]) => d === K.Prefer);
648
- if (l.length > 0 && !l.some(([d]) => Object.is(d, i))) return !1;
649
- }
650
- return !0;
651
- }
652
- function Z(t) {
653
- if (t == null || typeof t != "object" || typeof Reflect.get(t, "field") != "string" || !Me(Reflect.get(t, "direction")))
654
- throw new TypeError("Table sort must contain a field and asc/desc direction");
655
- }
656
- function Me(t) {
657
- return t === "asc" || t === "desc";
658
- }
659
- function De(t) {
660
- return Object.values(K).some((r) => r === t);
661
- }
662
- function Ne(t, r) {
663
- return Object.is(t, r) ? 0 : t == null ? -1 : r == null ? 1 : typeof t == "number" && typeof r == "number" ? t - r : String(t).localeCompare(String(r));
664
- }
665
- function $(t, r) {
666
- if (!(t == null || typeof t != "object" && typeof t != "function"))
667
- return Reflect.get(t, r);
668
- }
669
- function qe(t) {
670
- if (t == null || typeof t != "object" && typeof t != "function" || typeof Reflect.get(t, "toString") != "function")
671
- throw new TypeError("Table serializer requires a URL");
672
- const r = Reflect.get(t, "searchParams");
673
- if (r == null || typeof Reflect.get(r, "set") != "function" || typeof Reflect.get(r, "append") != "function")
674
- throw new TypeError("Table serializer requires URL search parameters");
675
- }
676
- class j extends w {
677
- constructor(e) {
678
- super(e);
679
- o(this, "columns");
680
- o(this, "rowKey");
681
- o(this, "sortEmitter");
682
- o(this, "filtersEmitter");
683
- o(this, "selectedItemsEmitter");
684
- o(this, "selectionHandler");
685
- o(this, "query", null);
686
- o(this, "dataSource", null);
687
- o(this, "ownedSelectedItemsEmitter");
688
- o(this, "ownedDataSource", null);
689
- o(this, "ownsQuery", !1);
690
- o(this, "queryArgs", []);
691
- if (e.mode !== "local" && e.mode !== "remote")
692
- throw new TypeError("DataTable mode must be local or remote");
693
- this.columns = Oe(e.columns), this.rowKey = je(e.rowKey), this.sortEmitter = new g(null, {
694
- owner: this,
695
- purpose: "table sort"
696
- }), this.filtersEmitter = new g({}, {
697
- owner: this,
698
- purpose: "table filters"
699
- }), this.ownedSelectedItemsEmitter = e.selectedItemsEmitter == null ? new g([], { owner: this, purpose: "selected table rows" }) : null, this.selectedItemsEmitter = e.selectedItemsEmitter ?? this.ownedSelectedItemsEmitter, this.selectionHandler = Y({
700
- owner: this,
701
- multiSelect: e.multiSelect ?? !1,
702
- selectedItemsEmitter: this.selectedItemsEmitter,
703
- getItems: () => {
704
- var s;
705
- return ((s = this.query) == null ? void 0 : s.get()) ?? [];
706
- },
707
- getKey: this.rowKey
708
- });
709
- }
710
- initialize() {
711
- this.query = this.props.mode === "local" ? this.createLocalQuery() : this.createRemoteQuery(), this.watch(this.query, this.selectedItemsEmitter);
712
- }
713
- createLocalQuery() {
714
- const e = this.props.data ?? [];
715
- let s;
716
- return ee(e) ? s = e : (this.ownedDataSource = new g(e, {
717
- owner: this,
718
- purpose: "local table data"
719
- }), s = this.ownedDataSource), this.dataSource = s, this.ownsQuery = !0, new oe(
720
- [s, this.sortEmitter, this.filtersEmitter],
721
- ([i, n, a]) => Ce(i, n, a),
722
- { owner: this, purpose: "local table view" }
723
- );
724
- }
725
- createRemoteQuery() {
726
- if (this.props.query != null)
727
- return Ae(this.props.query), this.props.query;
728
- const e = this.props.queryHandler ?? this.createRestHandler();
729
- if (e == null || typeof e.fetch != "function")
730
- throw new TypeError("Remote DataTable requires query, queryHandler, or queryUrl");
731
- const s = new V("sort", this.sortEmitter, {
732
- owner: this,
733
- purpose: "remote table sort argument"
734
- }), i = new V("filters", this.filtersEmitter, {
735
- owner: this,
736
- purpose: "remote table filters argument"
737
- });
738
- this.queryArgs.push(s, i), this.ownsQuery = !0;
739
- const n = { sort: s, filters: i };
740
- return new ae({
741
- handler: e,
742
- args: n,
743
- owner: this,
744
- purpose: "remote table query",
745
- keepPreviousValue: !0
746
- });
747
- }
748
- createRestHandler() {
749
- if (this.props.queryUrl == null) return null;
750
- const e = {
751
- url: this.props.queryUrl,
752
- serialize: this.props.serializeQuery ?? Ke
753
- };
754
- return this.props.baseUrl != null && (e.baseUrl = this.props.baseUrl), this.props.fetch != null && (e.fetch = this.props.fetch), new le(e);
755
- }
756
- render() {
757
- var d, h, u, f;
758
- const e = ((d = this.query) == null ? void 0 : d.get()) ?? [];
759
- if (!Array.isArray(e)) throw new TypeError("DataTable query value must be an array");
760
- const s = ((h = this.query) == null ? void 0 : h.getFetchState()) ?? m.Initial, i = (u = this.query) == null ? void 0 : u.getError(), n = s === m.Initial || s === m.Loading, a = new Set(
761
- this.selectedItemsEmitter.get().map((p, y) => this.rowKey(p, y))
762
- ), l = this.Host;
763
- return /* @__PURE__ */ b(
764
- l,
765
- {
766
- className: I(this.props) || null,
767
- "data-loading": n ? "" : null,
768
- "data-error": s === m.Error ? "" : null,
769
- children: [
770
- n ? /* @__PURE__ */ c("p", { role: "status", "data-part": "status", children: "Loading rows…" }) : null,
771
- s === m.Error ? /* @__PURE__ */ b("div", { "data-part": "error", role: "alert", children: [
772
- /* @__PURE__ */ c("span", { children: Fe(i, "Unable to load rows") }),
773
- typeof ((f = this.query) == null ? void 0 : f.retry) == "function" ? /* @__PURE__ */ c(
774
- "button",
775
- {
776
- type: "button",
777
- onClick: () => {
778
- var p, y;
779
- return (y = (p = this.query) == null ? void 0 : p.retry) == null ? void 0 : y.call(p, "table retry");
780
- },
781
- children: "Retry"
782
- }
783
- ) : null
784
- ] }) : null,
785
- /* @__PURE__ */ b("table", { "data-part": "table", "aria-busy": n ? "true" : null, children: [
786
- this.props.caption == null ? null : /* @__PURE__ */ c("caption", { children: this.props.caption }),
787
- /* @__PURE__ */ c(
788
- H,
789
- {
790
- columns: this.columns,
791
- sortEmitter: this.sortEmitter,
792
- filtersEmitter: this.filtersEmitter,
793
- ...this.props.filterModes == null ? {} : { filterModes: this.props.filterModes },
794
- ...this.props.defaultSemanticState == null ? {} : { defaultSemanticState: this.props.defaultSemanticState },
795
- ...this.props.onFilterChange == null ? {} : { onFilterChange: this.props.onFilterChange }
796
- },
797
- "header"
798
- ),
799
- /* @__PURE__ */ c("tbody", { children: e.length > 0 ? e.map((p, y) => this.renderRow(p, y, a)) : n ? this.renderPlaceholders() : s === m.Error ? null : /* @__PURE__ */ c("tr", { children: /* @__PURE__ */ c("td", { colSpan: this.columns.length, children: this.props.emptyMessage ?? "No rows" }) }, "empty") })
800
- ] })
801
- ]
802
- }
803
- );
804
- }
805
- renderRow(e, s, i) {
806
- const n = this.rowKey(e, s), a = i.has(n);
807
- return /* @__PURE__ */ c(
808
- "tr",
809
- {
810
- "data-fray-selectable-row": "",
811
- "data-index": s,
812
- "aria-selected": String(a),
813
- tabIndex: s === 0 ? 0 : -1,
814
- children: this.columns.map((l) => /* @__PURE__ */ c("td", { children: l.render ? l.render(e, s) : Le(e[l.field]) }, String(l.field)))
815
- },
816
- String(n)
817
- );
818
- }
819
- renderPlaceholders() {
820
- const e = this.props.placeholderCount ?? 5;
821
- return Array.from({ length: e }, (s, i) => /* @__PURE__ */ c("tr", { children: this.columns.map((n, a) => /* @__PURE__ */ c("td", { children: /* @__PURE__ */ c(
822
- E,
823
- {
824
- width: 45 + (i + a) % 6 * 8
825
- }
826
- ) }, String(n.field))) }, `placeholder-${i}`));
827
- }
828
- afterUpdate(e) {
829
- const s = e instanceof Element ? e.querySelectorAll("tbody [data-fray-selectable-row]") : [];
830
- this.selectionHandler.rowsUpdated(s);
831
- }
832
- getSelectedRows() {
833
- return this.selectionHandler.getSelectedItems();
834
- }
835
- getSelectedRowsEmitter() {
836
- return this.selectedItemsEmitter;
837
- }
838
- onDestroy() {
839
- var e, s, i, n;
840
- this.selectionHandler.destroy(), this.ownsQuery && ((s = (e = this.query) == null ? void 0 : e.dispose) == null || s.call(e));
841
- for (const a of this.queryArgs) a.dispose();
842
- (i = this.ownedDataSource) == null || i.dispose(), (n = this.ownedSelectedItemsEmitter) == null || n.dispose(), this.sortEmitter.dispose(), this.filtersEmitter.dispose();
843
- }
844
- }
845
- o(j, "dependencies", [E, H]), o(j, "hostName", "data-table"), o(j, "standaloneHostName", "data-table"), o(j, "css", x`
846
- & {
847
- overflow: auto;
848
- color: var(--ui-text-color);
849
- }
850
-
851
- & > table {
852
- width: 100%;
853
- border-collapse: collapse;
854
- }
855
-
856
- & th,
857
- & td {
858
- padding: var(--ui-padding-v) var(--ui-padding-h);
859
- text-align: start;
860
- }
861
-
862
- & tbody tr[data-fray-selectable-row] {
863
- cursor: default;
864
- user-select: none;
865
- }
866
-
867
- & tbody tr:nth-child(odd) {
868
- background: var(--fray-table-row-background, transparent);
869
- }
870
-
871
- & tbody tr:nth-child(even) {
872
- background: var(--fray-table-row-alt-background, transparent);
873
- }
874
-
875
- & tbody tr[data-fray-selectable-row]:hover {
876
- background: var(--fray-row-hover-background, var(--button-background-hover));
877
- }
878
-
879
- & tbody tr[data-fray-selectable-row]:focus-visible {
880
- outline: 2px solid var(--fray-color-focus, var(--ui-accent-color));
881
- outline-offset: -2px;
882
- }
883
-
884
- & tbody tr[data-fray-selectable-row][aria-selected="true"] {
885
- color: var(--fray-selection-color, var(--toggle-selected-text));
886
- background: var(--fray-selection-background, var(--toggle-selected-bg));
887
- }
888
-
889
- & > [data-part="error"] {
890
- color: var(--error-color);
891
- }
892
- `);
893
- function Oe(t) {
894
- if (!Array.isArray(t) || t.length === 0)
895
- throw new TypeError("DataTable columns must be a non-empty array");
896
- const r = /* @__PURE__ */ new Set();
897
- return t.map((e) => {
898
- if (e == null || typeof e != "object")
899
- throw new TypeError("Every DataTable column requires a field");
900
- const s = Reflect.get(e, "field");
901
- if (typeof s != "string" || s.length === 0)
902
- throw new TypeError("Every DataTable column requires a field");
903
- if (r.has(s)) throw new Error(`Duplicate DataTable column: ${s}`);
904
- r.add(s);
905
- const i = Reflect.get(e, "render");
906
- if (i != null && typeof i != "function")
907
- throw new TypeError(`DataTable column ${s} render must be a function`);
908
- return e;
909
- });
910
- }
911
- function je(t) {
912
- if (t == null) return z;
913
- if (typeof t == "function") return t;
914
- if (typeof t == "string" && t.length > 0)
915
- return (r, e) => {
916
- const s = r[t];
917
- if (s == null)
918
- throw new TypeError(`DataTable row at index ${e} lacks ${t}`);
919
- return s;
920
- };
921
- throw new TypeError("DataTable rowKey must be a function or property name");
922
- }
923
- function ee(t) {
924
- return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function" && typeof Reflect.get(t, "getFetchState") == "function" && typeof Reflect.get(t, "getError") == "function";
925
- }
926
- function Ae(t) {
927
- if (!ee(t))
928
- throw new TypeError("DataTable query must be an emitter");
929
- }
930
- function Le(t) {
931
- return t == null || typeof t == "string" || typeof t == "number" ? t : String(t);
932
- }
933
- function Fe(t, r) {
934
- return t instanceof Error ? t.message : t == null ? r : String(t);
935
- }
936
- class te extends w {
937
- render() {
938
- return this.props.children ?? [];
939
- }
940
- }
941
- class A extends w {
942
- constructor(e) {
943
- super(e);
944
- o(this, "nodesEmitter");
945
- o(this, "selectedKeyEmitter");
946
- o(this, "expandedKeysEmitter");
947
- o(this, "ownedNodesEmitter");
948
- o(this, "ownedSelectedEmitter");
949
- o(this, "ownedExpandedEmitter");
950
- o(this, "focusedKey", null);
951
- o(this, "typeahead", "");
952
- o(this, "typeaheadTimer", null);
953
- if (ze(e.nodes))
954
- this.nodesEmitter = e.nodes, this.ownedNodesEmitter = null;
955
- else {
956
- const s = e.nodes ?? re(e.children);
957
- this.ownedNodesEmitter = new g(s, {
958
- owner: this,
959
- purpose: "tree nodes"
960
- }), this.nodesEmitter = this.ownedNodesEmitter;
961
- }
962
- this.ownedSelectedEmitter = e.selectedKeyEmitter == null ? new g(null, { owner: this, purpose: "selected tree key" }) : null, this.selectedKeyEmitter = e.selectedKeyEmitter ?? this.ownedSelectedEmitter, this.ownedExpandedEmitter = e.expandedKeysEmitter == null ? new g([], { owner: this, purpose: "expanded tree keys" }) : null, this.expandedKeysEmitter = e.expandedKeysEmitter ?? this.ownedExpandedEmitter;
963
- }
964
- initialize() {
965
- this.reconcile(this.nodesEmitter.get()), this.watch(this.nodesEmitter, this.selectedKeyEmitter, this.expandedKeysEmitter), this.onCleanup(this.nodesEmitter.subscribe(({ value: e }) => this.reconcile(e), {
966
- emitCurrent: !1
967
- }));
968
- }
969
- render() {
970
- const e = this.nodesEmitter.get();
971
- B(e);
972
- const s = new Set(this.expandedKeysEmitter.get()), i = _(e, s), n = this.selectedKeyEmitter.get(), a = i.find(({ node: d }) => Object.is(d.id, this.focusedKey)) ?? i.find(({ node: d }) => Object.is(d.id, n)) ?? i[0] ?? null;
973
- this.focusedKey = (a == null ? void 0 : a.node.id) ?? null;
974
- const l = this.Host;
975
- return /* @__PURE__ */ c(l, { className: I(this.props) || null, children: i.length === 0 ? /* @__PURE__ */ c("p", { role: "status", "data-part": "empty", children: "No tree items" }) : /* @__PURE__ */ c("div", { role: "tree", "aria-label": this.props.label, "data-part": "tree", children: i.map((d, h) => {
976
- var k, R, M;
977
- const { node: u, depth: f, position: p, setSize: y } = d, S = (((k = u.children) == null ? void 0 : k.length) ?? 0) > 0, C = S && s.has(u.id), q = Object.is(u.id, n), v = ((M = (R = this.props).renderItem) == null ? void 0 : M.call(R, u, f)) ?? u.label;
978
- return /* @__PURE__ */ b(
979
- "div",
980
- {
981
- role: "treeitem",
982
- "data-part": "item",
983
- "data-index": h,
984
- "data-depth": f,
985
- "aria-level": f + 1,
986
- "aria-posinset": p,
987
- "aria-setsize": y,
988
- "aria-expanded": S ? String(C) : null,
989
- "aria-selected": String(q),
990
- tabIndex: Object.is(u.id, a == null ? void 0 : a.node.id) ? 0 : -1,
991
- style: { "--tree-depth": f },
992
- onClick: (O) => {
993
- if (this.focusedKey = u.id, Ue(O.target) && S) {
994
- this.toggleExpanded(u.id), this.focusRow(u.id);
995
- return;
996
- }
997
- this.selectNode(u, O);
998
- },
999
- onFocus: () => this.focusedKey = u.id,
1000
- onKeyDown: (O) => this.handleKeyDown(O, h, i),
1001
- children: [
1002
- /* @__PURE__ */ c(
1003
- "span",
1004
- {
1005
- "data-part": "expander",
1006
- "data-expandable": S ? "" : null,
1007
- "aria-hidden": "true",
1008
- children: S ? C ? "▾" : "▸" : "•"
1009
- }
1010
- ),
1011
- /* @__PURE__ */ c("span", { "data-part": "label", children: v })
1012
- ]
1013
- },
1014
- u.id
1015
- );
1016
- }) }) });
1017
- }
1018
- onDestroy() {
1019
- var e, s, i;
1020
- this.typeaheadTimer != null && clearTimeout(this.typeaheadTimer), (e = this.ownedNodesEmitter) == null || e.dispose(), (s = this.ownedSelectedEmitter) == null || s.dispose(), (i = this.ownedExpandedEmitter) == null || i.dispose();
1021
- }
1022
- reconcile(e) {
1023
- B(e);
1024
- const s = new Set(se(e).map(({ node: l }) => l.id)), i = this.selectedKeyEmitter.get();
1025
- this.ownedSelectedEmitter != null && i != null && !s.has(i) && this.selectedKeyEmitter.set(null, "selected tree item removed");
1026
- const n = this.expandedKeysEmitter.get(), a = n.filter((l) => s.has(l));
1027
- this.ownedExpandedEmitter != null && !$e(n, a) && this.expandedKeysEmitter.set(a, "removed tree expansions reconciled"), this.focusedKey != null && !s.has(this.focusedKey) && (this.focusedKey = null);
1028
- }
1029
- selectNode(e, s) {
1030
- this.selectedKeyEmitter.set(e.id, "tree item selected"), W(this.props.onSelect, e, s), this.focusRow(e.id);
1031
- }
1032
- toggleExpanded(e) {
1033
- const s = this.expandedKeysEmitter.get(), i = s.some((n) => Object.is(n, e));
1034
- this.expandedKeysEmitter.set(
1035
- i ? s.filter((n) => !Object.is(n, e)) : [...s, e],
1036
- i ? "tree item collapsed" : "tree item expanded"
1037
- );
1038
- }
1039
- handleKeyDown(e, s, i) {
1040
- var a, l, d, h;
1041
- const n = i[s];
1042
- if (n != null) {
1043
- if (e.key === "ArrowDown") return this.move(e, (a = i[s + 1]) == null ? void 0 : a.node.id);
1044
- if (e.key === "ArrowUp") return this.move(e, (l = i[s - 1]) == null ? void 0 : l.node.id);
1045
- if (e.key === "Home") return this.move(e, (d = i[0]) == null ? void 0 : d.node.id);
1046
- if (e.key === "End") return this.move(e, (h = i.at(-1)) == null ? void 0 : h.node.id);
1047
- if (e.key === "ArrowRight") {
1048
- e.preventDefault();
1049
- const u = n.node.children ?? [];
1050
- if (u.length === 0) return;
1051
- this.expandedKeysEmitter.get().some((p) => Object.is(p, n.node.id)) ? this.focusRow(u[0].id) : this.toggleExpanded(n.node.id);
1052
- return;
1053
- }
1054
- if (e.key === "ArrowLeft") {
1055
- e.preventDefault(), this.expandedKeysEmitter.get().some((f) => Object.is(f, n.node.id)) ? this.toggleExpanded(n.node.id) : n.parentId != null && this.focusRow(n.parentId);
1056
- return;
1057
- }
1058
- if (e.key === "Enter" || e.key === " ") {
1059
- e.preventDefault(), this.selectNode(n.node, e);
1060
- return;
1061
- }
1062
- e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && this.handleTypeahead(e, i, s);
1063
- }
1064
- }
1065
- move(e, s) {
1066
- s !== void 0 && (e.preventDefault(), this.focusRow(s));
1067
- }
1068
- focusRow(e) {
1069
- var i;
1070
- this.focusedKey = e;
1071
- const s = this.dom instanceof Element ? [...this.dom.querySelectorAll('[role="treeitem"]')] : [];
1072
- for (const n of s) {
1073
- const a = Number(n.dataset.index), l = _(
1074
- this.nodesEmitter.get(),
1075
- new Set(this.expandedKeysEmitter.get())
1076
- ), d = Object.is((i = l[a]) == null ? void 0 : i.node.id, e);
1077
- n.tabIndex = d ? 0 : -1, d && n.focus();
1078
- }
1079
- }
1080
- handleTypeahead(e, s, i) {
1081
- e.preventDefault(), this.typeaheadTimer != null && clearTimeout(this.typeaheadTimer), this.typeahead += e.key.toLocaleLowerCase(), this.typeaheadTimer = setTimeout(() => {
1082
- this.typeahead = "", this.typeaheadTimer = null;
1083
- }, 650);
1084
- const a = [...s.slice(i + 1), ...s.slice(0, i + 1)].find(({ node: l }) => He(l).toLocaleLowerCase().startsWith(this.typeahead));
1085
- a != null && this.focusRow(a.node.id);
1086
- }
1087
- }
1088
- o(A, "dependencies", [te]), o(A, "hostName", "tree-view"), o(A, "standaloneHostName", "tree-view"), o(A, "css", x`
1089
- & {
1090
- display: flex;
1091
- flex-direction: column;
1092
- min-width: 0;
1093
- min-height: 0;
1094
- overflow: auto;
1095
- }
1096
-
1097
- & > [data-part="tree"] {
1098
- display: grid;
1099
- align-content: start;
1100
- }
1101
-
1102
- & [data-part="item"] {
1103
- display: flex;
1104
- align-items: flex-start;
1105
- gap: 0.35rem;
1106
- min-width: 0;
1107
- padding: 0.38rem 0.5rem;
1108
- padding-inline-start: calc(0.5rem + var(--tree-depth) * 1.1rem);
1109
- cursor: default;
1110
- user-select: none;
1111
- }
1112
-
1113
- & [data-part="item"]:hover {
1114
- background: var(--button-background-hover);
1115
- }
1116
-
1117
- & [data-part="item"]:focus-visible {
1118
- outline: 2px solid var(--ui-accent-color);
1119
- outline-offset: -2px;
1120
- }
1121
-
1122
- & [data-part="item"][aria-selected="true"] {
1123
- color: var(--toggle-selected-text);
1124
- background: var(--toggle-selected-bg);
1125
- }
1126
-
1127
- & [data-part="expander"] {
1128
- flex: 0 0 1rem;
1129
- text-align: center;
1130
- }
1131
-
1132
- & [data-part="expander"][data-expandable] {
1133
- cursor: pointer;
1134
- }
1135
-
1136
- & [data-part="label"] {
1137
- min-width: 0;
1138
- overflow-wrap: anywhere;
1139
- }
1140
-
1141
- & > [data-part="empty"] {
1142
- margin: 0;
1143
- padding: var(--ui-padding, 0.75rem);
1144
- }
1145
-
1146
- @media (forced-colors: active) {
1147
- & [data-part="item"][aria-selected="true"] {
1148
- outline: 2px solid Highlight;
1149
- forced-color-adjust: auto;
1150
- }
1151
- }
1152
- `);
1153
- function re(t) {
1154
- return (Array.isArray(t) ? t : t == null ? [] : [t]).filter((e) => U(e) && e.type === te).map((e) => {
1155
- if (!U(e)) throw new TypeError("TreeView children must be TreeItem nodes");
1156
- const s = e.props;
1157
- return {
1158
- id: s.id,
1159
- label: s.label,
1160
- ...s.textValue == null ? {} : { textValue: s.textValue },
1161
- ...s.value === void 0 ? {} : { value: s.value },
1162
- children: re(s.children)
1163
- };
1164
- });
1165
- }
1166
- function _(t, r) {
1167
- const e = [], s = (i, n, a) => {
1168
- i.forEach((l, d) => {
1169
- var h;
1170
- e.push({ node: l, depth: n, parentId: a, position: d + 1, setSize: i.length }), (((h = l.children) == null ? void 0 : h.length) ?? 0) > 0 && r.has(l.id) && s(l.children ?? [], n + 1, l.id);
1171
- });
1172
- };
1173
- return s(t, 0, null), e;
1174
- }
1175
- function se(t) {
1176
- const r = /* @__PURE__ */ new Set(), e = [], s = (i, n, a) => {
1177
- i.forEach((l, d) => {
1178
- if (r.has(l.id)) throw new Error(`Duplicate tree item id: ${String(l.id)}`);
1179
- r.add(l.id), e.push({ node: l, depth: n, parentId: a, position: d + 1, setSize: i.length }), s(l.children ?? [], n + 1, l.id);
1180
- });
1181
- };
1182
- return s(t, 0, null), e;
1183
- }
1184
- function B(t) {
1185
- if (!Array.isArray(t)) throw new TypeError("TreeView nodes must be an array");
1186
- for (const { node: r } of se(t)) {
1187
- if (r == null || typeof r != "object" || r.id == null)
1188
- throw new TypeError("Each tree node requires an id");
1189
- if (!Array.isArray(r.children ?? []))
1190
- throw new TypeError(`Tree node ${String(r.id)} children must be an array`);
1191
- }
1192
- }
1193
- function He(t) {
1194
- return t.textValue != null ? t.textValue : typeof t.label == "string" || typeof t.label == "number" ? String(t.label) : String(t.id);
1195
- }
1196
- function $e(t, r) {
1197
- return t.length === r.length && t.every((e, s) => Object.is(e, r[s]));
1198
- }
1199
- function ze(t) {
1200
- return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function";
1201
- }
1202
- function Ue(t) {
1203
- return t instanceof Element && t.closest('[data-part="expander"]') != null;
1204
- }
1205
- class G extends w {
1206
- constructor(e) {
1207
- super(e);
1208
- o(this, "openEmitter");
1209
- o(this, "dialogId");
1210
- o(this, "titleId");
1211
- o(this, "descriptionId");
1212
- o(this, "dialogElement", null);
1213
- o(this, "restoreFocusTo", null);
1214
- o(this, "synchronizedOpen", !1);
1215
- this.openEmitter = de(this, e, !1, "dialog open state"), this.dialogId = ce("dialog", e.id), this.titleId = `${this.dialogId}-title`, this.descriptionId = `${this.dialogId}-description`;
1216
- }
1217
- initialize() {
1218
- this.watch(this.openEmitter);
1219
- }
1220
- render() {
1221
- const {
1222
- title: e,
1223
- description: s,
1224
- actions: i,
1225
- closeLabel: n = "Close",
1226
- showCloseButton: a = !0,
1227
- children: l = []
1228
- } = this.props;
1229
- return /* @__PURE__ */ b(
1230
- "dialog",
1231
- {
1232
- id: this.dialogId,
1233
- className: I(this.props) || void 0,
1234
- "data-fray-component": "dialog",
1235
- "aria-labelledby": this.titleId,
1236
- "aria-describedby": s == null ? null : this.descriptionId,
1237
- "aria-modal": "true",
1238
- ref: (d) => this.dialogElement = d,
1239
- children: [
1240
- /* @__PURE__ */ c("header", { "data-part": "header", children: /* @__PURE__ */ c("h2", { id: this.titleId, children: e }) }),
1241
- s == null ? null : /* @__PURE__ */ c("p", { id: this.descriptionId, "data-part": "description", children: s }),
1242
- /* @__PURE__ */ c("div", { "data-part": "content", children: l }),
1243
- i == null && !a ? null : /* @__PURE__ */ b("footer", { "data-part": "actions", children: [
1244
- i,
1245
- a ? /* @__PURE__ */ c(
1246
- Q,
1247
- {
1248
- label: n,
1249
- onClick: () => this.requestClose()
1250
- }
1251
- ) : null
1252
- ] })
1253
- ]
1254
- }
1255
- );
1256
- }
1257
- afterMount() {
1258
- const e = this.dialogElement;
1259
- e != null && (this.listen(e, "cancel", (s) => {
1260
- s.preventDefault(), this.requestClose();
1261
- }), this.listen(e, "close", () => {
1262
- this.openEmitter.get() && this.openEmitter.set(!1, "native dialog closed"), this.finishClose();
1263
- }), this.syncOpenState());
1264
- }
1265
- afterUpdate() {
1266
- this.syncOpenState();
1267
- }
1268
- close() {
1269
- this.requestClose();
1270
- }
1271
- onDestroy() {
1272
- const e = this.dialogElement;
1273
- (e == null ? void 0 : e.open) === !0 && typeof e.close == "function" && e.close(), this.finishClose(), this.dialogElement = null;
1274
- }
1275
- requestClose() {
1276
- this.openEmitter.get() && this.openEmitter.set(!1, "dialog close requested");
1277
- }
1278
- syncOpenState() {
1279
- const e = this.dialogElement;
1280
- if (e == null) return;
1281
- const s = this.openEmitter.get();
1282
- if (s && !this.synchronizedOpen) {
1283
- const i = document.activeElement;
1284
- this.restoreFocusTo = i instanceof HTMLElement ? i : null, Ve(e), this.synchronizedOpen = !0, Qe(e, this.props.initialFocusRef);
1285
- return;
1286
- }
1287
- !s && this.synchronizedOpen && (e.open && typeof e.close == "function" ? e.close() : e.removeAttribute("open"), this.finishClose());
1288
- }
1289
- finishClose() {
1290
- if (!this.synchronizedOpen && this.restoreFocusTo == null) return;
1291
- this.synchronizedOpen = !1;
1292
- const e = this.restoreFocusTo;
1293
- this.restoreFocusTo = null, (e == null ? void 0 : e.isConnected) === !0 && e.focus(), W(this.props.onClose);
1294
- }
1295
- }
1296
- o(G, "dependencies", [Q]), o(G, "css", x`
1297
- dialog[data-fray-component="dialog"] {
1298
- width: min(38rem, calc(100vw - 2rem));
1299
- max-height: min(42rem, calc(100dvh - 2rem));
1300
- padding: 0;
1301
- color: var(--fray-panel-color, var(--ui-text-color));
1302
- background: var(--fray-panel-background, var(--panel-bg));
1303
- border: var(--fray-panel-border, var(--panel-border));
1304
- border-radius: var(--fray-panel-radius, var(--panel-radius));
1305
- box-shadow: var(--fray-dialog-shadow, var(--fray-panel-shadow));
1306
- }
1307
-
1308
- dialog[data-fray-component="dialog"]::backdrop {
1309
- background: var(--fray-dialog-backdrop-background);
1310
- }
1311
-
1312
- dialog[data-fray-component="dialog"] > [data-part] {
1313
- padding: var(--panel-padding, 0.75rem);
1314
- }
1315
-
1316
- dialog[data-fray-component="dialog"] > [data-part="header"] {
1317
- color: var(
1318
- --fray-dialog-header-color,
1319
- var(--fray-section-header-color, var(--fray-header-color))
1320
- );
1321
- background: var(
1322
- --fray-dialog-header-background,
1323
- var(--fray-section-header-background, var(--fray-header-background))
1324
- );
1325
- border-block-end: var(
1326
- --fray-section-header-border,
1327
- var(--fray-header-border)
1328
- );
1329
- }
1330
-
1331
- dialog[data-fray-component="dialog"] > [data-part="header"] h2,
1332
- dialog[data-fray-component="dialog"] > [data-part="description"] {
1333
- margin: 0;
1334
- }
1335
-
1336
- dialog[data-fray-component="dialog"] > [data-part="content"] {
1337
- overflow: auto;
1338
- }
1339
-
1340
- dialog[data-fray-component="dialog"] > [data-part="actions"] {
1341
- display: flex;
1342
- justify-content: flex-end;
1343
- gap: var(--spacing-small, 0.5rem);
1344
- border-block-start: 1px solid var(--ui-border-color);
1345
- }
1346
-
1347
- @media (prefers-reduced-motion: no-preference) {
1348
- dialog[data-fray-component="dialog"][open] {
1349
- animation: fray-dialog-enter 120ms ease-out;
1350
- }
1351
- }
1352
-
1353
- @keyframes fray-dialog-enter {
1354
- from {
1355
- transform: translateY(0.4rem);
1356
- }
1357
- }
1358
-
1359
- @media (forced-colors: active) {
1360
- dialog[data-fray-component="dialog"] {
1361
- border: 2px solid CanvasText;
1362
- }
1363
- }
1364
- `);
1365
- function Ve(t) {
1366
- if (!t.open) {
1367
- if (typeof t.showModal == "function") {
1368
- t.showModal();
1369
- return;
1370
- }
1371
- t.setAttribute("open", "");
1372
- }
1373
- }
1374
- function Qe(t, r) {
1375
- const s = (r == null || typeof r == "function" ? null : r.current) ?? t.querySelector(
1376
- '[autofocus], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
1377
- );
1378
- s == null || s.focus();
1379
- }
1380
- export {
1381
- J as BaseSelectionHandler,
1382
- j as DataTable,
1383
- G as Dialog,
1384
- T as FilterPanel,
1385
- D as ListView,
1386
- pe as MultiSelectionHandler,
1387
- E as Placeholder,
1388
- ue as SingleSelectionHandler,
1389
- H as TableHeader,
1390
- N as TableHeaderCell,
1391
- te as TreeItem,
1392
- A as TreeView,
1393
- Ce as applyLocalTableState,
1394
- Z as assertSort,
1395
- Y as createSelectionHandler,
1396
- z as defaultItemKey,
1397
- Ke as serializeTableQuery
1398
- };
1399
- //# sourceMappingURL=experimental.js.map