kerfjs 4.4.0 → 4.5.0-beta.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 +284 -104
- package/LICENSE +1 -1
- package/README.md +73 -54
- package/ai/cursorrules +130 -48
- package/ai/manifest.json +63 -5
- package/ai/skill.md +148 -65
- package/dist/actions.d.ts +1 -1
- package/dist/actions.js +4 -4
- package/dist/actions.js.map +1 -1
- package/dist/array-signal.js +5 -5
- package/dist/async.js +34 -24
- package/dist/async.js.map +1 -1
- package/dist/attach.d.ts +11 -8
- package/dist/attach.js +54 -4
- package/dist/attach.js.map +1 -1
- package/dist/{chunk-QIP723L4.js → chunk-5WRGJZV6.js} +4 -3
- package/dist/chunk-5WRGJZV6.js.map +1 -0
- package/dist/{chunk-GY4XV2UV.js → chunk-BDX3R4OM.js} +4 -3
- package/dist/chunk-BDX3R4OM.js.map +1 -0
- package/dist/{chunk-VVDJLWMP.js → chunk-CEQMZYLR.js} +2 -2
- package/dist/chunk-CEQMZYLR.js.map +1 -0
- package/dist/{chunk-KEZTD6H4.js → chunk-E5R5GNKE.js} +15 -5
- package/dist/chunk-E5R5GNKE.js.map +1 -0
- package/dist/{chunk-MRYM3O3V.js → chunk-ELXVRKY2.js} +12 -9
- package/dist/chunk-ELXVRKY2.js.map +1 -0
- package/dist/{chunk-U32TFTGZ.js → chunk-MK42GLPV.js} +3 -3
- package/dist/chunk-MK42GLPV.js.map +1 -0
- package/dist/{chunk-SUPUPSBE.js → chunk-QFUNWHKH.js} +42 -20
- package/dist/chunk-QFUNWHKH.js.map +1 -0
- package/dist/{chunk-SRWQKB33.js → chunk-V757BT6U.js} +206 -111
- package/dist/chunk-V757BT6U.js.map +1 -0
- package/dist/{chunk-YHH7OUFA.js → chunk-WKIPLNVO.js} +3 -3
- package/dist/chunk-WKIPLNVO.js.map +1 -0
- package/dist/{chunk-3APBEVHF.js → chunk-Y2FOYPBV.js} +3 -3
- package/dist/{chunk-3APBEVHF.js.map → chunk-Y2FOYPBV.js.map} +1 -1
- package/dist/{chunk-SAYPJ6XR.js → chunk-ZOIERTUW.js} +10 -6
- package/dist/chunk-ZOIERTUW.js.map +1 -0
- package/dist/dev.d.ts +9 -6
- package/dist/dev.js +66 -19
- package/dist/dev.js.map +1 -1
- package/dist/html.d.ts +1 -1
- package/dist/html.js +8 -7
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +28 -19
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime.js +5 -5
- package/dist/list.d.ts +1 -1
- package/dist/list.js +304 -213
- package/dist/list.js.map +1 -1
- package/dist/overlay.d.ts +190 -280
- package/dist/overlay.js +471 -364
- package/dist/overlay.js.map +1 -1
- package/dist/remount.d.ts +5 -3
- package/dist/remount.js +29 -10
- package/dist/remount.js.map +1 -1
- package/dist/router.d.ts +1 -1
- package/dist/router.js +73 -28
- package/dist/router.js.map +1 -1
- package/dist/scope.d.ts +4 -3
- package/dist/scope.js +11 -10
- package/dist/scope.js.map +1 -1
- package/dist/testing.js +4 -4
- package/dist/timing.d.ts +3 -2
- package/dist/timing.js +5 -5
- package/dist/timing.js.map +1 -1
- package/llms.txt +13 -6
- package/package.json +35 -13
- package/setup/cli.mjs +90 -0
- package/setup/index.d.mts +37 -0
- package/setup/index.mjs +1347 -0
- package/setup/jsonc.mjs +201 -0
- package/setup/state.schema.json +56 -0
- package/dist/chunk-GY4XV2UV.js.map +0 -1
- package/dist/chunk-KEZTD6H4.js.map +0 -1
- package/dist/chunk-MRYM3O3V.js.map +0 -1
- package/dist/chunk-QIP723L4.js.map +0 -1
- package/dist/chunk-SAYPJ6XR.js.map +0 -1
- package/dist/chunk-SRWQKB33.js.map +0 -1
- package/dist/chunk-SUPUPSBE.js.map +0 -1
- package/dist/chunk-U32TFTGZ.js.map +0 -1
- package/dist/chunk-VVDJLWMP.js.map +0 -1
- package/dist/chunk-YHH7OUFA.js.map +0 -1
- /package/dist/{attrSelector-Cmu2ZoGO.d.ts → attr-Cmu2ZoGO.d.ts} +0 -0
package/dist/overlay.js
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
import { mount } from './chunk-
|
|
2
|
-
import { delegate } from './chunk-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { jsx } from './chunk-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { mount } from './chunk-V757BT6U.js';
|
|
2
|
+
import { delegate } from './chunk-E5R5GNKE.js';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import { jsx, escapeHtml } from './chunk-QFUNWHKH.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
9
|
|
|
10
10
|
// src/overlay-position.ts
|
|
11
11
|
function positionAnchored(el, anchor, options = {}) {
|
|
12
12
|
const { placement = "bottom", align = "start", gap = 4 } = options;
|
|
13
13
|
el.style.position = "fixed";
|
|
14
14
|
el.style.margin = "0";
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const belowTop =
|
|
20
|
-
const aboveTop =
|
|
15
|
+
const anchorRect = anchor.getBoundingClientRect();
|
|
16
|
+
const elementRect = el.getBoundingClientRect();
|
|
17
|
+
const viewportWidth = window.innerWidth;
|
|
18
|
+
const viewportHeight = window.innerHeight;
|
|
19
|
+
const belowTop = anchorRect.bottom + gap;
|
|
20
|
+
const aboveTop = anchorRect.top - gap - elementRect.height;
|
|
21
21
|
let below = placement !== "top";
|
|
22
|
-
if (below && belowTop +
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
if (below && belowTop + elementRect.height > viewportHeight && aboveTop >= 0)
|
|
23
|
+
below = false;
|
|
24
|
+
else if (!below && aboveTop < 0 && belowTop + elementRect.height <= viewportHeight)
|
|
25
|
+
below = true;
|
|
26
|
+
let left = align === "end" ? anchorRect.right - elementRect.width : anchorRect.left;
|
|
27
|
+
left = Math.max(0, Math.min(left, viewportWidth - elementRect.width));
|
|
26
28
|
el.style.left = `${left}px`;
|
|
27
29
|
el.style.top = `${below ? belowTop : aboveTop}px`;
|
|
28
30
|
}
|
|
@@ -37,91 +39,362 @@ function autoReposition(el, anchor, options = {}) {
|
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
// src/overlay-
|
|
41
|
-
|
|
42
|
+
// src/overlay-core.ts
|
|
43
|
+
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"]';
|
|
44
|
+
function focusable(root) {
|
|
45
|
+
const items = Array.from(
|
|
46
|
+
root.querySelectorAll(FOCUSABLE)
|
|
47
|
+
).filter((el) => !el.hasAttribute("hidden") && el.tabIndex >= 0);
|
|
48
|
+
for (const el of items) if (!el.hasAttribute("tabindex")) el.tabIndex = 0;
|
|
49
|
+
return items;
|
|
50
|
+
}
|
|
51
|
+
function supportsDialog() {
|
|
52
|
+
return typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
|
|
53
|
+
}
|
|
54
|
+
function supportsPopover() {
|
|
55
|
+
return typeof HTMLElement !== "undefined" && typeof HTMLElement.prototype.showPopover === "function";
|
|
56
|
+
}
|
|
57
|
+
var FALLBACK_OVERLAY_STACK = /* @__PURE__ */ Symbol("kerf.fallbackOverlayStack");
|
|
58
|
+
function fallbackOverlayStack(wrapper) {
|
|
59
|
+
const document2 = wrapper.ownerDocument;
|
|
60
|
+
return document2[FALLBACK_OVERLAY_STACK] ??= [];
|
|
61
|
+
}
|
|
62
|
+
function overlay(content, options = {}) {
|
|
63
|
+
const {
|
|
64
|
+
container = document.body,
|
|
65
|
+
className = "kerf-overlay",
|
|
66
|
+
dismiss = ["escape", "backdrop"],
|
|
67
|
+
initialFocus = true,
|
|
68
|
+
trap = true,
|
|
69
|
+
role = "dialog",
|
|
70
|
+
onDismiss,
|
|
71
|
+
outsideIgnore,
|
|
72
|
+
native = false
|
|
73
|
+
} = options;
|
|
74
|
+
const triggers = dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];
|
|
75
|
+
const restoreTo = document.activeElement;
|
|
76
|
+
const useDialog = native && trap && supportsDialog();
|
|
77
|
+
const usePopover = native && !trap && supportsPopover();
|
|
78
|
+
const wrapper = useDialog ? document.createElement("dialog") : document.createElement("div");
|
|
79
|
+
wrapper.className = className;
|
|
80
|
+
if (usePopover) wrapper.setAttribute("popover", "manual");
|
|
81
|
+
if (trap && !useDialog) {
|
|
82
|
+
wrapper.setAttribute("role", role);
|
|
83
|
+
wrapper.setAttribute("aria-modal", "true");
|
|
84
|
+
}
|
|
85
|
+
container.appendChild(wrapper);
|
|
86
|
+
const fallback = !useDialog && !usePopover;
|
|
87
|
+
const fallbackStack = fallback ? fallbackOverlayStack(wrapper) : void 0;
|
|
88
|
+
const isTopmostFallback = () => fallbackStack === void 0 || fallbackStack[fallbackStack.length - 1] === wrapper;
|
|
89
|
+
const disposeMount = mount(
|
|
90
|
+
wrapper,
|
|
91
|
+
typeof content === "function" ? content : () => content
|
|
92
|
+
);
|
|
93
|
+
fallbackStack?.push(wrapper);
|
|
94
|
+
let nativeOpened = false;
|
|
95
|
+
if (useDialog) {
|
|
96
|
+
wrapper.showModal();
|
|
97
|
+
nativeOpened = true;
|
|
98
|
+
} else if (usePopover) {
|
|
99
|
+
wrapper.showPopover();
|
|
100
|
+
wrapper.style.inset = "auto";
|
|
101
|
+
nativeOpened = true;
|
|
102
|
+
}
|
|
103
|
+
const removers = [];
|
|
104
|
+
const resultBox = {};
|
|
105
|
+
const result = new Promise((resolve) => {
|
|
106
|
+
resultBox.resolve = resolve;
|
|
107
|
+
});
|
|
108
|
+
const state = { closed: false };
|
|
109
|
+
function close(value) {
|
|
110
|
+
if (state.closed) return;
|
|
111
|
+
state.closed = true;
|
|
112
|
+
if (fallbackStack !== void 0) {
|
|
113
|
+
const stackIndex = fallbackStack.indexOf(wrapper);
|
|
114
|
+
if (stackIndex !== -1) fallbackStack.splice(stackIndex, 1);
|
|
115
|
+
}
|
|
116
|
+
for (const remove of removers) remove();
|
|
117
|
+
disposeMount();
|
|
118
|
+
if (nativeOpened) {
|
|
119
|
+
nativeOpened = false;
|
|
120
|
+
if (useDialog) wrapper.close();
|
|
121
|
+
else wrapper.hidePopover();
|
|
122
|
+
}
|
|
123
|
+
wrapper.remove();
|
|
124
|
+
if (restoreTo instanceof HTMLElement && restoreTo.isConnected)
|
|
125
|
+
restoreTo.focus();
|
|
126
|
+
resultBox.resolve?.(value);
|
|
127
|
+
}
|
|
128
|
+
function userDismiss() {
|
|
129
|
+
onDismiss?.();
|
|
130
|
+
close();
|
|
131
|
+
}
|
|
132
|
+
const wantEscape = triggers.includes("escape");
|
|
133
|
+
if (useDialog) {
|
|
134
|
+
const onCancel = (event) => {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
if (wantEscape) userDismiss();
|
|
137
|
+
};
|
|
138
|
+
wrapper.addEventListener("cancel", onCancel);
|
|
139
|
+
removers.push(() => wrapper.removeEventListener("cancel", onCancel));
|
|
140
|
+
} else if (wantEscape || trap) {
|
|
141
|
+
const onKeydown = (event) => {
|
|
142
|
+
if (!isTopmostFallback()) return;
|
|
143
|
+
if (wantEscape && event.key === "Escape") {
|
|
144
|
+
event.stopPropagation();
|
|
145
|
+
userDismiss();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (trap && event.key === "Tab") {
|
|
149
|
+
const items = focusable(wrapper);
|
|
150
|
+
if (items.length === 0) {
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const first = items[0];
|
|
155
|
+
const last = items[items.length - 1];
|
|
156
|
+
const active = document.activeElement;
|
|
157
|
+
const outside = !wrapper.contains(active);
|
|
158
|
+
if (event.shiftKey && (active === first || outside)) {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
last.focus();
|
|
161
|
+
} else if (!event.shiftKey && (active === last || outside)) {
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
first.focus();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
document.addEventListener("keydown", onKeydown, true);
|
|
168
|
+
removers.push(
|
|
169
|
+
() => document.removeEventListener("keydown", onKeydown, true)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (triggers.includes("backdrop")) {
|
|
173
|
+
const onClick = (event) => {
|
|
174
|
+
if (!isTopmostFallback()) return;
|
|
175
|
+
if (event.target === wrapper) userDismiss();
|
|
176
|
+
};
|
|
177
|
+
wrapper.addEventListener("click", onClick);
|
|
178
|
+
removers.push(() => wrapper.removeEventListener("click", onClick));
|
|
179
|
+
}
|
|
180
|
+
if (triggers.includes("outside")) {
|
|
181
|
+
const ignore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? outsideIgnore : [outsideIgnore];
|
|
182
|
+
const onDocClick = (event) => {
|
|
183
|
+
if (!isTopmostFallback()) return;
|
|
184
|
+
const target = event.target;
|
|
185
|
+
if (target === null) return;
|
|
186
|
+
if (wrapper.contains(target)) return;
|
|
187
|
+
if (ignore.some((el) => el === target || el.contains(target))) return;
|
|
188
|
+
userDismiss();
|
|
189
|
+
};
|
|
190
|
+
document.addEventListener("click", onDocClick, true);
|
|
191
|
+
removers.push(
|
|
192
|
+
() => document.removeEventListener("click", onDocClick, true)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (initialFocus !== false) {
|
|
196
|
+
if (typeof initialFocus === "string") {
|
|
197
|
+
wrapper.querySelector(initialFocus)?.focus();
|
|
198
|
+
} else {
|
|
199
|
+
const first = focusable(wrapper)[0];
|
|
200
|
+
if (first !== void 0) {
|
|
201
|
+
first.focus();
|
|
202
|
+
} else {
|
|
203
|
+
wrapper.tabIndex = -1;
|
|
204
|
+
wrapper.focus();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return { el: wrapper, close, result };
|
|
209
|
+
}
|
|
210
|
+
function popover(anchor, content, options = {}) {
|
|
211
|
+
const {
|
|
212
|
+
container,
|
|
213
|
+
className = "kerf-popover",
|
|
214
|
+
placement = "bottom",
|
|
215
|
+
align = "start",
|
|
216
|
+
gap = 4,
|
|
217
|
+
dismiss = ["outside"],
|
|
218
|
+
initialFocus = false,
|
|
219
|
+
outsideIgnore,
|
|
220
|
+
onDismiss,
|
|
221
|
+
native = false
|
|
222
|
+
} = options;
|
|
223
|
+
const extraIgnore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? [...outsideIgnore] : [outsideIgnore];
|
|
224
|
+
const handle = overlay(content, {
|
|
225
|
+
container,
|
|
226
|
+
className,
|
|
227
|
+
dismiss,
|
|
228
|
+
trap: false,
|
|
229
|
+
initialFocus,
|
|
230
|
+
onDismiss,
|
|
231
|
+
outsideIgnore: [anchor, ...extraIgnore],
|
|
232
|
+
native
|
|
233
|
+
});
|
|
234
|
+
const stopReposition = autoReposition(handle.el, anchor, {
|
|
235
|
+
placement,
|
|
236
|
+
align,
|
|
237
|
+
gap
|
|
238
|
+
});
|
|
239
|
+
void handle.result.then(stopReposition);
|
|
240
|
+
return handle;
|
|
241
|
+
}
|
|
242
|
+
function tooltip(anchor, content, options = {}) {
|
|
243
|
+
const {
|
|
244
|
+
container,
|
|
245
|
+
className = "kerf-tooltip",
|
|
246
|
+
delay = 400,
|
|
247
|
+
hideDelay = 100,
|
|
248
|
+
role = "tooltip",
|
|
249
|
+
placement = "top",
|
|
250
|
+
align = "start",
|
|
251
|
+
gap = 4,
|
|
252
|
+
native = false
|
|
253
|
+
} = options;
|
|
254
|
+
const body = typeof content === "function" ? content : typeof content === "string" ? jsx("span", { class: `${className}__text`, children: content }) : content;
|
|
255
|
+
const timers = {};
|
|
256
|
+
let current;
|
|
257
|
+
let presence = 0;
|
|
258
|
+
function show() {
|
|
259
|
+
const handle = overlay(body, {
|
|
260
|
+
container,
|
|
261
|
+
className,
|
|
262
|
+
dismiss: false,
|
|
263
|
+
trap: false,
|
|
264
|
+
initialFocus: false,
|
|
265
|
+
native
|
|
266
|
+
});
|
|
267
|
+
handle.el.setAttribute("role", role);
|
|
268
|
+
const stop = autoReposition(handle.el, anchor, { placement, align, gap });
|
|
269
|
+
current = { handle, stop };
|
|
270
|
+
}
|
|
271
|
+
function hide() {
|
|
272
|
+
if (current === void 0) return;
|
|
273
|
+
current.stop();
|
|
274
|
+
current.handle.close();
|
|
275
|
+
current = void 0;
|
|
276
|
+
}
|
|
277
|
+
const onEnter = (event) => {
|
|
278
|
+
presence |= event.type === "focus" ? 2 : 1;
|
|
279
|
+
if (timers.hide !== void 0) clearTimeout(timers.hide);
|
|
280
|
+
if (current !== void 0) return;
|
|
281
|
+
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
282
|
+
timers.show = setTimeout(show, delay);
|
|
283
|
+
};
|
|
284
|
+
const onLeave = (event) => {
|
|
285
|
+
presence &= event.type === "blur" ? -3 : -2;
|
|
286
|
+
if (presence) return;
|
|
287
|
+
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
288
|
+
if (current === void 0) return;
|
|
289
|
+
timers.hide = setTimeout(hide, hideDelay);
|
|
290
|
+
};
|
|
291
|
+
anchor.addEventListener("pointerenter", onEnter);
|
|
292
|
+
anchor.addEventListener("pointerleave", onLeave);
|
|
293
|
+
anchor.addEventListener("focus", onEnter);
|
|
294
|
+
anchor.addEventListener("blur", onLeave);
|
|
295
|
+
return () => {
|
|
296
|
+
anchor.removeEventListener("pointerenter", onEnter);
|
|
297
|
+
anchor.removeEventListener("pointerleave", onLeave);
|
|
298
|
+
anchor.removeEventListener("focus", onEnter);
|
|
299
|
+
anchor.removeEventListener("blur", onLeave);
|
|
300
|
+
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
301
|
+
if (timers.hide !== void 0) clearTimeout(timers.hide);
|
|
302
|
+
hide();
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/overlay-choice.ts
|
|
307
|
+
function choice(message, actions, options = {}) {
|
|
42
308
|
const {
|
|
43
309
|
container,
|
|
44
310
|
className = "kerf-overlay",
|
|
45
311
|
title,
|
|
46
|
-
|
|
47
|
-
cancelText = "Cancel",
|
|
48
|
-
danger = false,
|
|
312
|
+
defaultValue,
|
|
49
313
|
native = false,
|
|
50
314
|
render
|
|
51
315
|
} = options;
|
|
52
|
-
const
|
|
53
|
-
|
|
316
|
+
const hasDefault = "defaultValue" in options;
|
|
317
|
+
const actionAttrs = actions.map((_, i) => ({ "data-choice": String(i) }));
|
|
318
|
+
const body = render !== void 0 ? render({ message, actions: actionAttrs }) : jsx("div", {
|
|
319
|
+
class: "kerf-choice",
|
|
54
320
|
children: [
|
|
55
|
-
title !== void 0 ? jsx("h2", { class: "kerf-
|
|
56
|
-
jsx("p", { class: "kerf-
|
|
321
|
+
title !== void 0 ? jsx("h2", { class: "kerf-choice__title", children: title }) : "",
|
|
322
|
+
jsx("p", { class: "kerf-choice__message", children: message }),
|
|
57
323
|
jsx("div", {
|
|
58
|
-
class: "kerf-
|
|
59
|
-
children:
|
|
60
|
-
|
|
61
|
-
jsx("button", {
|
|
324
|
+
class: "kerf-choice__actions",
|
|
325
|
+
children: actions.map(
|
|
326
|
+
(action, i) => jsx("button", {
|
|
62
327
|
type: "button",
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
children:
|
|
328
|
+
class: action.className !== void 0 ? `kerf-choice__action ${action.className}` : "kerf-choice__action",
|
|
329
|
+
...actionAttrs[i],
|
|
330
|
+
children: action.label
|
|
66
331
|
})
|
|
67
|
-
|
|
332
|
+
)
|
|
68
333
|
})
|
|
69
334
|
]
|
|
70
335
|
});
|
|
336
|
+
let resolveChoice;
|
|
337
|
+
const result = new Promise((resolve) => {
|
|
338
|
+
resolveChoice = resolve;
|
|
339
|
+
});
|
|
71
340
|
const handle = overlay(body, {
|
|
72
341
|
container,
|
|
73
|
-
className
|
|
342
|
+
className,
|
|
74
343
|
dismiss: ["escape", "backdrop"],
|
|
75
|
-
initialFocus:
|
|
344
|
+
initialFocus: "[data-choice]",
|
|
76
345
|
trap: true,
|
|
77
346
|
native
|
|
78
347
|
});
|
|
79
|
-
delegate(handle.el, "click", "[data-
|
|
80
|
-
|
|
348
|
+
delegate(handle.el, "click", "[data-choice]", (_event, el) => {
|
|
349
|
+
resolveChoice(actions[Number(el.getAttribute("data-choice"))].value);
|
|
350
|
+
handle.close();
|
|
81
351
|
});
|
|
82
|
-
|
|
352
|
+
if (hasDefault) {
|
|
353
|
+
handle.el.addEventListener("keydown", (event) => {
|
|
354
|
+
if (event.key === "Enter") {
|
|
355
|
+
event.preventDefault();
|
|
356
|
+
resolveChoice(defaultValue);
|
|
357
|
+
handle.close();
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
void handle.result.then(() => resolveChoice(null));
|
|
362
|
+
return result;
|
|
83
363
|
}
|
|
84
|
-
|
|
364
|
+
|
|
365
|
+
// src/overlay-confirm.ts
|
|
366
|
+
function confirm(message, options = {}) {
|
|
85
367
|
const {
|
|
86
368
|
container,
|
|
87
369
|
className = "kerf-overlay",
|
|
88
370
|
title,
|
|
89
|
-
defaultValue = "",
|
|
90
|
-
placeholder,
|
|
91
|
-
inputType = "text",
|
|
92
371
|
okText = "OK",
|
|
93
372
|
cancelText = "Cancel",
|
|
94
|
-
|
|
373
|
+
danger = false,
|
|
95
374
|
native = false,
|
|
96
375
|
render
|
|
97
376
|
} = options;
|
|
98
|
-
const inputAttrs = {
|
|
99
|
-
"data-prompt-input": "",
|
|
100
|
-
type: inputType,
|
|
101
|
-
value: defaultValue,
|
|
102
|
-
...placeholder !== void 0 ? { placeholder } : {}
|
|
103
|
-
};
|
|
104
377
|
const body = render !== void 0 ? render({
|
|
105
378
|
message,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
ok: { "data-prompt": "ok" },
|
|
109
|
-
cancel: { "data-prompt": "cancel" }
|
|
379
|
+
ok: { "data-confirm": "ok" },
|
|
380
|
+
cancel: { "data-confirm": "cancel" }
|
|
110
381
|
}) : jsx("div", {
|
|
111
|
-
class: "kerf-
|
|
382
|
+
class: "kerf-confirm",
|
|
112
383
|
children: [
|
|
113
|
-
title !== void 0 ? jsx("h2", { class: "kerf-
|
|
114
|
-
jsx("
|
|
115
|
-
jsx("input", { class: "kerf-prompt__input", ...inputAttrs }),
|
|
116
|
-
jsx("p", { class: "kerf-prompt__error", "data-prompt-error": "", children: "" }),
|
|
384
|
+
title !== void 0 ? jsx("h2", { class: "kerf-confirm__title", children: title }) : "",
|
|
385
|
+
jsx("p", { class: "kerf-confirm__message", children: message }),
|
|
117
386
|
jsx("div", {
|
|
118
|
-
class: "kerf-
|
|
387
|
+
class: "kerf-confirm__actions",
|
|
119
388
|
children: [
|
|
120
|
-
jsx("button", { type: "button", "data-prompt": "cancel", children: cancelText }),
|
|
121
389
|
jsx("button", {
|
|
122
390
|
type: "button",
|
|
123
|
-
"data-
|
|
124
|
-
|
|
391
|
+
"data-confirm": "cancel",
|
|
392
|
+
children: cancelText
|
|
393
|
+
}),
|
|
394
|
+
jsx("button", {
|
|
395
|
+
type: "button",
|
|
396
|
+
"data-confirm": "ok",
|
|
397
|
+
class: "kerf-confirm__ok",
|
|
125
398
|
children: okText
|
|
126
399
|
})
|
|
127
400
|
]
|
|
@@ -130,40 +403,19 @@ function prompt(message, options = {}) {
|
|
|
130
403
|
});
|
|
131
404
|
const handle = overlay(body, {
|
|
132
405
|
container,
|
|
133
|
-
className,
|
|
406
|
+
className: danger ? `${className} kerf-confirm--danger` : className,
|
|
134
407
|
dismiss: ["escape", "backdrop"],
|
|
135
|
-
initialFocus:
|
|
408
|
+
initialFocus: '[data-confirm="ok"]',
|
|
136
409
|
trap: true,
|
|
137
410
|
native
|
|
138
411
|
});
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (errorEl !== null) errorEl.hidden = true;
|
|
142
|
-
function attemptOk() {
|
|
143
|
-
const value = input.value;
|
|
144
|
-
const error = validate?.(value);
|
|
145
|
-
if (typeof error === "string" && error.length > 0) {
|
|
146
|
-
if (errorEl !== null) {
|
|
147
|
-
errorEl.textContent = error;
|
|
148
|
-
errorEl.hidden = false;
|
|
149
|
-
}
|
|
150
|
-
input.focus();
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
handle.close(value);
|
|
154
|
-
}
|
|
155
|
-
delegate(handle.el, "click", "[data-prompt]", (_event, el) => {
|
|
156
|
-
if (el.getAttribute("data-prompt") === "ok") attemptOk();
|
|
157
|
-
else handle.close(null);
|
|
158
|
-
});
|
|
159
|
-
handle.el.addEventListener("keydown", (event) => {
|
|
160
|
-
if (event.key === "Enter" && event.target === input) {
|
|
161
|
-
event.preventDefault();
|
|
162
|
-
attemptOk();
|
|
163
|
-
}
|
|
412
|
+
delegate(handle.el, "click", "[data-confirm]", (_event, el) => {
|
|
413
|
+
handle.close(el.getAttribute("data-confirm") === "ok");
|
|
164
414
|
});
|
|
165
|
-
return handle.result.then((value) =>
|
|
415
|
+
return handle.result.then((value) => value === true);
|
|
166
416
|
}
|
|
417
|
+
|
|
418
|
+
// src/overlay-form.ts
|
|
167
419
|
function form(fields, options = {}) {
|
|
168
420
|
const {
|
|
169
421
|
container,
|
|
@@ -198,16 +450,30 @@ function form(fields, options = {}) {
|
|
|
198
450
|
(field) => jsx("div", {
|
|
199
451
|
class: "kerf-form__field",
|
|
200
452
|
children: [
|
|
201
|
-
jsx("label", {
|
|
202
|
-
|
|
203
|
-
|
|
453
|
+
jsx("label", {
|
|
454
|
+
class: "kerf-form__label",
|
|
455
|
+
children: field.label ?? field.name
|
|
456
|
+
}),
|
|
457
|
+
jsx("input", {
|
|
458
|
+
class: "kerf-form__input",
|
|
459
|
+
...fieldAttrs(field)
|
|
460
|
+
}),
|
|
461
|
+
jsx("p", {
|
|
462
|
+
class: "kerf-form__error",
|
|
463
|
+
"data-field-error": field.name,
|
|
464
|
+
children: ""
|
|
465
|
+
})
|
|
204
466
|
]
|
|
205
467
|
})
|
|
206
468
|
),
|
|
207
469
|
jsx("div", {
|
|
208
470
|
class: "kerf-form__actions",
|
|
209
471
|
children: [
|
|
210
|
-
jsx("button", {
|
|
472
|
+
jsx("button", {
|
|
473
|
+
type: "button",
|
|
474
|
+
"data-form": "cancel",
|
|
475
|
+
children: cancelText
|
|
476
|
+
}),
|
|
211
477
|
jsx("button", {
|
|
212
478
|
type: "button",
|
|
213
479
|
"data-form": "ok",
|
|
@@ -226,13 +492,19 @@ function form(fields, options = {}) {
|
|
|
226
492
|
trap: true,
|
|
227
493
|
native
|
|
228
494
|
});
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
);
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
495
|
+
const errorFor = (name) => Array.from(
|
|
496
|
+
handle.el.querySelectorAll("[data-field-error]")
|
|
497
|
+
).find((el) => el.getAttribute("data-field-error") === name) ?? null;
|
|
498
|
+
const inputFor = (name) => {
|
|
499
|
+
const input = Array.from(
|
|
500
|
+
handle.el.querySelectorAll("input[data-field]")
|
|
501
|
+
).find((el) => el.getAttribute("data-field") === name);
|
|
502
|
+
if (input !== void 0) return input;
|
|
503
|
+
handle.close(null);
|
|
504
|
+
throw new Error(`form(): render missing <input data-field="${name}">.`);
|
|
505
|
+
};
|
|
235
506
|
for (const field of fields) {
|
|
507
|
+
inputFor(field.name);
|
|
236
508
|
const errorEl = errorFor(field.name);
|
|
237
509
|
if (errorEl !== null) errorEl.hidden = true;
|
|
238
510
|
}
|
|
@@ -240,7 +512,7 @@ function form(fields, options = {}) {
|
|
|
240
512
|
const record = {};
|
|
241
513
|
let firstInvalid = null;
|
|
242
514
|
for (const field of fields) {
|
|
243
|
-
const el =
|
|
515
|
+
const el = inputFor(field.name);
|
|
244
516
|
const value = el.value;
|
|
245
517
|
record[field.name] = value;
|
|
246
518
|
const error = field.validate?.(value);
|
|
@@ -275,55 +547,107 @@ function form(fields, options = {}) {
|
|
|
275
547
|
(value) => value !== null && typeof value === "object" ? value : null
|
|
276
548
|
);
|
|
277
549
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
550
|
+
|
|
551
|
+
// src/overlay-prompt.ts
|
|
552
|
+
function prompt(message, options = {}) {
|
|
553
|
+
const {
|
|
554
|
+
container,
|
|
555
|
+
className = "kerf-overlay",
|
|
556
|
+
title,
|
|
557
|
+
defaultValue = "",
|
|
558
|
+
placeholder,
|
|
559
|
+
inputType = "text",
|
|
560
|
+
okText = "OK",
|
|
561
|
+
cancelText = "Cancel",
|
|
562
|
+
validate,
|
|
563
|
+
native = false,
|
|
564
|
+
render
|
|
565
|
+
} = options;
|
|
566
|
+
const inputAttrs = {
|
|
567
|
+
"data-prompt-input": "",
|
|
568
|
+
type: inputType,
|
|
569
|
+
value: defaultValue,
|
|
570
|
+
...placeholder !== void 0 ? { placeholder } : {}
|
|
571
|
+
};
|
|
572
|
+
const body = render !== void 0 ? render({
|
|
573
|
+
message,
|
|
574
|
+
input: inputAttrs,
|
|
575
|
+
error: { "data-prompt-error": "" },
|
|
576
|
+
ok: { "data-prompt": "ok" },
|
|
577
|
+
cancel: { "data-prompt": "cancel" }
|
|
578
|
+
}) : jsx("div", {
|
|
579
|
+
class: "kerf-prompt",
|
|
284
580
|
children: [
|
|
285
|
-
title !== void 0 ? jsx("h2", { class: "kerf-
|
|
286
|
-
jsx("
|
|
581
|
+
title !== void 0 ? jsx("h2", { class: "kerf-prompt__title", children: title }) : "",
|
|
582
|
+
jsx("label", { class: "kerf-prompt__message", children: message }),
|
|
583
|
+
jsx("input", { class: "kerf-prompt__input", ...inputAttrs }),
|
|
584
|
+
jsx("p", {
|
|
585
|
+
class: "kerf-prompt__error",
|
|
586
|
+
"data-prompt-error": "",
|
|
587
|
+
children: ""
|
|
588
|
+
}),
|
|
287
589
|
jsx("div", {
|
|
288
|
-
class: "kerf-
|
|
289
|
-
children:
|
|
290
|
-
|
|
590
|
+
class: "kerf-prompt__actions",
|
|
591
|
+
children: [
|
|
592
|
+
jsx("button", {
|
|
291
593
|
type: "button",
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
594
|
+
"data-prompt": "cancel",
|
|
595
|
+
children: cancelText
|
|
596
|
+
}),
|
|
597
|
+
jsx("button", {
|
|
598
|
+
type: "button",
|
|
599
|
+
"data-prompt": "ok",
|
|
600
|
+
class: "kerf-prompt__ok",
|
|
601
|
+
children: okText
|
|
295
602
|
})
|
|
296
|
-
|
|
297
|
-
})
|
|
298
|
-
]
|
|
299
|
-
});
|
|
300
|
-
let resolveChoice;
|
|
301
|
-
const result = new Promise((resolve) => {
|
|
302
|
-
resolveChoice = resolve;
|
|
603
|
+
]
|
|
604
|
+
})
|
|
605
|
+
]
|
|
303
606
|
});
|
|
304
607
|
const handle = overlay(body, {
|
|
305
608
|
container,
|
|
306
609
|
className,
|
|
307
610
|
dismiss: ["escape", "backdrop"],
|
|
308
|
-
initialFocus: "[data-
|
|
611
|
+
initialFocus: "[data-prompt-input]",
|
|
309
612
|
trap: true,
|
|
310
613
|
native
|
|
311
614
|
});
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
615
|
+
const input = handle.el.querySelector(
|
|
616
|
+
"input[data-prompt-input]"
|
|
617
|
+
);
|
|
618
|
+
if (input === null) {
|
|
619
|
+
handle.close(null);
|
|
620
|
+
throw new Error("prompt(): render missing <input data-prompt-input>.");
|
|
621
|
+
}
|
|
622
|
+
const promptInput = input;
|
|
623
|
+
const errorEl = handle.el.querySelector("[data-prompt-error]");
|
|
624
|
+
if (errorEl !== null) errorEl.hidden = true;
|
|
625
|
+
function attemptOk() {
|
|
626
|
+
const value = promptInput.value;
|
|
627
|
+
const error = validate?.(value);
|
|
628
|
+
if (typeof error === "string" && error.length > 0) {
|
|
629
|
+
if (errorEl !== null) {
|
|
630
|
+
errorEl.textContent = error;
|
|
631
|
+
errorEl.hidden = false;
|
|
322
632
|
}
|
|
323
|
-
|
|
633
|
+
promptInput.focus();
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
handle.close(value);
|
|
324
637
|
}
|
|
325
|
-
|
|
326
|
-
|
|
638
|
+
delegate(handle.el, "click", "[data-prompt]", (_event, el) => {
|
|
639
|
+
if (el.getAttribute("data-prompt") === "ok") attemptOk();
|
|
640
|
+
else handle.close(null);
|
|
641
|
+
});
|
|
642
|
+
handle.el.addEventListener("keydown", (event) => {
|
|
643
|
+
if (event.key === "Enter" && event.target === promptInput) {
|
|
644
|
+
event.preventDefault();
|
|
645
|
+
attemptOk();
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
return handle.result.then(
|
|
649
|
+
(value) => typeof value === "string" ? value : null
|
|
650
|
+
);
|
|
327
651
|
}
|
|
328
652
|
|
|
329
653
|
// src/overlay-toast.ts
|
|
@@ -364,8 +688,14 @@ function toast(content, options = {}) {
|
|
|
364
688
|
if (variant !== void 0) el.classList.add(`${className}--${variant}`);
|
|
365
689
|
el.setAttribute("role", role);
|
|
366
690
|
region.appendChild(el);
|
|
367
|
-
const
|
|
368
|
-
const
|
|
691
|
+
const render = typeof content === "function" ? content : () => typeof content === "string" ? escapeHtml(content) : content;
|
|
692
|
+
const disposeMount = mount(el, render);
|
|
693
|
+
const state = {
|
|
694
|
+
dismissed: false,
|
|
695
|
+
removed: false,
|
|
696
|
+
timer: void 0,
|
|
697
|
+
exitTimer: void 0
|
|
698
|
+
};
|
|
369
699
|
if (enterClass !== void 0) {
|
|
370
700
|
globalThis.requestAnimationFrame(() => {
|
|
371
701
|
if (!state.dismissed) el.classList.add(enterClass);
|
|
@@ -406,229 +736,6 @@ function toast(content, options = {}) {
|
|
|
406
736
|
return { el, dismiss };
|
|
407
737
|
}
|
|
408
738
|
|
|
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
|
-
}
|
|
551
|
-
function popover(anchor, content, options = {}) {
|
|
552
|
-
const {
|
|
553
|
-
container,
|
|
554
|
-
className = "kerf-popover",
|
|
555
|
-
placement = "bottom",
|
|
556
|
-
align = "start",
|
|
557
|
-
gap = 4,
|
|
558
|
-
dismiss = ["outside"],
|
|
559
|
-
initialFocus = false,
|
|
560
|
-
outsideIgnore,
|
|
561
|
-
onDismiss,
|
|
562
|
-
native = false
|
|
563
|
-
} = options;
|
|
564
|
-
const extraIgnore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? [...outsideIgnore] : [outsideIgnore];
|
|
565
|
-
const handle = overlay(content, {
|
|
566
|
-
container,
|
|
567
|
-
className,
|
|
568
|
-
dismiss,
|
|
569
|
-
trap: false,
|
|
570
|
-
initialFocus,
|
|
571
|
-
onDismiss,
|
|
572
|
-
outsideIgnore: [anchor, ...extraIgnore],
|
|
573
|
-
native
|
|
574
|
-
});
|
|
575
|
-
const stopReposition = autoReposition(handle.el, anchor, { placement, align, gap });
|
|
576
|
-
void handle.result.then(stopReposition);
|
|
577
|
-
return handle;
|
|
578
|
-
}
|
|
579
|
-
function tooltip(anchor, content, options = {}) {
|
|
580
|
-
const {
|
|
581
|
-
container,
|
|
582
|
-
className = "kerf-tooltip",
|
|
583
|
-
delay = 400,
|
|
584
|
-
hideDelay = 100,
|
|
585
|
-
role = "tooltip",
|
|
586
|
-
placement = "top",
|
|
587
|
-
align = "start",
|
|
588
|
-
gap = 4,
|
|
589
|
-
native = false
|
|
590
|
-
} = options;
|
|
591
|
-
const body = typeof content === "function" ? content : typeof content === "string" ? jsx("span", { class: `${className}__text`, children: content }) : content;
|
|
592
|
-
const timers = {};
|
|
593
|
-
let current;
|
|
594
|
-
function show() {
|
|
595
|
-
const handle = overlay(body, { container, className, dismiss: false, trap: false, initialFocus: false, native });
|
|
596
|
-
handle.el.setAttribute("role", role);
|
|
597
|
-
const stop = autoReposition(handle.el, anchor, { placement, align, gap });
|
|
598
|
-
current = { handle, stop };
|
|
599
|
-
}
|
|
600
|
-
function hide() {
|
|
601
|
-
if (current === void 0) return;
|
|
602
|
-
current.stop();
|
|
603
|
-
current.handle.close();
|
|
604
|
-
current = void 0;
|
|
605
|
-
}
|
|
606
|
-
const onEnter = () => {
|
|
607
|
-
if (timers.hide !== void 0) clearTimeout(timers.hide);
|
|
608
|
-
if (current !== void 0) return;
|
|
609
|
-
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
610
|
-
timers.show = setTimeout(show, delay);
|
|
611
|
-
};
|
|
612
|
-
const onLeave = () => {
|
|
613
|
-
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
614
|
-
if (current === void 0) return;
|
|
615
|
-
timers.hide = setTimeout(hide, hideDelay);
|
|
616
|
-
};
|
|
617
|
-
anchor.addEventListener("pointerenter", onEnter);
|
|
618
|
-
anchor.addEventListener("pointerleave", onLeave);
|
|
619
|
-
anchor.addEventListener("focus", onEnter);
|
|
620
|
-
anchor.addEventListener("blur", onLeave);
|
|
621
|
-
return () => {
|
|
622
|
-
anchor.removeEventListener("pointerenter", onEnter);
|
|
623
|
-
anchor.removeEventListener("pointerleave", onLeave);
|
|
624
|
-
anchor.removeEventListener("focus", onEnter);
|
|
625
|
-
anchor.removeEventListener("blur", onLeave);
|
|
626
|
-
if (timers.show !== void 0) clearTimeout(timers.show);
|
|
627
|
-
if (timers.hide !== void 0) clearTimeout(timers.hide);
|
|
628
|
-
hide();
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
|
|
632
739
|
export { autoReposition, choice, confirm, form, overlay, popover, positionAnchored, prompt, toast, tooltip };
|
|
633
|
-
|
|
740
|
+
|
|
634
741
|
//# sourceMappingURL=overlay.js.map
|