kerfjs 4.2.0 → 4.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.
- package/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/ai/manifest.json +1 -1
- package/dist/{chunk-LKWAKC2X.js → chunk-SRWQKB33.js} +18 -8
- package/dist/chunk-SRWQKB33.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/list.d.ts +35 -0
- package/dist/list.js +26 -13
- package/dist/list.js.map +1 -1
- package/dist/overlay.d.ts +180 -122
- package/dist/overlay.js +252 -202
- package/dist/overlay.js.map +1 -1
- package/dist/remount.js +1 -1
- package/dist/scope.js +1 -1
- package/llms.txt +4 -2
- package/package.json +1 -1
- package/dist/chunk-LKWAKC2X.js.map +0 -1
package/dist/overlay.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mount } from './chunk-
|
|
1
|
+
import { mount } from './chunk-SRWQKB33.js';
|
|
2
2
|
import { delegate } from './chunk-KEZTD6H4.js';
|
|
3
3
|
import './chunk-QIP723L4.js';
|
|
4
4
|
import './chunk-YHH7OUFA.js';
|
|
@@ -37,197 +37,7 @@ function autoReposition(el, anchor, options = {}) {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// src/overlay-
|
|
41
|
-
var TOAST_SET = /* @__PURE__ */ Symbol("kerf.toasts");
|
|
42
|
-
function toastRegion(container) {
|
|
43
|
-
if (container !== void 0) return container;
|
|
44
|
-
const existing = document.querySelector(".kerf-toasts");
|
|
45
|
-
if (existing !== null) return existing;
|
|
46
|
-
const region = document.createElement("div");
|
|
47
|
-
region.className = "kerf-toasts";
|
|
48
|
-
region.setAttribute("aria-live", "polite");
|
|
49
|
-
document.body.appendChild(region);
|
|
50
|
-
return region;
|
|
51
|
-
}
|
|
52
|
-
function toast(content, options = {}) {
|
|
53
|
-
const {
|
|
54
|
-
container,
|
|
55
|
-
className = "kerf-toast",
|
|
56
|
-
duration = 4e3,
|
|
57
|
-
role = "status",
|
|
58
|
-
mode = "stack",
|
|
59
|
-
collapse = "fade",
|
|
60
|
-
variant,
|
|
61
|
-
enterClass,
|
|
62
|
-
exitClass,
|
|
63
|
-
exitDuration = 0
|
|
64
|
-
} = options;
|
|
65
|
-
const region = toastRegion(container);
|
|
66
|
-
const active = region[TOAST_SET] ??= /* @__PURE__ */ new Set();
|
|
67
|
-
if (mode === "replace") {
|
|
68
|
-
for (const d of [...active]) {
|
|
69
|
-
if (collapse === "instant") d.removeNow();
|
|
70
|
-
else d();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const el = document.createElement("div");
|
|
74
|
-
el.className = className;
|
|
75
|
-
if (variant !== void 0) el.classList.add(`${className}--${variant}`);
|
|
76
|
-
el.setAttribute("role", role);
|
|
77
|
-
region.appendChild(el);
|
|
78
|
-
const disposeMount = mount(el, typeof content === "function" ? content : () => content);
|
|
79
|
-
const state = { dismissed: false, removed: false, timer: void 0, exitTimer: void 0 };
|
|
80
|
-
if (enterClass !== void 0) {
|
|
81
|
-
globalThis.requestAnimationFrame(() => {
|
|
82
|
-
if (!state.dismissed) el.classList.add(enterClass);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
const remove = () => {
|
|
86
|
-
if (state.removed) return;
|
|
87
|
-
state.removed = true;
|
|
88
|
-
state.dismissed = true;
|
|
89
|
-
if (state.exitTimer !== void 0) clearTimeout(state.exitTimer);
|
|
90
|
-
disposeMount();
|
|
91
|
-
el.remove();
|
|
92
|
-
active.delete(dismiss);
|
|
93
|
-
};
|
|
94
|
-
const removeNow = () => {
|
|
95
|
-
if (state.timer !== void 0) clearTimeout(state.timer);
|
|
96
|
-
remove();
|
|
97
|
-
};
|
|
98
|
-
const fadeOut = () => {
|
|
99
|
-
if (state.dismissed) return;
|
|
100
|
-
state.dismissed = true;
|
|
101
|
-
if (state.timer !== void 0) clearTimeout(state.timer);
|
|
102
|
-
if (enterClass !== void 0) el.classList.remove(enterClass);
|
|
103
|
-
if (exitClass !== void 0) el.classList.add(exitClass);
|
|
104
|
-
if (exitClass !== void 0 || exitDuration > 0) {
|
|
105
|
-
state.exitTimer = setTimeout(remove, exitDuration);
|
|
106
|
-
} else {
|
|
107
|
-
remove();
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
function dismiss(options2) {
|
|
111
|
-
if (options2?.instant === true) removeNow();
|
|
112
|
-
else fadeOut();
|
|
113
|
-
}
|
|
114
|
-
dismiss.removeNow = removeNow;
|
|
115
|
-
active.add(dismiss);
|
|
116
|
-
if (duration > 0) state.timer = setTimeout(fadeOut, duration);
|
|
117
|
-
return { el, dismiss };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/overlay.ts
|
|
121
|
-
var FOCUSABLE = 'a[href],area[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),iframe,[tabindex]:not([tabindex="-1"]),[contenteditable="true"]';
|
|
122
|
-
function focusable(root) {
|
|
123
|
-
return Array.from(root.querySelectorAll(FOCUSABLE)).filter(
|
|
124
|
-
(el) => !el.hasAttribute("hidden")
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
function overlay(content, options = {}) {
|
|
128
|
-
const {
|
|
129
|
-
container = document.body,
|
|
130
|
-
className = "kerf-overlay",
|
|
131
|
-
dismiss = ["escape", "backdrop"],
|
|
132
|
-
initialFocus = true,
|
|
133
|
-
trap = true,
|
|
134
|
-
role = "dialog",
|
|
135
|
-
onDismiss,
|
|
136
|
-
outsideIgnore
|
|
137
|
-
} = options;
|
|
138
|
-
const triggers = dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];
|
|
139
|
-
const restoreTo = document.activeElement;
|
|
140
|
-
const wrapper = document.createElement("div");
|
|
141
|
-
wrapper.className = className;
|
|
142
|
-
if (trap) {
|
|
143
|
-
wrapper.setAttribute("role", role);
|
|
144
|
-
wrapper.setAttribute("aria-modal", "true");
|
|
145
|
-
}
|
|
146
|
-
container.appendChild(wrapper);
|
|
147
|
-
const disposeMount = mount(wrapper, typeof content === "function" ? content : () => content);
|
|
148
|
-
const removers = [];
|
|
149
|
-
const resultBox = {};
|
|
150
|
-
const result = new Promise((resolve) => {
|
|
151
|
-
resultBox.resolve = resolve;
|
|
152
|
-
});
|
|
153
|
-
const state = { closed: false };
|
|
154
|
-
function close(value) {
|
|
155
|
-
if (state.closed) return;
|
|
156
|
-
state.closed = true;
|
|
157
|
-
for (const remove of removers) remove();
|
|
158
|
-
disposeMount();
|
|
159
|
-
wrapper.remove();
|
|
160
|
-
if (restoreTo instanceof HTMLElement && restoreTo.isConnected) restoreTo.focus();
|
|
161
|
-
resultBox.resolve?.(value);
|
|
162
|
-
}
|
|
163
|
-
function userDismiss() {
|
|
164
|
-
onDismiss?.();
|
|
165
|
-
close();
|
|
166
|
-
}
|
|
167
|
-
const wantEscape = triggers.includes("escape");
|
|
168
|
-
if (wantEscape || trap) {
|
|
169
|
-
const onKeydown = (event) => {
|
|
170
|
-
if (wantEscape && event.key === "Escape") {
|
|
171
|
-
event.stopPropagation();
|
|
172
|
-
userDismiss();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (trap && event.key === "Tab") {
|
|
176
|
-
const items = focusable(wrapper);
|
|
177
|
-
if (items.length === 0) {
|
|
178
|
-
event.preventDefault();
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const first = items[0];
|
|
182
|
-
const last = items[items.length - 1];
|
|
183
|
-
const active = document.activeElement;
|
|
184
|
-
const outside = !wrapper.contains(active);
|
|
185
|
-
if (event.shiftKey && (active === first || outside)) {
|
|
186
|
-
event.preventDefault();
|
|
187
|
-
last.focus();
|
|
188
|
-
} else if (!event.shiftKey && (active === last || outside)) {
|
|
189
|
-
event.preventDefault();
|
|
190
|
-
first.focus();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
document.addEventListener("keydown", onKeydown, true);
|
|
195
|
-
removers.push(() => document.removeEventListener("keydown", onKeydown, true));
|
|
196
|
-
}
|
|
197
|
-
if (triggers.includes("backdrop")) {
|
|
198
|
-
const onClick = (event) => {
|
|
199
|
-
if (event.target === wrapper) userDismiss();
|
|
200
|
-
};
|
|
201
|
-
wrapper.addEventListener("click", onClick);
|
|
202
|
-
removers.push(() => wrapper.removeEventListener("click", onClick));
|
|
203
|
-
}
|
|
204
|
-
if (triggers.includes("outside")) {
|
|
205
|
-
const ignore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? outsideIgnore : [outsideIgnore];
|
|
206
|
-
const onDocClick = (event) => {
|
|
207
|
-
const target = event.target;
|
|
208
|
-
if (target === null) return;
|
|
209
|
-
if (wrapper.contains(target)) return;
|
|
210
|
-
if (ignore.some((el) => el === target || el.contains(target))) return;
|
|
211
|
-
userDismiss();
|
|
212
|
-
};
|
|
213
|
-
document.addEventListener("click", onDocClick, true);
|
|
214
|
-
removers.push(() => document.removeEventListener("click", onDocClick, true));
|
|
215
|
-
}
|
|
216
|
-
if (initialFocus !== false) {
|
|
217
|
-
if (typeof initialFocus === "string") {
|
|
218
|
-
wrapper.querySelector(initialFocus)?.focus();
|
|
219
|
-
} else {
|
|
220
|
-
const first = focusable(wrapper)[0];
|
|
221
|
-
if (first !== void 0) {
|
|
222
|
-
first.focus();
|
|
223
|
-
} else {
|
|
224
|
-
wrapper.tabIndex = -1;
|
|
225
|
-
wrapper.focus();
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return { el: wrapper, close, result };
|
|
230
|
-
}
|
|
40
|
+
// src/overlay-dialogs.ts
|
|
231
41
|
function confirm(message, options = {}) {
|
|
232
42
|
const {
|
|
233
43
|
container,
|
|
@@ -236,6 +46,7 @@ function confirm(message, options = {}) {
|
|
|
236
46
|
okText = "OK",
|
|
237
47
|
cancelText = "Cancel",
|
|
238
48
|
danger = false,
|
|
49
|
+
native = false,
|
|
239
50
|
render
|
|
240
51
|
} = options;
|
|
241
52
|
const body = render !== void 0 ? render({ message, ok: { "data-confirm": "ok" }, cancel: { "data-confirm": "cancel" } }) : jsx("div", {
|
|
@@ -262,7 +73,8 @@ function confirm(message, options = {}) {
|
|
|
262
73
|
className: danger ? `${className} kerf-confirm--danger` : className,
|
|
263
74
|
dismiss: ["escape", "backdrop"],
|
|
264
75
|
initialFocus: '[data-confirm="ok"]',
|
|
265
|
-
trap: true
|
|
76
|
+
trap: true,
|
|
77
|
+
native
|
|
266
78
|
});
|
|
267
79
|
delegate(handle.el, "click", "[data-confirm]", (_event, el) => {
|
|
268
80
|
handle.close(el.getAttribute("data-confirm") === "ok");
|
|
@@ -280,6 +92,7 @@ function prompt(message, options = {}) {
|
|
|
280
92
|
okText = "OK",
|
|
281
93
|
cancelText = "Cancel",
|
|
282
94
|
validate,
|
|
95
|
+
native = false,
|
|
283
96
|
render
|
|
284
97
|
} = options;
|
|
285
98
|
const inputAttrs = {
|
|
@@ -320,7 +133,8 @@ function prompt(message, options = {}) {
|
|
|
320
133
|
className,
|
|
321
134
|
dismiss: ["escape", "backdrop"],
|
|
322
135
|
initialFocus: "[data-prompt-input]",
|
|
323
|
-
trap: true
|
|
136
|
+
trap: true,
|
|
137
|
+
native
|
|
324
138
|
});
|
|
325
139
|
const input = handle.el.querySelector("[data-prompt-input]");
|
|
326
140
|
const errorEl = handle.el.querySelector("[data-prompt-error]");
|
|
@@ -351,7 +165,15 @@ function prompt(message, options = {}) {
|
|
|
351
165
|
return handle.result.then((value) => typeof value === "string" ? value : null);
|
|
352
166
|
}
|
|
353
167
|
function form(fields, options = {}) {
|
|
354
|
-
const {
|
|
168
|
+
const {
|
|
169
|
+
container,
|
|
170
|
+
className = "kerf-overlay",
|
|
171
|
+
title,
|
|
172
|
+
okText = "OK",
|
|
173
|
+
cancelText = "Cancel",
|
|
174
|
+
native = false,
|
|
175
|
+
render
|
|
176
|
+
} = options;
|
|
355
177
|
const fieldAttrs = (field) => ({
|
|
356
178
|
"data-field": field.name,
|
|
357
179
|
name: field.name,
|
|
@@ -401,7 +223,8 @@ function form(fields, options = {}) {
|
|
|
401
223
|
className,
|
|
402
224
|
dismiss: ["escape", "backdrop"],
|
|
403
225
|
initialFocus: "[data-field]",
|
|
404
|
-
trap: true
|
|
226
|
+
trap: true,
|
|
227
|
+
native
|
|
405
228
|
});
|
|
406
229
|
const byAttr = (attr, name) => Array.from(handle.el.querySelectorAll(`[${attr}]`)).find(
|
|
407
230
|
(el) => el.getAttribute(attr) === name
|
|
@@ -453,7 +276,7 @@ function form(fields, options = {}) {
|
|
|
453
276
|
);
|
|
454
277
|
}
|
|
455
278
|
function choice(message, actions, options = {}) {
|
|
456
|
-
const { container, className = "kerf-overlay", title, defaultValue, render } = options;
|
|
279
|
+
const { container, className = "kerf-overlay", title, defaultValue, native = false, render } = options;
|
|
457
280
|
const hasDefault = "defaultValue" in options;
|
|
458
281
|
const actionAttrs = actions.map((_, i) => ({ "data-choice": String(i) }));
|
|
459
282
|
const body = render !== void 0 ? render({ message, actions: actionAttrs }) : jsx("div", {
|
|
@@ -483,7 +306,8 @@ function choice(message, actions, options = {}) {
|
|
|
483
306
|
className,
|
|
484
307
|
dismiss: ["escape", "backdrop"],
|
|
485
308
|
initialFocus: "[data-choice]",
|
|
486
|
-
trap: true
|
|
309
|
+
trap: true,
|
|
310
|
+
native
|
|
487
311
|
});
|
|
488
312
|
delegate(handle.el, "click", "[data-choice]", (_event, el) => {
|
|
489
313
|
resolveChoice(actions[Number(el.getAttribute("data-choice"))].value);
|
|
@@ -501,6 +325,229 @@ function choice(message, actions, options = {}) {
|
|
|
501
325
|
void handle.result.then(() => resolveChoice(null));
|
|
502
326
|
return result;
|
|
503
327
|
}
|
|
328
|
+
|
|
329
|
+
// src/overlay-toast.ts
|
|
330
|
+
var TOAST_SET = /* @__PURE__ */ Symbol("kerf.toasts");
|
|
331
|
+
function toastRegion(container) {
|
|
332
|
+
if (container !== void 0) return container;
|
|
333
|
+
const existing = document.querySelector(".kerf-toasts");
|
|
334
|
+
if (existing !== null) return existing;
|
|
335
|
+
const region = document.createElement("div");
|
|
336
|
+
region.className = "kerf-toasts";
|
|
337
|
+
region.setAttribute("aria-live", "polite");
|
|
338
|
+
document.body.appendChild(region);
|
|
339
|
+
return region;
|
|
340
|
+
}
|
|
341
|
+
function toast(content, options = {}) {
|
|
342
|
+
const {
|
|
343
|
+
container,
|
|
344
|
+
className = "kerf-toast",
|
|
345
|
+
duration = 4e3,
|
|
346
|
+
role = "status",
|
|
347
|
+
mode = "stack",
|
|
348
|
+
collapse = "fade",
|
|
349
|
+
variant,
|
|
350
|
+
enterClass,
|
|
351
|
+
exitClass,
|
|
352
|
+
exitDuration = 0
|
|
353
|
+
} = options;
|
|
354
|
+
const region = toastRegion(container);
|
|
355
|
+
const active = region[TOAST_SET] ??= /* @__PURE__ */ new Set();
|
|
356
|
+
if (mode === "replace") {
|
|
357
|
+
for (const d of [...active]) {
|
|
358
|
+
if (collapse === "instant") d.removeNow();
|
|
359
|
+
else d();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const el = document.createElement("div");
|
|
363
|
+
el.className = className;
|
|
364
|
+
if (variant !== void 0) el.classList.add(`${className}--${variant}`);
|
|
365
|
+
el.setAttribute("role", role);
|
|
366
|
+
region.appendChild(el);
|
|
367
|
+
const disposeMount = mount(el, typeof content === "function" ? content : () => content);
|
|
368
|
+
const state = { dismissed: false, removed: false, timer: void 0, exitTimer: void 0 };
|
|
369
|
+
if (enterClass !== void 0) {
|
|
370
|
+
globalThis.requestAnimationFrame(() => {
|
|
371
|
+
if (!state.dismissed) el.classList.add(enterClass);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
const remove = () => {
|
|
375
|
+
if (state.removed) return;
|
|
376
|
+
state.removed = true;
|
|
377
|
+
state.dismissed = true;
|
|
378
|
+
if (state.exitTimer !== void 0) clearTimeout(state.exitTimer);
|
|
379
|
+
disposeMount();
|
|
380
|
+
el.remove();
|
|
381
|
+
active.delete(dismiss);
|
|
382
|
+
};
|
|
383
|
+
const removeNow = () => {
|
|
384
|
+
if (state.timer !== void 0) clearTimeout(state.timer);
|
|
385
|
+
remove();
|
|
386
|
+
};
|
|
387
|
+
const fadeOut = () => {
|
|
388
|
+
if (state.dismissed) return;
|
|
389
|
+
state.dismissed = true;
|
|
390
|
+
if (state.timer !== void 0) clearTimeout(state.timer);
|
|
391
|
+
if (enterClass !== void 0) el.classList.remove(enterClass);
|
|
392
|
+
if (exitClass !== void 0) el.classList.add(exitClass);
|
|
393
|
+
if (exitClass !== void 0 || exitDuration > 0) {
|
|
394
|
+
state.exitTimer = setTimeout(remove, exitDuration);
|
|
395
|
+
} else {
|
|
396
|
+
remove();
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
function dismiss(options2) {
|
|
400
|
+
if (options2?.instant === true) removeNow();
|
|
401
|
+
else fadeOut();
|
|
402
|
+
}
|
|
403
|
+
dismiss.removeNow = removeNow;
|
|
404
|
+
active.add(dismiss);
|
|
405
|
+
if (duration > 0) state.timer = setTimeout(fadeOut, duration);
|
|
406
|
+
return { el, dismiss };
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/overlay.ts
|
|
410
|
+
var FOCUSABLE = 'a[href],area[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),iframe,[tabindex]:not([tabindex="-1"]),[contenteditable="true"]';
|
|
411
|
+
function focusable(root) {
|
|
412
|
+
return Array.from(root.querySelectorAll(FOCUSABLE)).filter(
|
|
413
|
+
(el) => !el.hasAttribute("hidden")
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
function supportsDialog() {
|
|
417
|
+
return typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
|
|
418
|
+
}
|
|
419
|
+
function supportsPopover() {
|
|
420
|
+
return typeof HTMLElement !== "undefined" && typeof HTMLElement.prototype.showPopover === "function";
|
|
421
|
+
}
|
|
422
|
+
function overlay(content, options = {}) {
|
|
423
|
+
const {
|
|
424
|
+
container = document.body,
|
|
425
|
+
className = "kerf-overlay",
|
|
426
|
+
dismiss = ["escape", "backdrop"],
|
|
427
|
+
initialFocus = true,
|
|
428
|
+
trap = true,
|
|
429
|
+
role = "dialog",
|
|
430
|
+
onDismiss,
|
|
431
|
+
outsideIgnore,
|
|
432
|
+
native = false
|
|
433
|
+
} = options;
|
|
434
|
+
const triggers = dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];
|
|
435
|
+
const restoreTo = document.activeElement;
|
|
436
|
+
const useDialog = native && trap && supportsDialog();
|
|
437
|
+
const usePopover = native && !trap && supportsPopover();
|
|
438
|
+
const wrapper = useDialog ? document.createElement("dialog") : document.createElement("div");
|
|
439
|
+
wrapper.className = className;
|
|
440
|
+
if (usePopover) wrapper.setAttribute("popover", "manual");
|
|
441
|
+
if (trap && !useDialog) {
|
|
442
|
+
wrapper.setAttribute("role", role);
|
|
443
|
+
wrapper.setAttribute("aria-modal", "true");
|
|
444
|
+
}
|
|
445
|
+
container.appendChild(wrapper);
|
|
446
|
+
const disposeMount = mount(wrapper, typeof content === "function" ? content : () => content);
|
|
447
|
+
let nativeOpened = false;
|
|
448
|
+
if (useDialog) {
|
|
449
|
+
wrapper.showModal();
|
|
450
|
+
nativeOpened = true;
|
|
451
|
+
} else if (usePopover) {
|
|
452
|
+
wrapper.showPopover();
|
|
453
|
+
wrapper.style.inset = "auto";
|
|
454
|
+
nativeOpened = true;
|
|
455
|
+
}
|
|
456
|
+
const removers = [];
|
|
457
|
+
const resultBox = {};
|
|
458
|
+
const result = new Promise((resolve) => {
|
|
459
|
+
resultBox.resolve = resolve;
|
|
460
|
+
});
|
|
461
|
+
const state = { closed: false };
|
|
462
|
+
function close(value) {
|
|
463
|
+
if (state.closed) return;
|
|
464
|
+
state.closed = true;
|
|
465
|
+
for (const remove of removers) remove();
|
|
466
|
+
disposeMount();
|
|
467
|
+
if (nativeOpened) {
|
|
468
|
+
nativeOpened = false;
|
|
469
|
+
if (useDialog) wrapper.close();
|
|
470
|
+
else wrapper.hidePopover();
|
|
471
|
+
}
|
|
472
|
+
wrapper.remove();
|
|
473
|
+
if (restoreTo instanceof HTMLElement && restoreTo.isConnected) restoreTo.focus();
|
|
474
|
+
resultBox.resolve?.(value);
|
|
475
|
+
}
|
|
476
|
+
function userDismiss() {
|
|
477
|
+
onDismiss?.();
|
|
478
|
+
close();
|
|
479
|
+
}
|
|
480
|
+
const wantEscape = triggers.includes("escape");
|
|
481
|
+
if (useDialog) {
|
|
482
|
+
const onCancel = (event) => {
|
|
483
|
+
event.preventDefault();
|
|
484
|
+
if (wantEscape) userDismiss();
|
|
485
|
+
};
|
|
486
|
+
wrapper.addEventListener("cancel", onCancel);
|
|
487
|
+
removers.push(() => wrapper.removeEventListener("cancel", onCancel));
|
|
488
|
+
} else if (wantEscape || trap) {
|
|
489
|
+
const onKeydown = (event) => {
|
|
490
|
+
if (wantEscape && event.key === "Escape") {
|
|
491
|
+
event.stopPropagation();
|
|
492
|
+
userDismiss();
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
if (trap && event.key === "Tab") {
|
|
496
|
+
const items = focusable(wrapper);
|
|
497
|
+
if (items.length === 0) {
|
|
498
|
+
event.preventDefault();
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const first = items[0];
|
|
502
|
+
const last = items[items.length - 1];
|
|
503
|
+
const active = document.activeElement;
|
|
504
|
+
const outside = !wrapper.contains(active);
|
|
505
|
+
if (event.shiftKey && (active === first || outside)) {
|
|
506
|
+
event.preventDefault();
|
|
507
|
+
last.focus();
|
|
508
|
+
} else if (!event.shiftKey && (active === last || outside)) {
|
|
509
|
+
event.preventDefault();
|
|
510
|
+
first.focus();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
document.addEventListener("keydown", onKeydown, true);
|
|
515
|
+
removers.push(() => document.removeEventListener("keydown", onKeydown, true));
|
|
516
|
+
}
|
|
517
|
+
if (triggers.includes("backdrop")) {
|
|
518
|
+
const onClick = (event) => {
|
|
519
|
+
if (event.target === wrapper) userDismiss();
|
|
520
|
+
};
|
|
521
|
+
wrapper.addEventListener("click", onClick);
|
|
522
|
+
removers.push(() => wrapper.removeEventListener("click", onClick));
|
|
523
|
+
}
|
|
524
|
+
if (triggers.includes("outside")) {
|
|
525
|
+
const ignore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? outsideIgnore : [outsideIgnore];
|
|
526
|
+
const onDocClick = (event) => {
|
|
527
|
+
const target = event.target;
|
|
528
|
+
if (target === null) return;
|
|
529
|
+
if (wrapper.contains(target)) return;
|
|
530
|
+
if (ignore.some((el) => el === target || el.contains(target))) return;
|
|
531
|
+
userDismiss();
|
|
532
|
+
};
|
|
533
|
+
document.addEventListener("click", onDocClick, true);
|
|
534
|
+
removers.push(() => document.removeEventListener("click", onDocClick, true));
|
|
535
|
+
}
|
|
536
|
+
if (initialFocus !== false) {
|
|
537
|
+
if (typeof initialFocus === "string") {
|
|
538
|
+
wrapper.querySelector(initialFocus)?.focus();
|
|
539
|
+
} else {
|
|
540
|
+
const first = focusable(wrapper)[0];
|
|
541
|
+
if (first !== void 0) {
|
|
542
|
+
first.focus();
|
|
543
|
+
} else {
|
|
544
|
+
wrapper.tabIndex = -1;
|
|
545
|
+
wrapper.focus();
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return { el: wrapper, close, result };
|
|
550
|
+
}
|
|
504
551
|
function popover(anchor, content, options = {}) {
|
|
505
552
|
const {
|
|
506
553
|
container,
|
|
@@ -511,7 +558,8 @@ function popover(anchor, content, options = {}) {
|
|
|
511
558
|
dismiss = ["outside"],
|
|
512
559
|
initialFocus = false,
|
|
513
560
|
outsideIgnore,
|
|
514
|
-
onDismiss
|
|
561
|
+
onDismiss,
|
|
562
|
+
native = false
|
|
515
563
|
} = options;
|
|
516
564
|
const extraIgnore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? [...outsideIgnore] : [outsideIgnore];
|
|
517
565
|
const handle = overlay(content, {
|
|
@@ -521,7 +569,8 @@ function popover(anchor, content, options = {}) {
|
|
|
521
569
|
trap: false,
|
|
522
570
|
initialFocus,
|
|
523
571
|
onDismiss,
|
|
524
|
-
outsideIgnore: [anchor, ...extraIgnore]
|
|
572
|
+
outsideIgnore: [anchor, ...extraIgnore],
|
|
573
|
+
native
|
|
525
574
|
});
|
|
526
575
|
const stopReposition = autoReposition(handle.el, anchor, { placement, align, gap });
|
|
527
576
|
void handle.result.then(stopReposition);
|
|
@@ -536,13 +585,14 @@ function tooltip(anchor, content, options = {}) {
|
|
|
536
585
|
role = "tooltip",
|
|
537
586
|
placement = "top",
|
|
538
587
|
align = "start",
|
|
539
|
-
gap = 4
|
|
588
|
+
gap = 4,
|
|
589
|
+
native = false
|
|
540
590
|
} = options;
|
|
541
591
|
const body = typeof content === "function" ? content : typeof content === "string" ? jsx("span", { class: `${className}__text`, children: content }) : content;
|
|
542
592
|
const timers = {};
|
|
543
593
|
let current;
|
|
544
594
|
function show() {
|
|
545
|
-
const handle = overlay(body, { container, className, dismiss: false, trap: false, initialFocus: false });
|
|
595
|
+
const handle = overlay(body, { container, className, dismiss: false, trap: false, initialFocus: false, native });
|
|
546
596
|
handle.el.setAttribute("role", role);
|
|
547
597
|
const stop = autoReposition(handle.el, anchor, { placement, align, gap });
|
|
548
598
|
current = { handle, stop };
|