gridsmith-ui 0.29.1 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/README.md +5 -1
- package/dist/DropdownMenu-DqT7ZQ0D.d.ts +39 -0
- package/dist/charts.js +24 -9
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +7 -7
- package/dist/{chunk-MFAWJSMJ.js → chunk-6C2IUMY7.js} +4 -23
- package/dist/chunk-6C2IUMY7.js.map +1 -0
- package/dist/{chunk-OYNUU346.js → chunk-7QLXYRPD.js} +3 -12
- package/dist/chunk-7QLXYRPD.js.map +1 -0
- package/dist/{chunk-FD4YED7O.js → chunk-DBHVJ7Z3.js} +5 -49
- package/dist/chunk-DBHVJ7Z3.js.map +1 -0
- package/dist/chunk-IELIF4PJ.js +110 -0
- package/dist/chunk-IELIF4PJ.js.map +1 -0
- package/dist/chunk-ISONVOA7.js +316 -0
- package/dist/chunk-ISONVOA7.js.map +1 -0
- package/dist/{chunk-4TUJXDRU.js → chunk-KMKBOTFR.js} +93 -32
- package/dist/chunk-KMKBOTFR.js.map +1 -0
- package/dist/{chunk-MKFWHWBK.js → chunk-L6HWACK7.js} +7 -7
- package/dist/chunk-L6HWACK7.js.map +1 -0
- package/dist/chunk-LJYSVZMI.js +25 -0
- package/dist/chunk-LJYSVZMI.js.map +1 -0
- package/dist/{chunk-6A5RHW2W.js → chunk-NEUWZUK6.js} +4 -5
- package/dist/chunk-NEUWZUK6.js.map +1 -0
- package/dist/chunk-NKUCS67T.js +13 -0
- package/dist/chunk-NKUCS67T.js.map +1 -0
- package/dist/{chunk-RECCCA7Z.js → chunk-OVHBQT3Z.js} +6 -5
- package/dist/chunk-OVHBQT3Z.js.map +1 -0
- package/dist/{chunk-I3MTQ3CS.js → chunk-OX3NNMWG.js} +6 -6
- package/dist/{chunk-I3MTQ3CS.js.map → chunk-OX3NNMWG.js.map} +1 -1
- package/dist/{chunk-ZI3OQDET.js → chunk-R5QXMNW7.js} +297 -15
- package/dist/chunk-R5QXMNW7.js.map +1 -0
- package/dist/chunk-SJZWEBHL.js +58 -0
- package/dist/chunk-SJZWEBHL.js.map +1 -0
- package/dist/{chunk-FUKSLQ77.js → chunk-SLRTSBCJ.js} +91 -51
- package/dist/chunk-SLRTSBCJ.js.map +1 -0
- package/dist/chunk-T52LAFKG.js +1350 -0
- package/dist/chunk-T52LAFKG.js.map +1 -0
- package/dist/chunk-TYNDXMBV.js +105 -0
- package/dist/chunk-TYNDXMBV.js.map +1 -0
- package/dist/{chunk-37WOC7F7.js → chunk-UDJOIVKQ.js} +31 -113
- package/dist/chunk-UDJOIVKQ.js.map +1 -0
- package/dist/{chunk-RJEUQ7RL.js → chunk-ULCACQSA.js} +47 -90
- package/dist/chunk-ULCACQSA.js.map +1 -0
- package/dist/{chunk-HP7WUZPK.js → chunk-WIUGPZOH.js} +10 -3
- package/dist/chunk-WIUGPZOH.js.map +1 -0
- package/dist/{chunk-JTU7OBYJ.js → chunk-YL5KD5RC.js} +4 -3
- package/dist/chunk-YL5KD5RC.js.map +1 -0
- package/dist/data-grid.d.ts +25 -6
- package/dist/data-grid.js +180 -58
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +4 -5
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +11 -8
- package/dist/editor.js.map +1 -1
- package/dist/{feather-FNBQ74RR.js → feather-XFFEFLTV.js} +5 -3
- package/dist/feather-XFFEFLTV.js.map +1 -0
- package/dist/{heroicons-DODCSYWD.js → heroicons-L6DOHBEA.js} +5 -3
- package/dist/heroicons-L6DOHBEA.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +138 -39
- package/dist/index.js +846 -1667
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +26 -8
- package/dist/kanban.js +204 -79
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-ZWE3EPGP.js → lucide-JOORDTO6.js} +5 -3
- package/dist/lucide-JOORDTO6.js.map +1 -0
- package/dist/{phosphor-DIHPA4AJ.js → phosphor-TKGDYNGR.js} +5 -3
- package/dist/phosphor-TKGDYNGR.js.map +1 -0
- package/dist/resizable.js +47 -16
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +12 -8
- package/dist/{table-utils-CxnpFHRF.d.ts → table-utils-BXkP-2Hx.d.ts} +3 -1
- package/dist/{tabler-D3VYTSGI.js → tabler-YGETLYRU.js} +5 -3
- package/dist/tabler-YGETLYRU.js.map +1 -0
- package/dist/tokens.css +14 -0
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +6 -1
- package/dist/virtualized.js +17 -13
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +14 -0
- package/package.json +1 -1
- package/dist/chunk-37WOC7F7.js.map +0 -1
- package/dist/chunk-4TUJXDRU.js.map +0 -1
- package/dist/chunk-6A5RHW2W.js.map +0 -1
- package/dist/chunk-FD4YED7O.js.map +0 -1
- package/dist/chunk-FUKSLQ77.js.map +0 -1
- package/dist/chunk-HP7WUZPK.js.map +0 -1
- package/dist/chunk-JTU7OBYJ.js.map +0 -1
- package/dist/chunk-MFAWJSMJ.js.map +0 -1
- package/dist/chunk-MKFWHWBK.js.map +0 -1
- package/dist/chunk-OYNUU346.js.map +0 -1
- package/dist/chunk-QM4SJKWV.js +0 -51
- package/dist/chunk-QM4SJKWV.js.map +0 -1
- package/dist/chunk-QNHVPE2B.js +0 -117
- package/dist/chunk-QNHVPE2B.js.map +0 -1
- package/dist/chunk-RECCCA7Z.js.map +0 -1
- package/dist/chunk-RJEUQ7RL.js.map +0 -1
- package/dist/chunk-WH2FUFAC.js +0 -15
- package/dist/chunk-WH2FUFAC.js.map +0 -1
- package/dist/chunk-ZI3OQDET.js.map +0 -1
- package/dist/feather-FNBQ74RR.js.map +0 -1
- package/dist/heroicons-DODCSYWD.js.map +0 -1
- package/dist/lucide-ZWE3EPGP.js.map +0 -1
- package/dist/phosphor-DIHPA4AJ.js.map +0 -1
- package/dist/tabler-D3VYTSGI.js.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useLatest } from './chunk-
|
|
2
|
+
import { useLatest } from './chunk-WIUGPZOH.js';
|
|
3
3
|
import { useRef, useInsertionEffect, useEffect, useCallback, useState, useMemo, useLayoutEffect } from 'react';
|
|
4
4
|
import { flushSync } from 'react-dom';
|
|
5
5
|
|
|
6
6
|
var FOCUSABLE = 'a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])';
|
|
7
7
|
var FIELD = "input, select, textarea, [contenteditable='true']";
|
|
8
|
+
var CONTROL_ANCESTOR = 'a[href], button, summary, label, [role="button"], [role="link"], [role="option"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="treeitem"], [role="row"], [role="gridcell"], [role="checkbox"], [role="radio"], [role="switch"]';
|
|
8
9
|
var SAFE_BUTTON = 'button:not([data-variant="destructive"])';
|
|
9
10
|
var OVERLAY_CLOSE_ATTR = "data-overlay-close";
|
|
10
11
|
function isRendered(el) {
|
|
@@ -54,10 +55,34 @@ function focusInitial(root, opts = {}) {
|
|
|
54
55
|
function useFocusBeforeOpen(open) {
|
|
55
56
|
const before = useRef(null);
|
|
56
57
|
useInsertionEffect(() => {
|
|
57
|
-
|
|
58
|
+
trackFocus();
|
|
59
|
+
if (!open) return;
|
|
60
|
+
const active = document.activeElement;
|
|
61
|
+
before.current = !active || active === document.body ? justLost() ?? active : active;
|
|
58
62
|
}, [open]);
|
|
59
63
|
return before;
|
|
60
64
|
}
|
|
65
|
+
var lastFocused = null;
|
|
66
|
+
var lastFocusedAt = 0;
|
|
67
|
+
var lastActedAt = 0;
|
|
68
|
+
var tracking = false;
|
|
69
|
+
function trackFocus() {
|
|
70
|
+
if (tracking || typeof document === "undefined") return;
|
|
71
|
+
tracking = true;
|
|
72
|
+
document.addEventListener("focusin", (e) => {
|
|
73
|
+
lastFocused = e.target instanceof Element ? e.target : null;
|
|
74
|
+
lastFocusedAt = performance.now();
|
|
75
|
+
}, true);
|
|
76
|
+
const acted = () => {
|
|
77
|
+
lastActedAt = performance.now();
|
|
78
|
+
};
|
|
79
|
+
for (const type of ["keydown", "pointerdown", "click"]) document.addEventListener(type, acted, true);
|
|
80
|
+
}
|
|
81
|
+
function justLost() {
|
|
82
|
+
const recent = lastActedAt >= lastFocusedAt && performance.now() - lastActedAt < 1e3;
|
|
83
|
+
return lastFocused && !lastFocused.isConnected && recent ? lastFocused : null;
|
|
84
|
+
}
|
|
85
|
+
trackFocus();
|
|
61
86
|
function pathAbove(to, from) {
|
|
62
87
|
const up = to.replace(/\/+$/, "");
|
|
63
88
|
return from.startsWith(`${up}/`) && from.replace(/\/+$/, "") !== up;
|
|
@@ -73,6 +98,59 @@ function deletedRow(before, now) {
|
|
|
73
98
|
for (let j = k; j < (refilled ? last : now.length); j++) if (now[j] !== before[j + 1]) return -1;
|
|
74
99
|
return k;
|
|
75
100
|
}
|
|
101
|
+
function focusForTheMoment(el) {
|
|
102
|
+
const own = el.getAttribute("tabindex");
|
|
103
|
+
if (own === null) el.setAttribute("tabindex", "-1");
|
|
104
|
+
el.focus();
|
|
105
|
+
if (document.activeElement !== el) {
|
|
106
|
+
if (own === null) el.removeAttribute("tabindex");
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
let ring = false;
|
|
110
|
+
try {
|
|
111
|
+
ring = el.matches(":focus-visible");
|
|
112
|
+
} catch {
|
|
113
|
+
}
|
|
114
|
+
const { outline, outlineOffset } = el.style;
|
|
115
|
+
if (ring) {
|
|
116
|
+
el.style.outline = "2px solid var(--ds-focus)";
|
|
117
|
+
el.style.outlineOffset = "2px";
|
|
118
|
+
}
|
|
119
|
+
el.addEventListener("blur", () => {
|
|
120
|
+
if (own === null) el.removeAttribute("tabindex");
|
|
121
|
+
if (ring) Object.assign(el.style, { outline, outlineOffset });
|
|
122
|
+
}, { once: true });
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
var HEADING = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
|
|
126
|
+
var LAST_RESORT_MS = 200;
|
|
127
|
+
function placesOf(el) {
|
|
128
|
+
const places = [];
|
|
129
|
+
for (let c = el, box = el.parentElement; box && box !== document.body && box.parentElement && box.parentElement !== document.body; c = box, box = box.parentElement) {
|
|
130
|
+
places.push({ box, prev: c.previousElementSibling, next: c.nextElementSibling });
|
|
131
|
+
}
|
|
132
|
+
return places;
|
|
133
|
+
}
|
|
134
|
+
function landLastResort(places, closing) {
|
|
135
|
+
const at = places.findIndex((p) => p.box.isConnected);
|
|
136
|
+
if (at < 0) return false;
|
|
137
|
+
const { box, prev, next } = places[at];
|
|
138
|
+
const kids = Array.from(box.children);
|
|
139
|
+
const from = prev?.parentElement === box ? kids.indexOf(prev) + 1 : 0;
|
|
140
|
+
const to = next?.parentElement === box ? kids.indexOf(next) : kids.length;
|
|
141
|
+
const areas = [kids.slice(from, Math.max(from, to)), ...places.slice(at).map((p) => [p.box])];
|
|
142
|
+
const counts = (el) => !closing?.contains(el);
|
|
143
|
+
for (const area of areas) {
|
|
144
|
+
const stop = area.flatMap((a) => [...isTabStop(a) ? [a] : [], ...tabStops(a)]).find(counts);
|
|
145
|
+
if (stop) {
|
|
146
|
+
stop.focus();
|
|
147
|
+
if (document.activeElement === stop) return true;
|
|
148
|
+
}
|
|
149
|
+
const heading = area.flatMap((a) => [...a.matches(HEADING) ? [a] : [], ...a.querySelectorAll(HEADING)]).find((h) => h instanceof HTMLElement && isRendered(h) && counts(h));
|
|
150
|
+
if (heading && focusForTheMoment(heading)) return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
76
154
|
function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
77
155
|
const { href, pathname } = location;
|
|
78
156
|
const row = el.closest(ROW);
|
|
@@ -85,6 +163,7 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
85
163
|
const texts = rows.map((r) => r.textContent ?? "");
|
|
86
164
|
const keyOf = (r) => r?.getAttribute("data-row-key") ?? null;
|
|
87
165
|
const key = keyOf(row);
|
|
166
|
+
const places = placesOf(el);
|
|
88
167
|
const pageChanged = () => {
|
|
89
168
|
if (ignoreRoute) return false;
|
|
90
169
|
if (location.pathname !== pathname) return !pathAbove(location.pathname, pathname);
|
|
@@ -117,16 +196,26 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
117
196
|
return k >= 0 && k <= at ? list.children[Math.max(0, at - 1)] ?? void 0 : void 0;
|
|
118
197
|
};
|
|
119
198
|
const neighbour = () => inRow(byKey(keyOf(before)) ?? before) || inRow(byKey(keyOf(after)) ?? after) || !!list?.isConnected && land(tabStops(list)[0]);
|
|
199
|
+
const lastResort = () => {
|
|
200
|
+
setTimeout(() => {
|
|
201
|
+
const active = document.activeElement;
|
|
202
|
+
if (active && active !== document.body && active.isConnected || pageChanged()) return;
|
|
203
|
+
landLastResort(places);
|
|
204
|
+
}, LAST_RESORT_MS);
|
|
205
|
+
return false;
|
|
206
|
+
};
|
|
120
207
|
let unwatch = null;
|
|
121
208
|
const watch = () => {
|
|
122
209
|
unwatch?.();
|
|
123
210
|
if (!list || typeof MutationObserver === "undefined") return;
|
|
124
|
-
const observer = new MutationObserver(() => {
|
|
211
|
+
const observer = new MutationObserver((changes) => {
|
|
125
212
|
if (el.isConnected) return;
|
|
126
213
|
const active = document.activeElement;
|
|
127
214
|
const dropped = !active || active === document.body || !active.isConnected;
|
|
128
215
|
stop();
|
|
129
|
-
if (dropped
|
|
216
|
+
if (!dropped || pageChanged()) return;
|
|
217
|
+
const fromList = changes.some((c) => c.target === list || c.target === list.parentNode);
|
|
218
|
+
if (!(fromList && neighbour())) lastResort();
|
|
130
219
|
});
|
|
131
220
|
const onFocusIn = (e) => {
|
|
132
221
|
if (e.target !== el) stop();
|
|
@@ -140,6 +229,7 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
140
229
|
}
|
|
141
230
|
observer.observe(list, { childList: true });
|
|
142
231
|
if (list.parentNode) observer.observe(list.parentNode, { childList: true });
|
|
232
|
+
for (const { box } of places) observer.observe(box, { childList: true });
|
|
143
233
|
document.addEventListener("focusin", onFocusIn, true);
|
|
144
234
|
unwatch = stop;
|
|
145
235
|
};
|
|
@@ -153,7 +243,89 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
153
243
|
return true;
|
|
154
244
|
}
|
|
155
245
|
if (row && !row.isConnected && neighbour()) return true;
|
|
156
|
-
return land(fallback);
|
|
246
|
+
return land(fallback) || lastResort();
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function useFocusKeptInList(listRef) {
|
|
251
|
+
useEffect(() => {
|
|
252
|
+
if (typeof MutationObserver === "undefined") return;
|
|
253
|
+
let held = null;
|
|
254
|
+
let observer = null;
|
|
255
|
+
const forget = () => {
|
|
256
|
+
held = null;
|
|
257
|
+
observer?.disconnect();
|
|
258
|
+
observer = null;
|
|
259
|
+
};
|
|
260
|
+
const onFocusIn = (e) => {
|
|
261
|
+
const list = listRef.current;
|
|
262
|
+
const t = e.target;
|
|
263
|
+
if (!list || !(t instanceof HTMLElement) || !list.contains(t)) {
|
|
264
|
+
if (held) forget();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
held = rememberFocus(t);
|
|
268
|
+
if (observer) return;
|
|
269
|
+
observer = new MutationObserver(() => {
|
|
270
|
+
const h = held;
|
|
271
|
+
if (!h || h.el.isConnected) return;
|
|
272
|
+
const active = document.activeElement;
|
|
273
|
+
forget();
|
|
274
|
+
if (!active || active === document.body || !active.isConnected) h.restore();
|
|
275
|
+
});
|
|
276
|
+
observer.observe(list, { childList: true, subtree: true });
|
|
277
|
+
};
|
|
278
|
+
const onFocusOut = (e) => {
|
|
279
|
+
if (!held || e.target !== held.el) return;
|
|
280
|
+
queueMicrotask(() => {
|
|
281
|
+
if (held?.el.isConnected && !listRef.current?.contains(document.activeElement)) forget();
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
document.addEventListener("focusin", onFocusIn, true);
|
|
285
|
+
document.addEventListener("focusout", onFocusOut, true);
|
|
286
|
+
return () => {
|
|
287
|
+
document.removeEventListener("focusin", onFocusIn, true);
|
|
288
|
+
document.removeEventListener("focusout", onFocusOut, true);
|
|
289
|
+
const h = held;
|
|
290
|
+
forget();
|
|
291
|
+
const active = document.activeElement;
|
|
292
|
+
if (h && !h.el.isConnected && (!active || active === document.body || !active.isConnected)) h.restore();
|
|
293
|
+
};
|
|
294
|
+
}, [listRef]);
|
|
295
|
+
}
|
|
296
|
+
var openers = /* @__PURE__ */ new WeakMap();
|
|
297
|
+
function rememberOpener(active, root) {
|
|
298
|
+
let own = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
299
|
+
const controller = !own && root?.id ? document.querySelector(`[aria-controls~="${CSS.escape(root.id)}"]`) : null;
|
|
300
|
+
if (controller) own = rememberFocus(controller);
|
|
301
|
+
let around = null;
|
|
302
|
+
for (let n = active; n && !around; n = n.parentElement) {
|
|
303
|
+
const opener = openers.get(n);
|
|
304
|
+
if (opener) around = { root: n, opener };
|
|
305
|
+
}
|
|
306
|
+
const back = own ?? around?.opener;
|
|
307
|
+
if (!back) {
|
|
308
|
+
if (!root) return null;
|
|
309
|
+
const places = placesOf(root);
|
|
310
|
+
const { pathname } = location;
|
|
311
|
+
return {
|
|
312
|
+
el: null,
|
|
313
|
+
restore() {
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
const now = document.activeElement;
|
|
316
|
+
if (now && now !== document.body && now.isConnected && !root.contains(now) || location.pathname !== pathname) return;
|
|
317
|
+
landLastResort(places, root);
|
|
318
|
+
}, LAST_RESORT_MS);
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (root) openers.set(root, back);
|
|
324
|
+
return {
|
|
325
|
+
el: own?.el ?? null,
|
|
326
|
+
restore(fallback) {
|
|
327
|
+
if (own?.restore(fallback)) return true;
|
|
328
|
+
return !!around && !around.root.isConnected && around.opener.restore();
|
|
157
329
|
}
|
|
158
330
|
};
|
|
159
331
|
}
|
|
@@ -162,8 +334,7 @@ function useReturnFocus(open, root) {
|
|
|
162
334
|
const before = useFocusBeforeOpen(open);
|
|
163
335
|
useEffect(() => {
|
|
164
336
|
if (open) {
|
|
165
|
-
|
|
166
|
-
remembered.current = active2 instanceof HTMLElement && active2 !== document.body && active2.isConnected ? rememberFocus(active2) : null;
|
|
337
|
+
remembered.current = rememberOpener(before.current, root?.current);
|
|
167
338
|
return;
|
|
168
339
|
}
|
|
169
340
|
const r = remembered.current;
|
|
@@ -190,6 +361,64 @@ function rovingTabStop(items, isChecked, isDisabled = () => false) {
|
|
|
190
361
|
function focusAfterRemoval(items, index, fallback) {
|
|
191
362
|
(items[index - 1] ?? items[index] ?? fallback)?.focus();
|
|
192
363
|
}
|
|
364
|
+
function mayStop(root) {
|
|
365
|
+
const disabled = (el) => (el instanceof HTMLButtonElement || el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) && el.disabled;
|
|
366
|
+
return Array.from(root.querySelectorAll(`${FOCUSABLE}, button:disabled, input:disabled, select:disabled, textarea:disabled`)).filter((el) => disabled(el) ? !(el instanceof HTMLInputElement && el.type === "hidden") : isTabStop(el)).sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
367
|
+
}
|
|
368
|
+
function focusAfterSelfRemoval(control, { item, group, to } = {}) {
|
|
369
|
+
const goes = item ?? control;
|
|
370
|
+
const within = group === void 0 ? goes.parentElement : group;
|
|
371
|
+
const stops = within ? mayStop(within).filter((el) => !goes.contains(el)) : [];
|
|
372
|
+
const before = stops.filter((el) => goes.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING).reverse();
|
|
373
|
+
const after = stops.filter((el) => goes.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
|
|
374
|
+
const stopsOf = (el) => [...isTabStop(el) ? [el] : [], ...tabStops(el)];
|
|
375
|
+
const index = stopsOf(goes).indexOf(control);
|
|
376
|
+
const neighbour = (step) => {
|
|
377
|
+
for (let el = goes[step]; el; el = el[step]) {
|
|
378
|
+
const own = stopsOf(el);
|
|
379
|
+
if (own.length) return own[Math.max(0, Math.min(index, own.length - 1))];
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
};
|
|
383
|
+
const sameBefore = neighbour("previousElementSibling");
|
|
384
|
+
const sameAfter = neighbour("nextElementSibling");
|
|
385
|
+
const gone = () => !control.isConnected || control instanceof HTMLButtonElement && control.disabled;
|
|
386
|
+
const lost = () => {
|
|
387
|
+
const active = document.activeElement;
|
|
388
|
+
return !active || active === document.body || !active.isConnected || active === control;
|
|
389
|
+
};
|
|
390
|
+
const land = (el) => {
|
|
391
|
+
if (!el || !el.isConnected || !isTabStop(el)) return false;
|
|
392
|
+
el.focus();
|
|
393
|
+
return document.activeElement === el;
|
|
394
|
+
};
|
|
395
|
+
const landOnGroup = () => {
|
|
396
|
+
if (!within?.isConnected) return false;
|
|
397
|
+
if (!within.hasAttribute("tabindex") && within.tabIndex < 0) within.setAttribute("tabindex", "-1");
|
|
398
|
+
within.focus();
|
|
399
|
+
return document.activeElement === within;
|
|
400
|
+
};
|
|
401
|
+
const place = () => land(typeof to === "function" ? to() : to) || land(sameBefore) || before.some(land) || land(sameAfter) || after.some(land) || landOnGroup();
|
|
402
|
+
if (typeof MutationObserver === "undefined") return () => {
|
|
403
|
+
};
|
|
404
|
+
const observer = new MutationObserver(() => {
|
|
405
|
+
if (!gone()) return;
|
|
406
|
+
stop();
|
|
407
|
+
if (lost()) place();
|
|
408
|
+
});
|
|
409
|
+
const onFocusIn = (e) => {
|
|
410
|
+
if (e.target !== control) stop();
|
|
411
|
+
};
|
|
412
|
+
const timer = setTimeout(() => stop(), 1e4);
|
|
413
|
+
function stop() {
|
|
414
|
+
observer.disconnect();
|
|
415
|
+
clearTimeout(timer);
|
|
416
|
+
document.removeEventListener("focusin", onFocusIn, true);
|
|
417
|
+
}
|
|
418
|
+
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["disabled"] });
|
|
419
|
+
document.addEventListener("focusin", onFocusIn, true);
|
|
420
|
+
return stop;
|
|
421
|
+
}
|
|
193
422
|
var layers = [];
|
|
194
423
|
function useOverlayLayer(open) {
|
|
195
424
|
const [id] = useState(() => /* @__PURE__ */ Symbol("overlay-layer"));
|
|
@@ -243,6 +472,28 @@ function usePressMarks() {
|
|
|
243
472
|
return { props: { onPointerDownCapture: mark, onMouseDownCapture: mark }, marked: (e) => marks.has(e) };
|
|
244
473
|
}, [marks]);
|
|
245
474
|
}
|
|
475
|
+
function useFocusLeave(onLeave) {
|
|
476
|
+
const onLeaveRef = useLatest(onLeave);
|
|
477
|
+
const leaving = useRef(null);
|
|
478
|
+
useEffect(() => () => {
|
|
479
|
+
if (leaving.current) clearTimeout(leaving.current);
|
|
480
|
+
}, []);
|
|
481
|
+
return useMemo(() => ({
|
|
482
|
+
onFocusCapture: () => {
|
|
483
|
+
if (leaving.current) {
|
|
484
|
+
clearTimeout(leaving.current);
|
|
485
|
+
leaving.current = null;
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
onBlurCapture: () => {
|
|
489
|
+
if (leaving.current) clearTimeout(leaving.current);
|
|
490
|
+
leaving.current = setTimeout(() => {
|
|
491
|
+
leaving.current = null;
|
|
492
|
+
onLeaveRef.current();
|
|
493
|
+
}, 0);
|
|
494
|
+
}
|
|
495
|
+
}), [onLeaveRef]);
|
|
496
|
+
}
|
|
246
497
|
var openPopups = /* @__PURE__ */ new Map();
|
|
247
498
|
function usePopupFocus(open, { trigger, panel, close, tabExits, onTabOut, marked }) {
|
|
248
499
|
const isTop = useOverlayLayer(open);
|
|
@@ -261,6 +512,7 @@ function usePopupFocus(open, { trigger, panel, close, tabExits, onTabOut, marked
|
|
|
261
512
|
const inPanel = active instanceof Node && !!panel.current?.contains(active);
|
|
262
513
|
const opener = active instanceof HTMLElement && active !== document.body && !inPanel ? active : trigger.current;
|
|
263
514
|
remembered.current = opener ? rememberFocus(opener) : null;
|
|
515
|
+
if (panel.current && remembered.current) openers.set(panel.current, remembered.current);
|
|
264
516
|
lastPress.current = null;
|
|
265
517
|
}, [open, trigger, panel, before]);
|
|
266
518
|
useEffect(() => {
|
|
@@ -335,7 +587,19 @@ function usePopupFocus(open, { trigger, panel, close, tabExits, onTabOut, marked
|
|
|
335
587
|
const r = remembered.current;
|
|
336
588
|
remembered.current = null;
|
|
337
589
|
const press = lastPress.current;
|
|
338
|
-
if (!r
|
|
590
|
+
if (!r) return;
|
|
591
|
+
if (press && !press.inside && !markedRef.current?.(press.e)) {
|
|
592
|
+
const modal = r.el.closest('[aria-modal="true"]');
|
|
593
|
+
const target = press.e.target;
|
|
594
|
+
if (modal && target instanceof Node && modal.contains(target)) {
|
|
595
|
+
setTimeout(() => {
|
|
596
|
+
const active2 = document.activeElement;
|
|
597
|
+
if (active2 && active2 !== document.body && active2.isConnected) return;
|
|
598
|
+
if (modal.isConnected) r.restore(trigger.current);
|
|
599
|
+
}, 0);
|
|
600
|
+
}
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
339
603
|
const active = document.activeElement;
|
|
340
604
|
if (active !== r.el && active && active !== document.body && active.isConnected) return;
|
|
341
605
|
r.restore(trigger.current);
|
|
@@ -428,12 +692,13 @@ function useGridKeyboard({ container, active, setActive, keyOf, move, onActivate
|
|
|
428
692
|
return { onKeyDown, tabIndexOf, focusActive, focus };
|
|
429
693
|
}
|
|
430
694
|
var ALWAYS_TOP = () => true;
|
|
431
|
-
function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
695
|
+
function useFocusTrap(root, active, isTop = ALWAYS_TOP, also) {
|
|
432
696
|
useEffect(() => {
|
|
433
697
|
if (!active) return;
|
|
434
698
|
const onKeyDown = (e) => {
|
|
435
699
|
if (e.key !== "Tab" || e.defaultPrevented || !root.current || !isTop()) return;
|
|
436
|
-
const
|
|
700
|
+
const scope = [root.current, also?.current].filter((el) => !!el);
|
|
701
|
+
const focusable = scope.flatMap((el) => tabStops(el)).sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
437
702
|
if (focusable.length === 0) {
|
|
438
703
|
e.preventDefault();
|
|
439
704
|
return;
|
|
@@ -441,7 +706,7 @@ function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
|
441
706
|
const first = focusable[0];
|
|
442
707
|
const last = focusable[focusable.length - 1];
|
|
443
708
|
const current = document.activeElement;
|
|
444
|
-
const inside = current instanceof Node &&
|
|
709
|
+
const inside = current instanceof Node && scope.some((el) => el.contains(current));
|
|
445
710
|
if (e.shiftKey) {
|
|
446
711
|
if (!inside || current === first) {
|
|
447
712
|
e.preventDefault();
|
|
@@ -454,7 +719,24 @@ function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
|
454
719
|
};
|
|
455
720
|
document.addEventListener("keydown", onKeyDown);
|
|
456
721
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
457
|
-
}, [root, active, isTop]);
|
|
722
|
+
}, [root, active, isTop, also]);
|
|
723
|
+
}
|
|
724
|
+
function inertOutside(keep, within) {
|
|
725
|
+
const made = [];
|
|
726
|
+
const visit = (el) => {
|
|
727
|
+
for (const child of Array.from(el.children)) {
|
|
728
|
+
if (keep.includes(child)) continue;
|
|
729
|
+
if (keep.some((k) => child.contains(k))) visit(child);
|
|
730
|
+
else if (!child.hasAttribute("inert")) {
|
|
731
|
+
child.setAttribute("inert", "");
|
|
732
|
+
made.push(child);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
visit(within);
|
|
737
|
+
return () => {
|
|
738
|
+
for (const el of made) el.removeAttribute("inert");
|
|
739
|
+
};
|
|
458
740
|
}
|
|
459
741
|
function useNonModalDialog(root, active, onClose, isTop = ALWAYS_TOP) {
|
|
460
742
|
const onCloseRef = useLatest(onClose);
|
|
@@ -478,6 +760,6 @@ function useNonModalDialog(root, active, onClose, isTop = ALWAYS_TOP) {
|
|
|
478
760
|
}, [active, root, isTop, onCloseRef]);
|
|
479
761
|
}
|
|
480
762
|
|
|
481
|
-
export { FIELD, FOCUSABLE, OVERLAY_CLOSE_ATTR, ZOOM_KEYS, focusAfterRemoval, focusInitial, isTabStop, rememberFocus, rovingTabStop, tabStops, useCloseOnFocusOut, useFocusBeforeOpen, useFocusTrap, useGridKeyboard, useNonModalDialog, useOverlayLayer, usePopupFocus, usePressMarks, useReturnFocus };
|
|
482
|
-
//# sourceMappingURL=chunk-
|
|
483
|
-
//# sourceMappingURL=chunk-
|
|
763
|
+
export { CONTROL_ANCESTOR, FIELD, FOCUSABLE, OVERLAY_CLOSE_ATTR, ZOOM_KEYS, focusAfterRemoval, focusAfterSelfRemoval, focusInitial, inertOutside, isTabStop, rememberFocus, rememberOpener, rovingTabStop, tabStops, useCloseOnFocusOut, useFocusBeforeOpen, useFocusKeptInList, useFocusLeave, useFocusTrap, useGridKeyboard, useNonModalDialog, useOverlayLayer, usePopupFocus, usePressMarks, useReturnFocus };
|
|
764
|
+
//# sourceMappingURL=chunk-R5QXMNW7.js.map
|
|
765
|
+
//# sourceMappingURL=chunk-R5QXMNW7.js.map
|