kerfjs 5.0.0-beta.52 → 5.0.0-beta.53
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 +329 -0
- package/README.md +4 -3
- package/ai/cursorrules +6 -5
- package/ai/manifest.json +9 -7
- package/ai/skill.md +6 -5
- package/dist/actions.js +3 -3
- package/dist/actions.js.map +1 -1
- package/dist/array-signal.js +1 -1
- package/dist/async.js +1 -1
- package/dist/attach.js +1 -68
- package/dist/attach.js.map +1 -1
- package/dist/{chunk-CEQMZYLR.js → chunk-3C6F6NM4.js} +1 -1
- package/dist/{chunk-CEQMZYLR.js.map → chunk-3C6F6NM4.js.map} +1 -1
- package/dist/{chunk-ZOIERTUW.js → chunk-BI4HGICV.js} +3 -3
- package/dist/{chunk-ZOIERTUW.js.map → chunk-BI4HGICV.js.map} +1 -1
- package/dist/{chunk-3GSWKMBZ.js → chunk-DU35YGKW.js} +3 -3
- package/dist/{chunk-3GSWKMBZ.js.map → chunk-DU35YGKW.js.map} +1 -1
- package/dist/chunk-FM6N2B4N.js +70 -0
- package/dist/chunk-FM6N2B4N.js.map +1 -0
- package/dist/{chunk-ELXVRKY2.js → chunk-H7WTRM6F.js} +2 -2
- package/dist/{chunk-ELXVRKY2.js.map → chunk-H7WTRM6F.js.map} +1 -1
- package/dist/{chunk-H3TTM7PQ.js → chunk-HTXQR2KL.js} +108 -106
- package/dist/chunk-HTXQR2KL.js.map +1 -0
- package/dist/{chunk-Y2FOYPBV.js → chunk-IHMDBBUJ.js} +2 -2
- package/dist/chunk-IHMDBBUJ.js.map +1 -0
- package/dist/{chunk-E5R5GNKE.js → chunk-X6OQ2HTR.js} +2 -2
- package/dist/{chunk-E5R5GNKE.js.map → chunk-X6OQ2HTR.js.map} +1 -1
- package/dist/dev.d.ts +31 -13
- package/dist/dev.js +34 -18
- package/dist/dev.js.map +1 -1
- package/dist/html.js +2 -2
- package/dist/index.d.ts +12 -7
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/dist/list.d.ts +3 -2
- package/dist/list.js +27 -13
- package/dist/list.js.map +1 -1
- package/dist/overlay.d.ts +0 -22
- package/dist/overlay.js +107 -30
- package/dist/overlay.js.map +1 -1
- package/dist/remount.js +2 -2
- package/dist/router.d.ts +13 -4
- package/dist/router.js +8 -4
- package/dist/router.js.map +1 -1
- package/dist/scope.d.ts +10 -2
- package/dist/scope.js +22 -28
- package/dist/scope.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/timing.d.ts +3 -2
- package/dist/timing.js +1 -1
- package/dist/timing.js.map +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/dist/chunk-H3TTM7PQ.js.map +0 -1
- package/dist/chunk-Y2FOYPBV.js.map +0 -1
package/dist/overlay.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { attach } from './chunk-FM6N2B4N.js';
|
|
2
|
+
import { mount } from './chunk-HTXQR2KL.js';
|
|
3
|
+
import { delegate } from './chunk-X6OQ2HTR.js';
|
|
3
4
|
|
|
4
5
|
|
|
5
|
-
import { jsx, escapeHtml } from './chunk-
|
|
6
|
-
|
|
6
|
+
import { jsx, escapeHtml } from './chunk-DU35YGKW.js';
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
import { devHooks } from './chunk-3C6F6NM4.js';
|
|
9
10
|
|
|
10
11
|
// src/overlay-position.ts
|
|
11
12
|
function positionAnchored(el, anchor, options = {}) {
|
|
@@ -54,10 +55,32 @@ function supportsDialog() {
|
|
|
54
55
|
function supportsPopover() {
|
|
55
56
|
return typeof HTMLElement !== "undefined" && typeof HTMLElement.prototype.showPopover === "function";
|
|
56
57
|
}
|
|
57
|
-
var
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
var OVERLAY_ARBITRATION = /* @__PURE__ */ Symbol("kerf.overlayArbitration");
|
|
59
|
+
function overlayArbitration(doc) {
|
|
60
|
+
return doc[OVERLAY_ARBITRATION] ??= {
|
|
61
|
+
stack: [],
|
|
62
|
+
handled: /* @__PURE__ */ new WeakSet()
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function modalDialogOpen(doc, arbitration) {
|
|
66
|
+
if (arbitration.stack.some(
|
|
67
|
+
({ el, modal }) => modal && el.isConnected && el.open === true
|
|
68
|
+
))
|
|
69
|
+
return true;
|
|
70
|
+
try {
|
|
71
|
+
for (const dialog of doc.querySelectorAll("dialog[open]"))
|
|
72
|
+
if (dialog.matches(":modal")) return true;
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
function ownsInput(stack, self, kind) {
|
|
78
|
+
for (let i = stack.indexOf(self) + 1; i < stack.length; i++) {
|
|
79
|
+
const above = stack[i];
|
|
80
|
+
if (above.modal || kind !== "trap" && above.triggers.includes(kind))
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
61
84
|
}
|
|
62
85
|
function assertInitialFocusSelector(selector) {
|
|
63
86
|
try {
|
|
@@ -84,9 +107,11 @@ function overlay(content, options = {}) {
|
|
|
84
107
|
if (typeof initialFocus === "string")
|
|
85
108
|
assertInitialFocusSelector(initialFocus);
|
|
86
109
|
const triggers = dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
const
|
|
110
|
+
const arbitration = overlayArbitration(document);
|
|
111
|
+
const liftOverModal = !native && modalDialogOpen(document, arbitration);
|
|
112
|
+
const topLayer = native || liftOverModal;
|
|
113
|
+
const useDialog = topLayer && trap && supportsDialog();
|
|
114
|
+
const usePopover = topLayer && !trap && supportsPopover();
|
|
90
115
|
const wrapper = useDialog ? document.createElement("dialog") : document.createElement("div");
|
|
91
116
|
wrapper.className = className;
|
|
92
117
|
if (usePopover) wrapper.setAttribute("popover", "manual");
|
|
@@ -94,9 +119,13 @@ function overlay(content, options = {}) {
|
|
|
94
119
|
wrapper.setAttribute("role", role);
|
|
95
120
|
wrapper.setAttribute("aria-modal", "true");
|
|
96
121
|
}
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
122
|
+
const surface = {
|
|
123
|
+
el: wrapper,
|
|
124
|
+
triggers,
|
|
125
|
+
modal: trap,
|
|
126
|
+
restoreTo: document.activeElement
|
|
127
|
+
};
|
|
128
|
+
const owns = (kind, event) => !(event !== void 0 && arbitration.handled.has(event)) && ownsInput(arbitration.stack, surface, kind);
|
|
100
129
|
const removers = [];
|
|
101
130
|
const resultBox = {};
|
|
102
131
|
const result = new Promise((resolve) => {
|
|
@@ -105,13 +134,33 @@ function overlay(content, options = {}) {
|
|
|
105
134
|
const state = { closed: false };
|
|
106
135
|
let disposeMount;
|
|
107
136
|
let nativeOpened = false;
|
|
137
|
+
if (!trap)
|
|
138
|
+
surface.liftAbove = () => {
|
|
139
|
+
if (!supportsPopover()) {
|
|
140
|
+
devHooks.overlayBlockedByModal?.("hidden");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const el = wrapper;
|
|
144
|
+
if (nativeOpened) el.hidePopover();
|
|
145
|
+
else {
|
|
146
|
+
wrapper.setAttribute("popover", "manual");
|
|
147
|
+
wrapper.style.inset = "auto";
|
|
148
|
+
}
|
|
149
|
+
el.showPopover();
|
|
150
|
+
nativeOpened = true;
|
|
151
|
+
if (wrapper.querySelector(FOCUSABLE) !== null)
|
|
152
|
+
devHooks.overlayBlockedByModal?.("inert");
|
|
153
|
+
};
|
|
108
154
|
function close(value) {
|
|
109
155
|
if (state.closed) return;
|
|
110
156
|
state.closed = true;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
157
|
+
const { stack } = arbitration;
|
|
158
|
+
const stackIndex = stack.indexOf(surface);
|
|
159
|
+
if (stackIndex !== -1) stack.splice(stackIndex, 1);
|
|
160
|
+
for (const other of stack)
|
|
161
|
+
if (other.restoreTo !== null && wrapper.contains(other.restoreTo))
|
|
162
|
+
other.restoreTo = surface.restoreTo;
|
|
163
|
+
const active = document.activeElement;
|
|
115
164
|
for (const remove of removers) remove();
|
|
116
165
|
disposeMount?.();
|
|
117
166
|
if (nativeOpened) {
|
|
@@ -120,9 +169,17 @@ function overlay(content, options = {}) {
|
|
|
120
169
|
else wrapper.hidePopover();
|
|
121
170
|
}
|
|
122
171
|
wrapper.remove();
|
|
172
|
+
restoreFocus(active);
|
|
173
|
+
resultBox.resolve?.(value);
|
|
174
|
+
}
|
|
175
|
+
function restoreFocus(active) {
|
|
176
|
+
if (active instanceof HTMLElement && active.isConnected && arbitration.stack.some((other) => other.el.contains(active))) {
|
|
177
|
+
if (document.activeElement !== active) active.focus();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const { restoreTo } = surface;
|
|
123
181
|
if (restoreTo instanceof HTMLElement && restoreTo.isConnected)
|
|
124
182
|
restoreTo.focus();
|
|
125
|
-
resultBox.resolve?.(value);
|
|
126
183
|
}
|
|
127
184
|
function userDismiss() {
|
|
128
185
|
onDismiss?.();
|
|
@@ -134,10 +191,12 @@ function overlay(content, options = {}) {
|
|
|
134
191
|
wrapper,
|
|
135
192
|
typeof content === "function" ? content : () => content
|
|
136
193
|
);
|
|
137
|
-
|
|
194
|
+
arbitration.stack.push(surface);
|
|
138
195
|
if (useDialog) {
|
|
139
196
|
wrapper.showModal();
|
|
140
197
|
nativeOpened = true;
|
|
198
|
+
for (const other of arbitration.stack)
|
|
199
|
+
if (other !== surface && other.el.isConnected) other.liftAbove?.();
|
|
141
200
|
} else if (usePopover) {
|
|
142
201
|
wrapper.showPopover();
|
|
143
202
|
nativeOpened = true;
|
|
@@ -149,25 +208,32 @@ function overlay(content, options = {}) {
|
|
|
149
208
|
close();
|
|
150
209
|
throw error;
|
|
151
210
|
}
|
|
211
|
+
if (liftOverModal) {
|
|
212
|
+
if (!useDialog && !usePopover) devHooks.overlayBlockedByModal?.("hidden");
|
|
213
|
+
else if (usePopover && wrapper.querySelector(FOCUSABLE) !== null)
|
|
214
|
+
devHooks.overlayBlockedByModal?.("inert");
|
|
215
|
+
}
|
|
152
216
|
return { el: wrapper, close, result };
|
|
153
217
|
function installDismissal() {
|
|
154
218
|
const wantEscape = triggers.includes("escape");
|
|
155
219
|
if (useDialog) {
|
|
156
220
|
const onCancel = (event) => {
|
|
157
221
|
event.preventDefault();
|
|
158
|
-
if (wantEscape) userDismiss();
|
|
222
|
+
if (wantEscape && owns("escape")) userDismiss();
|
|
159
223
|
};
|
|
160
224
|
wrapper.addEventListener("cancel", onCancel);
|
|
161
225
|
removers.push(() => wrapper.removeEventListener("cancel", onCancel));
|
|
162
226
|
} else if (wantEscape || trap) {
|
|
163
227
|
const onKeydown = (event) => {
|
|
164
|
-
if (!isTopmostFallback()) return;
|
|
165
228
|
if (wantEscape && event.key === "Escape") {
|
|
229
|
+
if (!owns("escape", event)) return;
|
|
166
230
|
event.stopPropagation();
|
|
231
|
+
event.preventDefault();
|
|
232
|
+
arbitration.handled.add(event);
|
|
167
233
|
userDismiss();
|
|
168
234
|
return;
|
|
169
235
|
}
|
|
170
|
-
if (trap && event.key === "Tab") {
|
|
236
|
+
if (trap && event.key === "Tab" && owns("trap")) {
|
|
171
237
|
const items = focusable(wrapper);
|
|
172
238
|
if (items.length === 0) {
|
|
173
239
|
event.preventDefault();
|
|
@@ -193,8 +259,9 @@ function overlay(content, options = {}) {
|
|
|
193
259
|
}
|
|
194
260
|
if (triggers.includes("backdrop")) {
|
|
195
261
|
const onClick = (event) => {
|
|
196
|
-
if (!
|
|
197
|
-
|
|
262
|
+
if (event.target !== wrapper || !owns("backdrop", event)) return;
|
|
263
|
+
arbitration.handled.add(event);
|
|
264
|
+
userDismiss();
|
|
198
265
|
};
|
|
199
266
|
wrapper.addEventListener("click", onClick);
|
|
200
267
|
removers.push(() => wrapper.removeEventListener("click", onClick));
|
|
@@ -202,11 +269,12 @@ function overlay(content, options = {}) {
|
|
|
202
269
|
if (triggers.includes("outside")) {
|
|
203
270
|
const ignore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? outsideIgnore : [outsideIgnore];
|
|
204
271
|
const onDocClick = (event) => {
|
|
205
|
-
if (!isTopmostFallback()) return;
|
|
206
272
|
const target = event.target;
|
|
207
273
|
if (target === null) return;
|
|
208
274
|
if (wrapper.contains(target)) return;
|
|
209
275
|
if (ignore.some((el) => el === target || el.contains(target))) return;
|
|
276
|
+
if (!owns("outside", event)) return;
|
|
277
|
+
arbitration.handled.add(event);
|
|
210
278
|
userDismiss();
|
|
211
279
|
};
|
|
212
280
|
document.addEventListener("click", onDocClick, true);
|
|
@@ -292,6 +360,7 @@ function popover(anchor, content, options = {}) {
|
|
|
292
360
|
throw error;
|
|
293
361
|
}
|
|
294
362
|
void handle.result.then(stopReposition);
|
|
363
|
+
void handle.result.then(attach(anchor, () => handle.close));
|
|
295
364
|
return handle;
|
|
296
365
|
}
|
|
297
366
|
function tooltip(anchor, content, options = {}) {
|
|
@@ -311,6 +380,7 @@ function tooltip(anchor, content, options = {}) {
|
|
|
311
380
|
let current;
|
|
312
381
|
let presence = 0;
|
|
313
382
|
function show() {
|
|
383
|
+
if (!anchor.isConnected) return;
|
|
314
384
|
const handle = overlay(body, {
|
|
315
385
|
container,
|
|
316
386
|
className,
|
|
@@ -327,13 +397,20 @@ function tooltip(anchor, content, options = {}) {
|
|
|
327
397
|
handle.close();
|
|
328
398
|
throw error;
|
|
329
399
|
}
|
|
330
|
-
|
|
400
|
+
const unwatch = attach(anchor, () => () => {
|
|
401
|
+
presence = 0;
|
|
402
|
+
if (timers.hide !== void 0) clearTimeout(timers.hide);
|
|
403
|
+
hide();
|
|
404
|
+
});
|
|
405
|
+
current = { handle, stop, unwatch };
|
|
331
406
|
}
|
|
332
407
|
function hide() {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
current.handle.close();
|
|
408
|
+
const shown = current;
|
|
409
|
+
if (shown === void 0) return;
|
|
336
410
|
current = void 0;
|
|
411
|
+
shown.unwatch();
|
|
412
|
+
shown.stop();
|
|
413
|
+
shown.handle.close();
|
|
337
414
|
}
|
|
338
415
|
const onEnter = (event) => {
|
|
339
416
|
presence |= event.type === "focus" ? 2 : 1;
|