@sylwellsoftware/fray 0.1.0-alpha.1 → 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 (75) hide show
  1. package/README.md +324 -21
  2. package/colors/README.md +15 -0
  3. package/colors/gray/colors.css +29 -0
  4. package/colors/green/colors.css +29 -0
  5. package/colors/iceblue/colors.css +29 -0
  6. package/colors/ocean/colors.css +29 -0
  7. package/colors/orange/colors.css +29 -0
  8. package/colors/purple/colors.css +29 -0
  9. package/colors/red/colors.css +29 -0
  10. package/colors/yellow/colors.css +29 -0
  11. package/dist/Components/Placeholder.d.ts +1 -1
  12. package/dist/Components/Placeholder.d.ts.map +1 -1
  13. package/dist/Components/controlUtils.d.ts.map +1 -1
  14. package/dist/Components/data/filterState.d.ts +38 -0
  15. package/dist/Components/data/filterState.d.ts.map +1 -0
  16. package/dist/Components/data/listview/listview.d.ts +16 -5
  17. package/dist/Components/data/listview/listview.d.ts.map +1 -1
  18. package/dist/Components/data/selectionhandler.d.ts +24 -5
  19. package/dist/Components/data/selectionhandler.d.ts.map +1 -1
  20. package/dist/Components/data/table/DataTable.d.ts +36 -30
  21. package/dist/Components/data/table/DataTable.d.ts.map +1 -1
  22. package/dist/Components/data/table/FilterPanel.d.ts +8 -1
  23. package/dist/Components/data/table/FilterPanel.d.ts.map +1 -1
  24. package/dist/Components/data/table/TableHeaderCell.d.ts.map +1 -1
  25. package/dist/Components/data/table/tableDataSource.d.ts +49 -0
  26. package/dist/Components/data/table/tableDataSource.d.ts.map +1 -0
  27. package/dist/Components/data/table/tableQuery.d.ts +6 -2
  28. package/dist/Components/data/table/tableQuery.d.ts.map +1 -1
  29. package/dist/Components/data/treeview/treeModel.d.ts +23 -0
  30. package/dist/Components/data/treeview/treeModel.d.ts.map +1 -0
  31. package/dist/Components/data/treeview/treeview.d.ts +1 -1
  32. package/dist/Components/data/treeview/treeview.d.ts.map +1 -1
  33. package/dist/Components/dialog/dialog.d.ts +1 -1
  34. package/dist/Components/dialog/dialog.d.ts.map +1 -1
  35. package/dist/Components/layout/panel.d.ts.map +1 -1
  36. package/dist/Components/layout/tabpanel/tabline.d.ts.map +1 -1
  37. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts +1 -1
  38. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts.map +1 -1
  39. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts +2 -2
  40. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts.map +1 -1
  41. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts +2 -2
  42. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts.map +1 -1
  43. package/dist/Components/lineinputs/toggle.d.ts.map +1 -1
  44. package/dist/Components/status/progressBar.d.ts.map +1 -1
  45. package/dist/Components/theme/stylesheetPicker.d.ts +40 -0
  46. package/dist/Components/theme/stylesheetPicker.d.ts.map +1 -0
  47. package/dist/index.d.ts +16 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2807 -559
  50. package/dist/index.js.map +1 -1
  51. package/dist/{jsx-dev-runtime-CarwHDyL.js → jsx-dev-runtime-DukiDpV9.js} +202 -214
  52. package/dist/jsx-dev-runtime-DukiDpV9.js.map +1 -0
  53. package/dist/jsx-dev-runtime.js +1 -1
  54. package/dist/jsx-runtime.js +1 -1
  55. package/dist/styling/baseStyleDefinitions.d.ts +3 -0
  56. package/dist/styling/baseStyleDefinitions.d.ts.map +1 -1
  57. package/dist/styling/styleRegistry.d.ts.map +1 -1
  58. package/dist/styling/theme.d.ts +27 -0
  59. package/dist/styling/theme.d.ts.map +1 -0
  60. package/dist/util/filterMode.d.ts +6 -4
  61. package/dist/util/filterMode.d.ts.map +1 -1
  62. package/package.json +14 -11
  63. package/styles/structural.css +922 -0
  64. package/themes/README.md +84 -30
  65. package/themes/java/theme.css +140 -0
  66. package/themes/minimal/theme.css +128 -0
  67. package/themes/shiny/theme.css +314 -0
  68. package/EXPERIMENTAL.md +0 -75
  69. package/dist/button-BRDkmR1C.js +0 -203
  70. package/dist/button-BRDkmR1C.js.map +0 -1
  71. package/dist/experimental.d.ts +0 -16
  72. package/dist/experimental.d.ts.map +0 -1
  73. package/dist/experimental.js +0 -1361
  74. package/dist/experimental.js.map +0 -1
  75. package/dist/jsx-dev-runtime-CarwHDyL.js.map +0 -1
@@ -1,1361 +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 b, j as c, c as x, a as w, i as U } from "./jsx-dev-runtime-CarwHDyL.js";
5
- import { Emitter as y, 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-BRDkmR1C.js";
7
- class E extends b {
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 y([], { 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 b {
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
- ge(e.items) ? (this.itemsEmitter = e.items, this.ownedItemsEmitter = null) : (this.ownedItemsEmitter = new y(e.items ?? [], {
229
- owner: this,
230
- purpose: "list items"
231
- }), this.itemsEmitter = this.ownedItemsEmitter), this.items$ = this.itemsEmitter, this.ownedSelectedItemsEmitter = e.selectedItemsEmitter == null ? new y([], { 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__ */ w(
247
- l,
248
- {
249
- className: I(this.props) || null,
250
- children: [
251
- s === m.Error ? /* @__PURE__ */ c("p", { role: "alert", "data-part": "error", children: be(i, "Unable to load items") }) : null,
252
- n && e.length === 0 ? /* @__PURE__ */ w("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) : ye(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 ge(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 ye(t) {
364
- if (t != null && (typeof t == "object" || typeof t == "function")) {
365
- const r = Reflect.get(t, "label");
366
- if (we(r)) return r;
367
- }
368
- return String(t);
369
- }
370
- function we(t) {
371
- return t == null || typeof t == "string" || typeof t == "number";
372
- }
373
- function be(t, r) {
374
- return t instanceof Error ? t.message : t == null ? r : String(t);
375
- }
376
- class T extends b {
377
- constructor(e = {}) {
378
- super(e);
379
- o(this, "optionsEmitter");
380
- this.optionsEmitter = ke(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: ve(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 g = X(p), S = Ie(p), C = n.get(g) ?? l;
415
- return /* @__PURE__ */ c(
416
- Ee,
417
- {
418
- label: S,
419
- defaultValue: C,
420
- symbols: a,
421
- onChange: (q, k) => {
422
- var R, M;
423
- k == null || k.stopPropagation();
424
- const v = new Map(n);
425
- q === K.Neutral ? v.delete(g) : v.set(g, q), (M = (R = this.props).onChange) == null || M.call(R, v, k);
426
- }
427
- },
428
- `${String(g)}:${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 ke(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 ve(t, r) {
482
- return t instanceof Error ? t.message : t == null ? r : String(t);
483
- }
484
- class N extends b {
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__ */ w(
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__ */ w(
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
- }
570
-
571
- th[data-fray-component="table-header-cell"] > [data-part="sort"],
572
- th[data-fray-component="table-header-cell"] > [data-part="filter-toggle"] {
573
- width: auto;
574
- font-family: inherit;
575
- }
576
-
577
- th[data-fray-component="table-header-cell"] > [data-part="filter-toggle"] {
578
- margin-inline-start: var(--ui-padding-h);
579
- font-size: 0.75em;
580
- }
581
- `);
582
- function Te(t) {
583
- return typeof t[0] == "string" || typeof t[0] == "number";
584
- }
585
- class H extends b {
586
- render() {
587
- return /* @__PURE__ */ c("thead", { "data-fray-component": "table-header", children: /* @__PURE__ */ c("tr", { children: this.props.columns.map((r) => /* @__PURE__ */ c(
588
- N,
589
- {
590
- field: r.field,
591
- sortEmitter: this.props.sortEmitter,
592
- filtersEmitter: this.props.filtersEmitter,
593
- ...r.label == null ? {} : { label: r.label },
594
- ...r.sortable == null ? {} : { sortable: r.sortable },
595
- ...r.filterOptions == null ? {} : { filterOptions: r.filterOptions },
596
- ...this.props.filterModes == null ? {} : { filterModes: this.props.filterModes },
597
- ...this.props.defaultSemanticState == null ? {} : { defaultSemanticState: this.props.defaultSemanticState },
598
- ...this.props.onFilterChange == null ? {} : { onFilterChange: this.props.onFilterChange }
599
- },
600
- String(r.field)
601
- )) }) });
602
- }
603
- }
604
- o(H, "dependencies", [N]);
605
- function Ke(t, { sort: r = null, filters: e = {} } = {}) {
606
- qe(t), r != null && (Z(r), t.searchParams.set("sort", `${r.field}:${r.direction}`));
607
- for (const [s, i] of Object.entries(e))
608
- for (const [n, a] of i) {
609
- if (!De(a))
610
- throw new TypeError(`Unknown filter mode for ${s}: ${String(a)}`);
611
- t.searchParams.append(
612
- "filter",
613
- `${s}:${a}:${JSON.stringify(n)}`
614
- );
615
- }
616
- return t;
617
- }
618
- function Ce(t, r, e) {
619
- if (!Array.isArray(t)) throw new TypeError("Local table data must be an array");
620
- const s = t.filter((n) => Re(n, e));
621
- if (r == null) return s;
622
- Z(r);
623
- const i = r.direction === "asc" ? 1 : -1;
624
- return [...s].sort((n, a) => Ne($(n, r.field), $(a, r.field)) * i);
625
- }
626
- function Re(t, r) {
627
- for (const [e, s] of Object.entries(r)) {
628
- const i = $(t, e);
629
- if (s.filter(([, d]) => d === K.Deny).some(([d]) => Object.is(d, i))) return !1;
630
- const a = s.filter(([, d]) => d === K.Require);
631
- if (a.length > 0 && !a.some(([d]) => Object.is(d, i))) return !1;
632
- const l = s.filter(([, d]) => d === K.Prefer);
633
- if (l.length > 0 && !l.some(([d]) => Object.is(d, i))) return !1;
634
- }
635
- return !0;
636
- }
637
- function Z(t) {
638
- if (t == null || typeof t != "object" || typeof Reflect.get(t, "field") != "string" || !Me(Reflect.get(t, "direction")))
639
- throw new TypeError("Table sort must contain a field and asc/desc direction");
640
- }
641
- function Me(t) {
642
- return t === "asc" || t === "desc";
643
- }
644
- function De(t) {
645
- return Object.values(K).some((r) => r === t);
646
- }
647
- function Ne(t, r) {
648
- 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));
649
- }
650
- function $(t, r) {
651
- if (!(t == null || typeof t != "object" && typeof t != "function"))
652
- return Reflect.get(t, r);
653
- }
654
- function qe(t) {
655
- if (t == null || typeof t != "object" && typeof t != "function" || typeof Reflect.get(t, "toString") != "function")
656
- throw new TypeError("Table serializer requires a URL");
657
- const r = Reflect.get(t, "searchParams");
658
- if (r == null || typeof Reflect.get(r, "set") != "function" || typeof Reflect.get(r, "append") != "function")
659
- throw new TypeError("Table serializer requires URL search parameters");
660
- }
661
- class j extends b {
662
- constructor(e) {
663
- super(e);
664
- o(this, "columns");
665
- o(this, "rowKey");
666
- o(this, "sortEmitter");
667
- o(this, "filtersEmitter");
668
- o(this, "selectedItemsEmitter");
669
- o(this, "selectionHandler");
670
- o(this, "query", null);
671
- o(this, "dataSource", null);
672
- o(this, "ownedSelectedItemsEmitter");
673
- o(this, "ownedDataSource", null);
674
- o(this, "ownsQuery", !1);
675
- o(this, "queryArgs", []);
676
- if (e.mode !== "local" && e.mode !== "remote")
677
- throw new TypeError("DataTable mode must be local or remote");
678
- this.columns = Oe(e.columns), this.rowKey = je(e.rowKey), this.sortEmitter = new y(null, {
679
- owner: this,
680
- purpose: "table sort"
681
- }), this.filtersEmitter = new y({}, {
682
- owner: this,
683
- purpose: "table filters"
684
- }), this.ownedSelectedItemsEmitter = e.selectedItemsEmitter == null ? new y([], { owner: this, purpose: "selected table rows" }) : null, this.selectedItemsEmitter = e.selectedItemsEmitter ?? this.ownedSelectedItemsEmitter, this.selectionHandler = Y({
685
- owner: this,
686
- multiSelect: e.multiSelect ?? !1,
687
- selectedItemsEmitter: this.selectedItemsEmitter,
688
- getItems: () => {
689
- var s;
690
- return ((s = this.query) == null ? void 0 : s.get()) ?? [];
691
- },
692
- getKey: this.rowKey
693
- });
694
- }
695
- initialize() {
696
- this.query = this.props.mode === "local" ? this.createLocalQuery() : this.createRemoteQuery(), this.watch(this.query, this.selectedItemsEmitter);
697
- }
698
- createLocalQuery() {
699
- const e = this.props.data ?? [];
700
- let s;
701
- return ee(e) ? s = e : (this.ownedDataSource = new y(e, {
702
- owner: this,
703
- purpose: "local table data"
704
- }), s = this.ownedDataSource), this.dataSource = s, this.ownsQuery = !0, new oe(
705
- [s, this.sortEmitter, this.filtersEmitter],
706
- ([i, n, a]) => Ce(i, n, a),
707
- { owner: this, purpose: "local table view" }
708
- );
709
- }
710
- createRemoteQuery() {
711
- if (this.props.query != null)
712
- return Ae(this.props.query), this.props.query;
713
- const e = this.props.queryHandler ?? this.createRestHandler();
714
- if (e == null || typeof e.fetch != "function")
715
- throw new TypeError("Remote DataTable requires query, queryHandler, or queryUrl");
716
- const s = new V("sort", this.sortEmitter, {
717
- owner: this,
718
- purpose: "remote table sort argument"
719
- }), i = new V("filters", this.filtersEmitter, {
720
- owner: this,
721
- purpose: "remote table filters argument"
722
- });
723
- this.queryArgs.push(s, i), this.ownsQuery = !0;
724
- const n = { sort: s, filters: i };
725
- return new ae({
726
- handler: e,
727
- args: n,
728
- owner: this,
729
- purpose: "remote table query",
730
- keepPreviousValue: !0
731
- });
732
- }
733
- createRestHandler() {
734
- if (this.props.queryUrl == null) return null;
735
- const e = {
736
- url: this.props.queryUrl,
737
- serialize: this.props.serializeQuery ?? Ke
738
- };
739
- return this.props.baseUrl != null && (e.baseUrl = this.props.baseUrl), this.props.fetch != null && (e.fetch = this.props.fetch), new le(e);
740
- }
741
- render() {
742
- var d, h, u, f;
743
- const e = ((d = this.query) == null ? void 0 : d.get()) ?? [];
744
- if (!Array.isArray(e)) throw new TypeError("DataTable query value must be an array");
745
- 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(
746
- this.selectedItemsEmitter.get().map((p, g) => this.rowKey(p, g))
747
- ), l = this.Host;
748
- return /* @__PURE__ */ w(
749
- l,
750
- {
751
- className: I(this.props) || null,
752
- "data-loading": n ? "" : null,
753
- "data-error": s === m.Error ? "" : null,
754
- children: [
755
- n ? /* @__PURE__ */ c("p", { role: "status", "data-part": "status", children: "Loading rows…" }) : null,
756
- s === m.Error ? /* @__PURE__ */ w("div", { "data-part": "error", role: "alert", children: [
757
- /* @__PURE__ */ c("span", { children: Fe(i, "Unable to load rows") }),
758
- typeof ((f = this.query) == null ? void 0 : f.retry) == "function" ? /* @__PURE__ */ c(
759
- "button",
760
- {
761
- type: "button",
762
- onClick: () => {
763
- var p, g;
764
- return (g = (p = this.query) == null ? void 0 : p.retry) == null ? void 0 : g.call(p, "table retry");
765
- },
766
- children: "Retry"
767
- }
768
- ) : null
769
- ] }) : null,
770
- /* @__PURE__ */ w("table", { "data-part": "table", "aria-busy": n ? "true" : null, children: [
771
- this.props.caption == null ? null : /* @__PURE__ */ c("caption", { children: this.props.caption }),
772
- /* @__PURE__ */ c(
773
- H,
774
- {
775
- columns: this.columns,
776
- sortEmitter: this.sortEmitter,
777
- filtersEmitter: this.filtersEmitter,
778
- ...this.props.filterModes == null ? {} : { filterModes: this.props.filterModes },
779
- ...this.props.defaultSemanticState == null ? {} : { defaultSemanticState: this.props.defaultSemanticState },
780
- ...this.props.onFilterChange == null ? {} : { onFilterChange: this.props.onFilterChange }
781
- },
782
- "header"
783
- ),
784
- /* @__PURE__ */ c("tbody", { children: e.length > 0 ? e.map((p, g) => this.renderRow(p, g, 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") })
785
- ] })
786
- ]
787
- }
788
- );
789
- }
790
- renderRow(e, s, i) {
791
- const n = this.rowKey(e, s), a = i.has(n);
792
- return /* @__PURE__ */ c(
793
- "tr",
794
- {
795
- "data-fray-selectable-row": "",
796
- "data-index": s,
797
- "aria-selected": String(a),
798
- tabIndex: s === 0 ? 0 : -1,
799
- children: this.columns.map((l) => /* @__PURE__ */ c("td", { children: l.render ? l.render(e, s) : Le(e[l.field]) }, String(l.field)))
800
- },
801
- String(n)
802
- );
803
- }
804
- renderPlaceholders() {
805
- const e = this.props.placeholderCount ?? 5;
806
- return Array.from({ length: e }, (s, i) => /* @__PURE__ */ c("tr", { children: this.columns.map((n, a) => /* @__PURE__ */ c("td", { children: /* @__PURE__ */ c(
807
- E,
808
- {
809
- width: 45 + (i + a) % 6 * 8
810
- }
811
- ) }, String(n.field))) }, `placeholder-${i}`));
812
- }
813
- afterUpdate(e) {
814
- const s = e instanceof Element ? e.querySelectorAll("tbody [data-fray-selectable-row]") : [];
815
- this.selectionHandler.rowsUpdated(s);
816
- }
817
- getSelectedRows() {
818
- return this.selectionHandler.getSelectedItems();
819
- }
820
- getSelectedRowsEmitter() {
821
- return this.selectedItemsEmitter;
822
- }
823
- onDestroy() {
824
- var e, s, i, n;
825
- this.selectionHandler.destroy(), this.ownsQuery && ((s = (e = this.query) == null ? void 0 : e.dispose) == null || s.call(e));
826
- for (const a of this.queryArgs) a.dispose();
827
- (i = this.ownedDataSource) == null || i.dispose(), (n = this.ownedSelectedItemsEmitter) == null || n.dispose(), this.sortEmitter.dispose(), this.filtersEmitter.dispose();
828
- }
829
- }
830
- o(j, "dependencies", [E, H]), o(j, "hostName", "data-table"), o(j, "standaloneHostName", "data-table"), o(j, "css", x`
831
- & {
832
- overflow: auto;
833
- color: var(--ui-text-color);
834
- }
835
-
836
- & > table {
837
- width: 100%;
838
- border-collapse: collapse;
839
- }
840
-
841
- & th,
842
- & td {
843
- padding: var(--ui-padding-v) var(--ui-padding-h);
844
- text-align: start;
845
- }
846
-
847
- & tbody tr[data-fray-selectable-row] {
848
- cursor: default;
849
- user-select: none;
850
- }
851
-
852
- & tbody tr[data-fray-selectable-row]:focus-visible {
853
- outline: 2px solid var(--ui-accent-color);
854
- outline-offset: -2px;
855
- }
856
-
857
- & tbody tr[data-fray-selectable-row][aria-selected="true"] {
858
- color: var(--toggle-selected-text);
859
- background: var(--toggle-selected-bg);
860
- }
861
-
862
- & > [data-part="error"] {
863
- color: var(--error-color);
864
- }
865
- `);
866
- function Oe(t) {
867
- if (!Array.isArray(t) || t.length === 0)
868
- throw new TypeError("DataTable columns must be a non-empty array");
869
- const r = /* @__PURE__ */ new Set();
870
- return t.map((e) => {
871
- if (e == null || typeof e != "object")
872
- throw new TypeError("Every DataTable column requires a field");
873
- const s = Reflect.get(e, "field");
874
- if (typeof s != "string" || s.length === 0)
875
- throw new TypeError("Every DataTable column requires a field");
876
- if (r.has(s)) throw new Error(`Duplicate DataTable column: ${s}`);
877
- r.add(s);
878
- const i = Reflect.get(e, "render");
879
- if (i != null && typeof i != "function")
880
- throw new TypeError(`DataTable column ${s} render must be a function`);
881
- return e;
882
- });
883
- }
884
- function je(t) {
885
- if (t == null) return z;
886
- if (typeof t == "function") return t;
887
- if (typeof t == "string" && t.length > 0)
888
- return (r, e) => {
889
- const s = r[t];
890
- if (s == null)
891
- throw new TypeError(`DataTable row at index ${e} lacks ${t}`);
892
- return s;
893
- };
894
- throw new TypeError("DataTable rowKey must be a function or property name");
895
- }
896
- function ee(t) {
897
- 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";
898
- }
899
- function Ae(t) {
900
- if (!ee(t))
901
- throw new TypeError("DataTable query must be an emitter");
902
- }
903
- function Le(t) {
904
- return t == null || typeof t == "string" || typeof t == "number" ? t : String(t);
905
- }
906
- function Fe(t, r) {
907
- return t instanceof Error ? t.message : t == null ? r : String(t);
908
- }
909
- class te extends b {
910
- render() {
911
- return this.props.children ?? [];
912
- }
913
- }
914
- class A extends b {
915
- constructor(e) {
916
- super(e);
917
- o(this, "nodesEmitter");
918
- o(this, "selectedKeyEmitter");
919
- o(this, "expandedKeysEmitter");
920
- o(this, "ownedNodesEmitter");
921
- o(this, "ownedSelectedEmitter");
922
- o(this, "ownedExpandedEmitter");
923
- o(this, "focusedKey", null);
924
- o(this, "typeahead", "");
925
- o(this, "typeaheadTimer", null);
926
- if (ze(e.nodes))
927
- this.nodesEmitter = e.nodes, this.ownedNodesEmitter = null;
928
- else {
929
- const s = e.nodes ?? re(e.children);
930
- this.ownedNodesEmitter = new y(s, {
931
- owner: this,
932
- purpose: "tree nodes"
933
- }), this.nodesEmitter = this.ownedNodesEmitter;
934
- }
935
- this.ownedSelectedEmitter = e.selectedKeyEmitter == null ? new y(null, { owner: this, purpose: "selected tree key" }) : null, this.selectedKeyEmitter = e.selectedKeyEmitter ?? this.ownedSelectedEmitter, this.ownedExpandedEmitter = e.expandedKeysEmitter == null ? new y([], { owner: this, purpose: "expanded tree keys" }) : null, this.expandedKeysEmitter = e.expandedKeysEmitter ?? this.ownedExpandedEmitter;
936
- }
937
- initialize() {
938
- this.reconcile(this.nodesEmitter.get()), this.watch(this.nodesEmitter, this.selectedKeyEmitter, this.expandedKeysEmitter), this.onCleanup(this.nodesEmitter.subscribe(({ value: e }) => this.reconcile(e), {
939
- emitCurrent: !1
940
- }));
941
- }
942
- render() {
943
- const e = this.nodesEmitter.get();
944
- B(e);
945
- 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;
946
- this.focusedKey = (a == null ? void 0 : a.node.id) ?? null;
947
- const l = this.Host;
948
- 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) => {
949
- var v, R, M;
950
- const { node: u, depth: f, position: p, setSize: g } = d, S = (((v = u.children) == null ? void 0 : v.length) ?? 0) > 0, C = S && s.has(u.id), q = Object.is(u.id, n), k = ((M = (R = this.props).renderItem) == null ? void 0 : M.call(R, u, f)) ?? u.label;
951
- return /* @__PURE__ */ w(
952
- "div",
953
- {
954
- role: "treeitem",
955
- "data-part": "item",
956
- "data-index": h,
957
- "data-depth": f,
958
- "aria-level": f + 1,
959
- "aria-posinset": p,
960
- "aria-setsize": g,
961
- "aria-expanded": S ? String(C) : null,
962
- "aria-selected": String(q),
963
- tabIndex: Object.is(u.id, a == null ? void 0 : a.node.id) ? 0 : -1,
964
- style: { "--tree-depth": f },
965
- onClick: (O) => {
966
- if (this.focusedKey = u.id, Ue(O.target) && S) {
967
- this.toggleExpanded(u.id), this.focusRow(u.id);
968
- return;
969
- }
970
- this.selectNode(u, O);
971
- },
972
- onFocus: () => this.focusedKey = u.id,
973
- onKeyDown: (O) => this.handleKeyDown(O, h, i),
974
- children: [
975
- /* @__PURE__ */ c(
976
- "span",
977
- {
978
- "data-part": "expander",
979
- "data-expandable": S ? "" : null,
980
- "aria-hidden": "true",
981
- children: S ? C ? "▾" : "▸" : "•"
982
- }
983
- ),
984
- /* @__PURE__ */ c("span", { "data-part": "label", children: k })
985
- ]
986
- },
987
- u.id
988
- );
989
- }) }) });
990
- }
991
- onDestroy() {
992
- var e, s, i;
993
- this.typeaheadTimer != null && clearTimeout(this.typeaheadTimer), (e = this.ownedNodesEmitter) == null || e.dispose(), (s = this.ownedSelectedEmitter) == null || s.dispose(), (i = this.ownedExpandedEmitter) == null || i.dispose();
994
- }
995
- reconcile(e) {
996
- B(e);
997
- const s = new Set(se(e).map(({ node: l }) => l.id)), i = this.selectedKeyEmitter.get();
998
- this.ownedSelectedEmitter != null && i != null && !s.has(i) && this.selectedKeyEmitter.set(null, "selected tree item removed");
999
- const n = this.expandedKeysEmitter.get(), a = n.filter((l) => s.has(l));
1000
- this.ownedExpandedEmitter != null && !$e(n, a) && this.expandedKeysEmitter.set(a, "removed tree expansions reconciled"), this.focusedKey != null && !s.has(this.focusedKey) && (this.focusedKey = null);
1001
- }
1002
- selectNode(e, s) {
1003
- this.selectedKeyEmitter.set(e.id, "tree item selected"), W(this.props.onSelect, e, s), this.focusRow(e.id);
1004
- }
1005
- toggleExpanded(e) {
1006
- const s = this.expandedKeysEmitter.get(), i = s.some((n) => Object.is(n, e));
1007
- this.expandedKeysEmitter.set(
1008
- i ? s.filter((n) => !Object.is(n, e)) : [...s, e],
1009
- i ? "tree item collapsed" : "tree item expanded"
1010
- );
1011
- }
1012
- handleKeyDown(e, s, i) {
1013
- var a, l, d, h;
1014
- const n = i[s];
1015
- if (n != null) {
1016
- if (e.key === "ArrowDown") return this.move(e, (a = i[s + 1]) == null ? void 0 : a.node.id);
1017
- if (e.key === "ArrowUp") return this.move(e, (l = i[s - 1]) == null ? void 0 : l.node.id);
1018
- if (e.key === "Home") return this.move(e, (d = i[0]) == null ? void 0 : d.node.id);
1019
- if (e.key === "End") return this.move(e, (h = i.at(-1)) == null ? void 0 : h.node.id);
1020
- if (e.key === "ArrowRight") {
1021
- e.preventDefault();
1022
- const u = n.node.children ?? [];
1023
- if (u.length === 0) return;
1024
- this.expandedKeysEmitter.get().some((p) => Object.is(p, n.node.id)) ? this.focusRow(u[0].id) : this.toggleExpanded(n.node.id);
1025
- return;
1026
- }
1027
- if (e.key === "ArrowLeft") {
1028
- 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);
1029
- return;
1030
- }
1031
- if (e.key === "Enter" || e.key === " ") {
1032
- e.preventDefault(), this.selectNode(n.node, e);
1033
- return;
1034
- }
1035
- e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && this.handleTypeahead(e, i, s);
1036
- }
1037
- }
1038
- move(e, s) {
1039
- s !== void 0 && (e.preventDefault(), this.focusRow(s));
1040
- }
1041
- focusRow(e) {
1042
- var i;
1043
- this.focusedKey = e;
1044
- const s = this.dom instanceof Element ? [...this.dom.querySelectorAll('[role="treeitem"]')] : [];
1045
- for (const n of s) {
1046
- const a = Number(n.dataset.index), l = _(
1047
- this.nodesEmitter.get(),
1048
- new Set(this.expandedKeysEmitter.get())
1049
- ), d = Object.is((i = l[a]) == null ? void 0 : i.node.id, e);
1050
- n.tabIndex = d ? 0 : -1, d && n.focus();
1051
- }
1052
- }
1053
- handleTypeahead(e, s, i) {
1054
- e.preventDefault(), this.typeaheadTimer != null && clearTimeout(this.typeaheadTimer), this.typeahead += e.key.toLocaleLowerCase(), this.typeaheadTimer = setTimeout(() => {
1055
- this.typeahead = "", this.typeaheadTimer = null;
1056
- }, 650);
1057
- const a = [...s.slice(i + 1), ...s.slice(0, i + 1)].find(({ node: l }) => He(l).toLocaleLowerCase().startsWith(this.typeahead));
1058
- a != null && this.focusRow(a.node.id);
1059
- }
1060
- }
1061
- o(A, "dependencies", [te]), o(A, "hostName", "tree-view"), o(A, "standaloneHostName", "tree-view"), o(A, "css", x`
1062
- & {
1063
- display: flex;
1064
- flex-direction: column;
1065
- min-width: 0;
1066
- min-height: 0;
1067
- overflow: auto;
1068
- }
1069
-
1070
- & > [data-part="tree"] {
1071
- display: grid;
1072
- align-content: start;
1073
- }
1074
-
1075
- & [data-part="item"] {
1076
- display: flex;
1077
- align-items: flex-start;
1078
- gap: 0.35rem;
1079
- min-width: 0;
1080
- padding: 0.38rem 0.5rem;
1081
- padding-inline-start: calc(0.5rem + var(--tree-depth) * 1.1rem);
1082
- cursor: default;
1083
- user-select: none;
1084
- }
1085
-
1086
- & [data-part="item"]:hover {
1087
- background: var(--button-background-hover);
1088
- }
1089
-
1090
- & [data-part="item"]:focus-visible {
1091
- outline: 2px solid var(--ui-accent-color);
1092
- outline-offset: -2px;
1093
- }
1094
-
1095
- & [data-part="item"][aria-selected="true"] {
1096
- color: var(--toggle-selected-text);
1097
- background: var(--toggle-selected-bg);
1098
- }
1099
-
1100
- & [data-part="expander"] {
1101
- flex: 0 0 1rem;
1102
- text-align: center;
1103
- }
1104
-
1105
- & [data-part="expander"][data-expandable] {
1106
- cursor: pointer;
1107
- }
1108
-
1109
- & [data-part="label"] {
1110
- min-width: 0;
1111
- overflow-wrap: anywhere;
1112
- }
1113
-
1114
- & > [data-part="empty"] {
1115
- margin: 0;
1116
- padding: var(--ui-padding, 0.75rem);
1117
- }
1118
-
1119
- @media (forced-colors: active) {
1120
- & [data-part="item"][aria-selected="true"] {
1121
- outline: 2px solid Highlight;
1122
- forced-color-adjust: auto;
1123
- }
1124
- }
1125
- `);
1126
- function re(t) {
1127
- return (Array.isArray(t) ? t : t == null ? [] : [t]).filter((e) => U(e) && e.type === te).map((e) => {
1128
- if (!U(e)) throw new TypeError("TreeView children must be TreeItem nodes");
1129
- const s = e.props;
1130
- return {
1131
- id: s.id,
1132
- label: s.label,
1133
- ...s.textValue == null ? {} : { textValue: s.textValue },
1134
- ...s.value === void 0 ? {} : { value: s.value },
1135
- children: re(s.children)
1136
- };
1137
- });
1138
- }
1139
- function _(t, r) {
1140
- const e = [], s = (i, n, a) => {
1141
- i.forEach((l, d) => {
1142
- var h;
1143
- 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);
1144
- });
1145
- };
1146
- return s(t, 0, null), e;
1147
- }
1148
- function se(t) {
1149
- const r = /* @__PURE__ */ new Set(), e = [], s = (i, n, a) => {
1150
- i.forEach((l, d) => {
1151
- if (r.has(l.id)) throw new Error(`Duplicate tree item id: ${String(l.id)}`);
1152
- 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);
1153
- });
1154
- };
1155
- return s(t, 0, null), e;
1156
- }
1157
- function B(t) {
1158
- if (!Array.isArray(t)) throw new TypeError("TreeView nodes must be an array");
1159
- for (const { node: r } of se(t)) {
1160
- if (r == null || typeof r != "object" || r.id == null)
1161
- throw new TypeError("Each tree node requires an id");
1162
- if (!Array.isArray(r.children ?? []))
1163
- throw new TypeError(`Tree node ${String(r.id)} children must be an array`);
1164
- }
1165
- }
1166
- function He(t) {
1167
- return t.textValue != null ? t.textValue : typeof t.label == "string" || typeof t.label == "number" ? String(t.label) : String(t.id);
1168
- }
1169
- function $e(t, r) {
1170
- return t.length === r.length && t.every((e, s) => Object.is(e, r[s]));
1171
- }
1172
- function ze(t) {
1173
- return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function";
1174
- }
1175
- function Ue(t) {
1176
- return t instanceof Element && t.closest('[data-part="expander"]') != null;
1177
- }
1178
- class G extends b {
1179
- constructor(e) {
1180
- super(e);
1181
- o(this, "openEmitter");
1182
- o(this, "dialogId");
1183
- o(this, "titleId");
1184
- o(this, "descriptionId");
1185
- o(this, "dialogElement", null);
1186
- o(this, "restoreFocusTo", null);
1187
- o(this, "synchronizedOpen", !1);
1188
- 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`;
1189
- }
1190
- initialize() {
1191
- this.watch(this.openEmitter);
1192
- }
1193
- render() {
1194
- const {
1195
- title: e,
1196
- description: s,
1197
- actions: i,
1198
- closeLabel: n = "Close",
1199
- showCloseButton: a = !0,
1200
- children: l = []
1201
- } = this.props;
1202
- return /* @__PURE__ */ w(
1203
- "dialog",
1204
- {
1205
- id: this.dialogId,
1206
- className: I(this.props) || void 0,
1207
- "data-fray-component": "dialog",
1208
- "aria-labelledby": this.titleId,
1209
- "aria-describedby": s == null ? null : this.descriptionId,
1210
- "aria-modal": "true",
1211
- ref: (d) => this.dialogElement = d,
1212
- children: [
1213
- /* @__PURE__ */ c("header", { "data-part": "header", children: /* @__PURE__ */ c("h2", { id: this.titleId, children: e }) }),
1214
- s == null ? null : /* @__PURE__ */ c("p", { id: this.descriptionId, "data-part": "description", children: s }),
1215
- /* @__PURE__ */ c("div", { "data-part": "content", children: l }),
1216
- i == null && !a ? null : /* @__PURE__ */ w("footer", { "data-part": "actions", children: [
1217
- i,
1218
- a ? /* @__PURE__ */ c(
1219
- Q,
1220
- {
1221
- label: n,
1222
- onClick: () => this.requestClose()
1223
- }
1224
- ) : null
1225
- ] })
1226
- ]
1227
- }
1228
- );
1229
- }
1230
- afterMount() {
1231
- const e = this.dialogElement;
1232
- e != null && (this.listen(e, "cancel", (s) => {
1233
- s.preventDefault(), this.requestClose();
1234
- }), this.listen(e, "close", () => {
1235
- this.openEmitter.get() && this.openEmitter.set(!1, "native dialog closed"), this.finishClose();
1236
- }), this.syncOpenState());
1237
- }
1238
- afterUpdate() {
1239
- this.syncOpenState();
1240
- }
1241
- close() {
1242
- this.requestClose();
1243
- }
1244
- onDestroy() {
1245
- const e = this.dialogElement;
1246
- (e == null ? void 0 : e.open) === !0 && typeof e.close == "function" && e.close(), this.finishClose(), this.dialogElement = null;
1247
- }
1248
- requestClose() {
1249
- this.openEmitter.get() && this.openEmitter.set(!1, "dialog close requested");
1250
- }
1251
- syncOpenState() {
1252
- const e = this.dialogElement;
1253
- if (e == null) return;
1254
- const s = this.openEmitter.get();
1255
- if (s && !this.synchronizedOpen) {
1256
- const i = document.activeElement;
1257
- this.restoreFocusTo = i instanceof HTMLElement ? i : null, Ve(e), this.synchronizedOpen = !0, Qe(e, this.props.initialFocusRef);
1258
- return;
1259
- }
1260
- !s && this.synchronizedOpen && (e.open && typeof e.close == "function" ? e.close() : e.removeAttribute("open"), this.finishClose());
1261
- }
1262
- finishClose() {
1263
- if (!this.synchronizedOpen && this.restoreFocusTo == null) return;
1264
- this.synchronizedOpen = !1;
1265
- const e = this.restoreFocusTo;
1266
- this.restoreFocusTo = null, (e == null ? void 0 : e.isConnected) === !0 && e.focus(), W(this.props.onClose);
1267
- }
1268
- }
1269
- o(G, "dependencies", [Q]), o(G, "css", x`
1270
- dialog[data-fray-component="dialog"] {
1271
- width: min(38rem, calc(100vw - 2rem));
1272
- max-height: min(42rem, calc(100dvh - 2rem));
1273
- padding: 0;
1274
- color: var(--ui-text-color);
1275
- background: var(--panel-bg);
1276
- border: 1px solid var(--ui-border-color);
1277
- border-radius: var(--panel-radius, var(--ui-border-radius));
1278
- box-shadow: 0 1.25rem 4rem rgb(0 0 0 / 35%);
1279
- }
1280
-
1281
- dialog[data-fray-component="dialog"]::backdrop {
1282
- background: rgb(0 0 0 / 55%);
1283
- }
1284
-
1285
- dialog[data-fray-component="dialog"] > [data-part] {
1286
- padding: var(--panel-padding, 0.75rem);
1287
- }
1288
-
1289
- dialog[data-fray-component="dialog"] > [data-part="header"] {
1290
- border-block-end: 1px solid var(--ui-border-color);
1291
- }
1292
-
1293
- dialog[data-fray-component="dialog"] > [data-part="header"] h2,
1294
- dialog[data-fray-component="dialog"] > [data-part="description"] {
1295
- margin: 0;
1296
- }
1297
-
1298
- dialog[data-fray-component="dialog"] > [data-part="content"] {
1299
- overflow: auto;
1300
- }
1301
-
1302
- dialog[data-fray-component="dialog"] > [data-part="actions"] {
1303
- display: flex;
1304
- justify-content: flex-end;
1305
- gap: var(--spacing-small, 0.5rem);
1306
- border-block-start: 1px solid var(--ui-border-color);
1307
- }
1308
-
1309
- @media (prefers-reduced-motion: no-preference) {
1310
- dialog[data-fray-component="dialog"][open] {
1311
- animation: fray-dialog-enter 120ms ease-out;
1312
- }
1313
- }
1314
-
1315
- @keyframes fray-dialog-enter {
1316
- from {
1317
- transform: translateY(0.4rem);
1318
- }
1319
- }
1320
-
1321
- @media (forced-colors: active) {
1322
- dialog[data-fray-component="dialog"] {
1323
- border: 2px solid CanvasText;
1324
- }
1325
- }
1326
- `);
1327
- function Ve(t) {
1328
- if (!t.open) {
1329
- if (typeof t.showModal == "function") {
1330
- t.showModal();
1331
- return;
1332
- }
1333
- t.setAttribute("open", "");
1334
- }
1335
- }
1336
- function Qe(t, r) {
1337
- const s = (r == null || typeof r == "function" ? null : r.current) ?? t.querySelector(
1338
- '[autofocus], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
1339
- );
1340
- s == null || s.focus();
1341
- }
1342
- export {
1343
- J as BaseSelectionHandler,
1344
- j as DataTable,
1345
- G as Dialog,
1346
- T as FilterPanel,
1347
- D as ListView,
1348
- pe as MultiSelectionHandler,
1349
- E as Placeholder,
1350
- ue as SingleSelectionHandler,
1351
- H as TableHeader,
1352
- N as TableHeaderCell,
1353
- te as TreeItem,
1354
- A as TreeView,
1355
- Ce as applyLocalTableState,
1356
- Z as assertSort,
1357
- Y as createSelectionHandler,
1358
- z as defaultItemKey,
1359
- Ke as serializeTableQuery
1360
- };
1361
- //# sourceMappingURL=experimental.js.map