kerfjs 5.0.0-beta.77 → 5.0.0-beta.79

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 CHANGED
@@ -6,8 +6,40 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Removed
10
+
11
+ - **Breaking (`@kerfjs/ui`, 5.0 beta):** remove the deprecated `TabScaffold` component and type aliases, `wireTabScaffold` and `WireTabScaffoldOptions`, and the `tab-scaffold`, `wire-tab-scaffold`, and `tab-scaffold.css` package subpaths. Use `TabNavigator`, `TabNavigatorTab`, `TabNavigatorProps`, `wireTabNavigator`, and their corresponding subpaths. The rendered DOM classes and data attributes remain stable. See `ui/docs/tab-navigator.md` for migration steps (`KF-CMK0W8`).
12
+
13
+ ### Added
14
+
15
+ - `TabNavigator`, `TabNavigatorTab`, `TabNavigatorProps`, and `wireTabNavigator` name the complete persistent bottom-tab layout. The matching module, wiring, and CSS subpaths are available; former `TabScaffold` names and paths were deprecated aliases in earlier 5.0 betas.
16
+
17
+ - `Pane` exposes its resolved logical inline content insets to child CSS, so a table can paint edge to edge while its cell text stays aligned, with or without `deepInset`.
18
+
19
+ - `Pane` and plain `TabNavigator` scenes accept `deepInset` for a 16px outer content gutter while nested Row, List, and Grid spacing remains at its normal 8px.
20
+
21
+ - The TabNavigator catalog now demonstrates a NavStack with a view-owned top toolbar and Pane above the persistent tab bar, including push, tab switch, and return.
22
+
23
+ - UI Doctor now checks component root class names, stylesheet names, and CSS selectors that reach into another local component.
24
+
25
+ - Configure modal `DialogSurface` viewport gutters and typed maximum heights, including a dynamic viewport cap, without application shadow-part overrides.
26
+
27
+ ### Changed
28
+
29
+ - Toolbar composition guidance and catalog metadata now allow direct `KerfUiContent` in every zone; `ToolbarControlGroup` remains the recommended shared chrome for related controls.
30
+
31
+ - The UI composition lint rule checks component parent requirements for direct content passed through a named zone prop.
32
+
33
+ - Toolbar zones center direct content by default while keeping ToolbarText, control groups, and standalone primary actions on their established control-band axis.
34
+
9
35
  ### Fixed
10
36
 
37
+ - The actionable ToolbarText catalog example uses the standard TokenSearchField toolbar presentation for its search control, and an empty TokenSearchField shows its placeholder.
38
+
39
+ - Preserve toolbar visibility and measurement state across app renders to prevent geometry-driven render loops and repeated observer/layout work (`KF-58HBRR`).
40
+
41
+ - Restore accessible native dialog names through `@kerfjs/ui/surface-scaffold/register`, preserving live title slots and headerless labels.
42
+
11
43
  - Validate remote CI freshness through newer-run searches and exact-run details before warning about a failed main build (`KF-X4PTHF`).
12
44
 
13
45
  - Select menus now shift their complete visible surface inside narrow viewport edges while preserving `fitMenu` trigger width (`KF-H4JBQP`).
package/ai/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "kerfjsVersion": "5.0.0-beta.77",
2
+ "kerfjsVersion": "5.0.0-beta.79",
3
3
  "files": [
4
4
  {
5
5
  "name": "skill",
package/dist/overlay.d.ts CHANGED
@@ -3,46 +3,6 @@ import { M as MountResult } from './mount-Bo2qOx25.js';
3
3
  import '@preact/signals-core';
4
4
  import './bindings-CYwoJpQb.js';
5
5
 
6
- /**
7
- * Anchored positioning primitives for `kerfjs/overlay` — position an element
8
- * relative to an anchor, with viewport flip + clamp. These are standalone: they
9
- * take any element and have no overlay lifecycle, so `popover()` / `tooltip()`
10
- * build on them but you can also position your own element (an inline hint, a
11
- * custom menu). Re-exported from `src/overlay.ts` so the public `kerfjs/overlay`
12
- * surface is unchanged (KF-511 split out of overlay.ts's dialog + toast code).
13
- */
14
- /** Vertical placement relative to an anchor (used by `popover`, {@link positionAnchored}, `tooltip`). */
15
- type PopoverPlacement = 'bottom' | 'top';
16
- /** Placement options for {@link positionAnchored} / {@link autoReposition}. */
17
- interface AnchorPositionOptions {
18
- /** Preferred side of the anchor; flips to the other side if it would overflow the viewport. Default `'bottom'`. */
19
- placement?: PopoverPlacement;
20
- /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */
21
- align?: 'start' | 'end';
22
- /** Gap in px between the anchor and the element. Default `4`. */
23
- gap?: number;
24
- }
25
- /**
26
- * One-shot: position `el` relative to `anchor` — below by default, flipping above
27
- * if it would overflow the viewport, aligned to a horizontal edge and clamped into
28
- * view. Sets `el.style` `position: fixed`, `margin: 0`, `left`, and `top` (fixed so
29
- * `left`/`top` are viewport coordinates, matching `getBoundingClientRect`). When an
30
- * ancestor makes itself the containing block for fixed descendants (a
31
- * `transform`, `filter`, `perspective`, or `contain` on a wrapping `<dialog>`),
32
- * `left`/`top` are translated (and unscaled) into that box's coordinates so `el`
33
- * still lands next to the anchor. This is
34
- * `popover()`'s placement core, usable on any element (an inline hint, a tooltip) —
35
- * no overlay lifecycle. Pair with {@link autoReposition} to keep it glued while open.
36
- */
37
- declare function positionAnchored(el: HTMLElement, anchor: Element, options?: AnchorPositionOptions): void;
38
- /**
39
- * Keep `el` positioned against `anchor` (via {@link positionAnchored}) as the page
40
- * scrolls or resizes. Positions once immediately, then re-runs on `scroll`
41
- * (capture phase — catches scrolls in any inner container, not just `window`) and
42
- * `resize`. Returns a disposer that removes the listeners.
43
- */
44
- declare function autoReposition(el: HTMLElement, anchor: Element, options?: AnchorPositionOptions): () => void;
45
-
46
6
  /** A user-initiated dismissal trigger. */
47
7
  type DismissTrigger = 'escape' | 'backdrop' | 'outside';
48
8
  /** Content for an overlay: static `SafeHtml`, or a render function `mount()` drives reactively. */
@@ -118,79 +78,6 @@ interface OverlayHandle {
118
78
  * error is rethrown.
119
79
  */
120
80
  declare function overlay(content: OverlayContent, options?: OverlayOptions): OverlayHandle;
121
- /** Options for {@link popover}. */
122
- interface PopoverOptions {
123
- /**
124
- * Where to append the popover wrapper. Default: when `anchor` sits inside an
125
- * open modal `<dialog>`, that dialog's `[data-kerf-overlay-host]` element (a
126
- * dialog kerf opened gets one automatically), so the popover is part of the
127
- * modal subtree and stays interactive; otherwise `document.body`.
128
- */
129
- container?: Element;
130
- /** Class on the wrapper. Default `'kerf-popover'`. */
131
- className?: string;
132
- /** Preferred side of the anchor. Flips to the other side if it would overflow the viewport. Default `'bottom'`. */
133
- placement?: PopoverPlacement;
134
- /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */
135
- align?: 'start' | 'end';
136
- /** Gap in px between the anchor and the popover. Default `4`. */
137
- gap?: number;
138
- /**
139
- * Which user actions dismiss the popover. Default `['outside']` (a click
140
- * outside the popover, the anchor exempt). Pass `false` to close only via `close()`.
141
- */
142
- dismiss?: DismissTrigger | DismissTrigger[] | false;
143
- /** Focus behavior on open. Default `false` (non-modal — leave focus alone). */
144
- initialFocus?: string | boolean;
145
- /** Extra elements (besides the anchor) whose clicks do NOT count as outside. */
146
- outsideIgnore?: Element | readonly Element[];
147
- /** Called on any user-initiated dismissal. */
148
- onDismiss?: () => void;
149
- /**
150
- * Host the popover in the browser top layer (the Popover API — `[popover]` +
151
- * `showPopover()`) where supported, so it stacks above any `z-index` without a
152
- * z-index war. Falls back to today's plain `<div>` where unsupported. kerf keeps
153
- * owning positioning + its own dismiss wiring; the popover is `popover="manual"`.
154
- * See {@link OverlayOptions.native}. Default `false`.
155
- */
156
- native?: boolean;
157
- }
158
- /**
159
- * Anchored, non-modal overlay: positions `content` relative to `anchor` (below by
160
- * default, flipping above if it would overflow, and clamped horizontally to the
161
- * viewport) and repositions on scroll / resize while open. A thin wrapper over
162
- * {@link overlay} with non-modal defaults — `trap: false`, `dismiss: ['outside']`,
163
- * and the anchor added to `outsideIgnore` so the trigger click doesn't self-close.
164
- * Returns the same {@link OverlayHandle}; `close()` also drops the reposition
165
- * listeners. `position: fixed` is set inline (you style everything else).
166
- */
167
- declare function popover(anchor: Element, content: OverlayContent, options?: PopoverOptions): OverlayHandle;
168
- /** Content for a {@link tooltip}: text (auto-escaped), `SafeHtml`, or a render function. */
169
- type TooltipContent = string | SafeHtml | (() => MountResult);
170
- /** Options for {@link tooltip}. */
171
- interface TooltipOptions extends AnchorPositionOptions {
172
- /** Where to append the tooltip wrapper. Default: the anchor's modal-dialog host slot (see {@link PopoverOptions.container}), else `document.body`. */
173
- container?: Element;
174
- /** Class on the wrapper. Default `'kerf-tooltip'`. */
175
- className?: string;
176
- /** Delay in ms before showing after hover/focus enters. Default `400`. */
177
- delay?: number;
178
- /** Delay in ms before hiding after hover/focus leaves. Default `100`. */
179
- hideDelay?: number;
180
- /** ARIA role on the wrapper. Default `'tooltip'`. */
181
- role?: string;
182
- /** Host the tooltip in the browser top layer (the Popover API) where supported. See {@link OverlayOptions.native}. Default `false`. */
183
- native?: boolean;
184
- }
185
- /**
186
- * A hover/focus-triggered, non-modal, auto-hiding tooltip anchored to `anchor`.
187
- * Shows after `delay` on `pointerenter`/`focus`, hides after `hideDelay` on
188
- * `pointerleave`/`blur`, and positions itself with {@link autoReposition} (above
189
- * the anchor by default). Unlike {@link popover} there is no click-dismiss model —
190
- * it follows the pointer/focus. Returns a disposer that removes the anchor
191
- * listeners and hides any shown tooltip. Structural only (kerf ships no CSS).
192
- */
193
- declare function tooltip(anchor: Element, content: TooltipContent, options?: TooltipOptions): () => void;
194
81
 
195
82
  /** One choosable action in a {@link choice} dialog. */
196
83
  interface ChoiceAction<R> {
@@ -311,6 +198,94 @@ interface FormOptions {
311
198
  /** A promise-based multi-field dialog. */
312
199
  declare function form(fields: readonly FormField[], options?: FormOptions): Promise<Record<string, string> | null>;
313
200
 
201
+ /**
202
+ * Anchored positioning primitives for `kerfjs/overlay` — position an element
203
+ * relative to an anchor, with viewport flip + clamp. These are standalone: they
204
+ * take any element and have no overlay lifecycle, so `popover()` / `tooltip()`
205
+ * build on them but you can also position your own element (an inline hint, a
206
+ * custom menu). Re-exported from `src/overlay.ts` so the public `kerfjs/overlay`
207
+ * surface is unchanged (KF-511 split out of overlay.ts's dialog + toast code).
208
+ */
209
+ /** Vertical placement relative to an anchor (used by `popover`, {@link positionAnchored}, `tooltip`). */
210
+ type PopoverPlacement = 'bottom' | 'top';
211
+ /** Placement options for {@link positionAnchored} / {@link autoReposition}. */
212
+ interface AnchorPositionOptions {
213
+ /** Preferred side of the anchor; flips to the other side if it would overflow the viewport. Default `'bottom'`. */
214
+ placement?: PopoverPlacement;
215
+ /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */
216
+ align?: 'start' | 'end';
217
+ /** Gap in px between the anchor and the element. Default `4`. */
218
+ gap?: number;
219
+ }
220
+ /**
221
+ * One-shot: position `el` relative to `anchor` — below by default, flipping above
222
+ * if it would overflow the viewport, aligned to a horizontal edge and clamped into
223
+ * view. Sets `el.style` `position: fixed`, `margin: 0`, `left`, and `top` (fixed so
224
+ * `left`/`top` are viewport coordinates, matching `getBoundingClientRect`). When an
225
+ * ancestor makes itself the containing block for fixed descendants (a
226
+ * `transform`, `filter`, `perspective`, or `contain` on a wrapping `<dialog>`),
227
+ * `left`/`top` are translated (and unscaled) into that box's coordinates so `el`
228
+ * still lands next to the anchor. This is
229
+ * `popover()`'s placement core, usable on any element (an inline hint, a tooltip) —
230
+ * no overlay lifecycle. Pair with {@link autoReposition} to keep it glued while open.
231
+ */
232
+ declare function positionAnchored(el: HTMLElement, anchor: Element, options?: AnchorPositionOptions): void;
233
+ /**
234
+ * Keep `el` positioned against `anchor` (via {@link positionAnchored}) as the page
235
+ * scrolls or resizes. Positions once immediately, then re-runs on `scroll`
236
+ * (capture phase — catches scrolls in any inner container, not just `window`) and
237
+ * `resize`. Returns a disposer that removes the listeners.
238
+ */
239
+ declare function autoReposition(el: HTMLElement, anchor: Element, options?: AnchorPositionOptions): () => void;
240
+
241
+ /** Options for {@link popover}. */
242
+ interface PopoverOptions {
243
+ /**
244
+ * Where to append the popover wrapper. Default: when `anchor` sits inside an
245
+ * open modal `<dialog>`, that dialog's `[data-kerf-overlay-host]` element (a
246
+ * dialog kerf opened gets one automatically), so the popover is part of the
247
+ * modal subtree and stays interactive; otherwise `document.body`.
248
+ */
249
+ container?: Element;
250
+ /** Class on the wrapper. Default `'kerf-popover'`. */
251
+ className?: string;
252
+ /** Preferred side of the anchor. Flips to the other side if it would overflow the viewport. Default `'bottom'`. */
253
+ placement?: PopoverPlacement;
254
+ /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */
255
+ align?: 'start' | 'end';
256
+ /** Gap in px between the anchor and the popover. Default `4`. */
257
+ gap?: number;
258
+ /**
259
+ * Which user actions dismiss the popover. Default `['outside']` (a click
260
+ * outside the popover, the anchor exempt). Pass `false` to close only via `close()`.
261
+ */
262
+ dismiss?: DismissTrigger | DismissTrigger[] | false;
263
+ /** Focus behavior on open. Default `false` (non-modal — leave focus alone). */
264
+ initialFocus?: string | boolean;
265
+ /** Extra elements (besides the anchor) whose clicks do NOT count as outside. */
266
+ outsideIgnore?: Element | readonly Element[];
267
+ /** Called on any user-initiated dismissal. */
268
+ onDismiss?: () => void;
269
+ /**
270
+ * Host the popover in the browser top layer (the Popover API — `[popover]` +
271
+ * `showPopover()`) where supported, so it stacks above any `z-index` without a
272
+ * z-index war. Falls back to today's plain `<div>` where unsupported. kerf keeps
273
+ * owning positioning + its own dismiss wiring; the popover is `popover="manual"`.
274
+ * See {@link OverlayOptions.native}. Default `false`.
275
+ */
276
+ native?: boolean;
277
+ }
278
+ /**
279
+ * Anchored, non-modal overlay: positions `content` relative to `anchor` (below by
280
+ * default, flipping above if it would overflow, and clamped horizontally to the
281
+ * viewport) and repositions on scroll / resize while open. A thin wrapper over
282
+ * {@link overlay} with non-modal defaults — `trap: false`, `dismiss: ['outside']`,
283
+ * and the anchor added to `outsideIgnore` so the trigger click doesn't self-close.
284
+ * Returns the same {@link OverlayHandle}; `close()` also drops the reposition
285
+ * listeners. `position: fixed` is set inline (you style everything else).
286
+ */
287
+ declare function popover(anchor: Element, content: OverlayContent, options?: PopoverOptions): OverlayHandle;
288
+
314
289
  /**
315
290
  * `toast()` for `kerfjs/overlay` — a non-modal, auto-dismissing notification that
316
291
  * stacks in a shared body-level region. Split out of `overlay.ts` (KF-513) since
@@ -383,4 +358,31 @@ interface ToastHandle {
383
358
  */
384
359
  declare function toast(content: ToastContent, options?: ToastOptions): ToastHandle;
385
360
 
361
+ /** Content for a {@link tooltip}: text (auto-escaped), `SafeHtml`, or a render function. */
362
+ type TooltipContent = string | SafeHtml | (() => MountResult);
363
+ /** Options for {@link tooltip}. */
364
+ interface TooltipOptions extends AnchorPositionOptions {
365
+ /** Where to append the tooltip wrapper. Default: the anchor's modal-dialog host slot (see {@link PopoverOptions.container}), else `document.body`. */
366
+ container?: Element;
367
+ /** Class on the wrapper. Default `'kerf-tooltip'`. */
368
+ className?: string;
369
+ /** Delay in ms before showing after hover/focus enters. Default `400`. */
370
+ delay?: number;
371
+ /** Delay in ms before hiding after hover/focus leaves. Default `100`. */
372
+ hideDelay?: number;
373
+ /** ARIA role on the wrapper. Default `'tooltip'`. */
374
+ role?: string;
375
+ /** Host the tooltip in the browser top layer (the Popover API) where supported. See {@link OverlayOptions.native}. Default `false`. */
376
+ native?: boolean;
377
+ }
378
+ /**
379
+ * A hover/focus-triggered, non-modal, auto-hiding tooltip anchored to `anchor`.
380
+ * Shows after `delay` on `pointerenter`/`focus`, hides after `hideDelay` on
381
+ * `pointerleave`/`blur`, and positions itself with {@link autoReposition} (above
382
+ * the anchor by default). Unlike {@link popover} there is no click-dismiss model —
383
+ * it follows the pointer/focus. Returns a disposer that removes the anchor
384
+ * listeners and hides any shown tooltip. Structural only (kerf ships no CSS).
385
+ */
386
+ declare function tooltip(anchor: Element, content: TooltipContent, options?: TooltipOptions): () => void;
387
+
386
388
  export { type AnchorPositionOptions, type ChoiceAction, type ChoiceOptions, type ChoiceRenderSlots, type ConfirmOptions, type ConfirmRenderSlots, type DismissTrigger, type FieldValidator, type FormField, type FormOptions, type FormRenderField, type FormRenderSlots, type OverlayContent, type OverlayHandle, type OverlayOptions, type PopoverOptions, type PopoverPlacement, type PromptOptions, type PromptRenderSlots, type ToastContent, type ToastHandle, type ToastOptions, type ToastVariant, type TooltipContent, type TooltipOptions, autoReposition, choice, confirm, form, overlay, popover, positionAnchored, prompt, toast, tooltip };
package/dist/overlay.js CHANGED
@@ -8,49 +8,6 @@ import { jsx, escapeHtml } from './chunk-UGNPDLNI.js';
8
8
  import { OVERLAY_HOST_SELECTOR } from './chunk-4TX6YJDM.js';
9
9
  import { devHooks } from './chunk-3C6F6NM4.js';
10
10
 
11
- // src/overlay-position.ts
12
- function positionAnchored(el, anchor, options = {}) {
13
- const { placement = "bottom", align = "start", gap = 4 } = options;
14
- el.style.position = "fixed";
15
- el.style.margin = "0";
16
- const anchorRect = anchor.getBoundingClientRect();
17
- const elementRect = el.getBoundingClientRect();
18
- const viewportWidth = window.innerWidth;
19
- const viewportHeight = window.innerHeight;
20
- const belowTop = anchorRect.bottom + gap;
21
- const aboveTop = anchorRect.top - gap - elementRect.height;
22
- let below = placement !== "top";
23
- if (below && belowTop + elementRect.height > viewportHeight && aboveTop >= 0)
24
- below = false;
25
- else if (!below && aboveTop < 0 && belowTop + elementRect.height <= viewportHeight)
26
- below = true;
27
- let left = align === "end" ? anchorRect.right - elementRect.width : anchorRect.left;
28
- left = Math.max(0, Math.min(left, viewportWidth - elementRect.width));
29
- const [originX, originY, scaleX, scaleY] = fixedOrigin(el);
30
- el.style.left = `${(left - originX) / scaleX}px`;
31
- el.style.top = `${((below ? belowTop : aboveTop) - originY) / scaleY}px`;
32
- }
33
- function fixedOrigin(el) {
34
- const parent = el.parentNode;
35
- if (!parent) return [0, 0, 1, 1];
36
- const probe = el.ownerDocument.createElement("div");
37
- probe.style.cssText = "position:fixed;left:0;top:0;width:1px;height:1px;margin:0;padding:0;border:0";
38
- parent.insertBefore(probe, el);
39
- const rect = probe.getBoundingClientRect();
40
- probe.remove();
41
- return [rect.left, rect.top, rect.width || 1, rect.height || 1];
42
- }
43
- function autoReposition(el, anchor, options = {}) {
44
- const reposition = () => positionAnchored(el, anchor, options);
45
- reposition();
46
- window.addEventListener("scroll", reposition, true);
47
- window.addEventListener("resize", reposition);
48
- return () => {
49
- window.removeEventListener("scroll", reposition, true);
50
- window.removeEventListener("resize", reposition);
51
- };
52
- }
53
-
54
11
  // src/overlay-core.ts
55
12
  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"]';
56
13
  function focusable(root) {
@@ -386,125 +343,6 @@ function wireDialog(handle, wire, settle) {
386
343
  return settle(value);
387
344
  });
388
345
  }
389
- function popover(anchor, content, options = {}) {
390
- const {
391
- container,
392
- className = "kerf-popover",
393
- placement = "bottom",
394
- align = "start",
395
- gap = 4,
396
- dismiss = ["outside"],
397
- initialFocus = false,
398
- outsideIgnore,
399
- onDismiss,
400
- native = false
401
- } = options;
402
- const extraIgnore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? [...outsideIgnore] : [outsideIgnore];
403
- const handle = overlay(content, {
404
- container: container ?? overlayHost(anchor),
405
- className,
406
- dismiss,
407
- trap: false,
408
- initialFocus,
409
- onDismiss,
410
- outsideIgnore: [anchor, ...extraIgnore],
411
- native
412
- });
413
- let stopReposition;
414
- try {
415
- stopReposition = autoReposition(handle.el, anchor, {
416
- placement,
417
- align,
418
- gap
419
- });
420
- } catch (error) {
421
- handle.close();
422
- throw error;
423
- }
424
- void handle.result.then(stopReposition);
425
- void handle.result.then(attach(anchor, () => handle.close));
426
- return handle;
427
- }
428
- function tooltip(anchor, content, options = {}) {
429
- const {
430
- container,
431
- className = "kerf-tooltip",
432
- delay = 400,
433
- hideDelay = 100,
434
- role = "tooltip",
435
- placement = "top",
436
- align = "start",
437
- gap = 4,
438
- native = false
439
- } = options;
440
- const body = typeof content === "function" ? content : typeof content === "string" ? jsx("span", { class: `${className}__text`, children: content }) : content;
441
- const timers = {};
442
- let current;
443
- let presence = 0;
444
- function show() {
445
- if (!anchor.isConnected) return;
446
- const handle = overlay(body, {
447
- container: container ?? overlayHost(anchor),
448
- className,
449
- dismiss: false,
450
- trap: false,
451
- initialFocus: false,
452
- native
453
- });
454
- handle.el.setAttribute("role", role);
455
- let stop;
456
- try {
457
- stop = autoReposition(handle.el, anchor, { placement, align, gap });
458
- } catch (error) {
459
- handle.close();
460
- throw error;
461
- }
462
- const unwatch = attach(anchor, () => () => {
463
- presence = 0;
464
- if (timers.hide !== void 0) clearTimeout(timers.hide);
465
- hide();
466
- });
467
- current = { handle, stop, unwatch };
468
- void handle.result.then(() => {
469
- if (current?.handle === handle) hide();
470
- });
471
- }
472
- function hide() {
473
- const shown = current;
474
- if (shown === void 0) return;
475
- current = void 0;
476
- shown.unwatch();
477
- shown.stop();
478
- shown.handle.close();
479
- }
480
- const onEnter = (event) => {
481
- presence |= event.type === "focus" ? 2 : 1;
482
- if (timers.hide !== void 0) clearTimeout(timers.hide);
483
- if (current !== void 0) return;
484
- if (timers.show !== void 0) clearTimeout(timers.show);
485
- timers.show = setTimeout(show, delay);
486
- };
487
- const onLeave = (event) => {
488
- presence &= event.type === "blur" ? -3 : -2;
489
- if (presence) return;
490
- if (timers.show !== void 0) clearTimeout(timers.show);
491
- if (current === void 0) return;
492
- timers.hide = setTimeout(hide, hideDelay);
493
- };
494
- anchor.addEventListener("pointerenter", onEnter);
495
- anchor.addEventListener("pointerleave", onLeave);
496
- anchor.addEventListener("focus", onEnter);
497
- anchor.addEventListener("blur", onLeave);
498
- return () => {
499
- anchor.removeEventListener("pointerenter", onEnter);
500
- anchor.removeEventListener("pointerleave", onLeave);
501
- anchor.removeEventListener("focus", onEnter);
502
- anchor.removeEventListener("blur", onLeave);
503
- if (timers.show !== void 0) clearTimeout(timers.show);
504
- if (timers.hide !== void 0) clearTimeout(timers.hide);
505
- hide();
506
- };
507
- }
508
346
 
509
347
  // src/overlay-choice.ts
510
348
  function choice(message, actions, options = {}) {
@@ -888,6 +726,90 @@ function form(fields, options = {}) {
888
726
  );
889
727
  }
890
728
 
729
+ // src/overlay-position.ts
730
+ function positionAnchored(el, anchor, options = {}) {
731
+ const { placement = "bottom", align = "start", gap = 4 } = options;
732
+ el.style.position = "fixed";
733
+ el.style.margin = "0";
734
+ const anchorRect = anchor.getBoundingClientRect();
735
+ const elementRect = el.getBoundingClientRect();
736
+ const viewportWidth = window.innerWidth;
737
+ const viewportHeight = window.innerHeight;
738
+ const belowTop = anchorRect.bottom + gap;
739
+ const aboveTop = anchorRect.top - gap - elementRect.height;
740
+ let below = placement !== "top";
741
+ if (below && belowTop + elementRect.height > viewportHeight && aboveTop >= 0)
742
+ below = false;
743
+ else if (!below && aboveTop < 0 && belowTop + elementRect.height <= viewportHeight)
744
+ below = true;
745
+ let left = align === "end" ? anchorRect.right - elementRect.width : anchorRect.left;
746
+ left = Math.max(0, Math.min(left, viewportWidth - elementRect.width));
747
+ const [originX, originY, scaleX, scaleY] = fixedOrigin(el);
748
+ el.style.left = `${(left - originX) / scaleX}px`;
749
+ el.style.top = `${((below ? belowTop : aboveTop) - originY) / scaleY}px`;
750
+ }
751
+ function fixedOrigin(el) {
752
+ const parent = el.parentNode;
753
+ if (!parent) return [0, 0, 1, 1];
754
+ const probe = el.ownerDocument.createElement("div");
755
+ probe.style.cssText = "position:fixed;left:0;top:0;width:1px;height:1px;margin:0;padding:0;border:0";
756
+ parent.insertBefore(probe, el);
757
+ const rect = probe.getBoundingClientRect();
758
+ probe.remove();
759
+ return [rect.left, rect.top, rect.width || 1, rect.height || 1];
760
+ }
761
+ function autoReposition(el, anchor, options = {}) {
762
+ const reposition = () => positionAnchored(el, anchor, options);
763
+ reposition();
764
+ window.addEventListener("scroll", reposition, true);
765
+ window.addEventListener("resize", reposition);
766
+ return () => {
767
+ window.removeEventListener("scroll", reposition, true);
768
+ window.removeEventListener("resize", reposition);
769
+ };
770
+ }
771
+
772
+ // src/overlay-popover.ts
773
+ function popover(anchor, content, options = {}) {
774
+ const {
775
+ container,
776
+ className = "kerf-popover",
777
+ placement = "bottom",
778
+ align = "start",
779
+ gap = 4,
780
+ dismiss = ["outside"],
781
+ initialFocus = false,
782
+ outsideIgnore,
783
+ onDismiss,
784
+ native = false
785
+ } = options;
786
+ const extraIgnore = outsideIgnore === void 0 ? [] : Array.isArray(outsideIgnore) ? [...outsideIgnore] : [outsideIgnore];
787
+ const handle = overlay(content, {
788
+ container: container ?? overlayHost(anchor),
789
+ className,
790
+ dismiss,
791
+ trap: false,
792
+ initialFocus,
793
+ onDismiss,
794
+ outsideIgnore: [anchor, ...extraIgnore],
795
+ native
796
+ });
797
+ let stopReposition;
798
+ try {
799
+ stopReposition = autoReposition(handle.el, anchor, {
800
+ placement,
801
+ align,
802
+ gap
803
+ });
804
+ } catch (error) {
805
+ handle.close();
806
+ throw error;
807
+ }
808
+ void handle.result.then(stopReposition);
809
+ void handle.result.then(attach(anchor, () => handle.close));
810
+ return handle;
811
+ }
812
+
891
813
  // src/overlay-toast.ts
892
814
  var TOAST_SET = /* @__PURE__ */ Symbol("kerf.toasts");
893
815
  function toastRegion(container) {
@@ -974,6 +896,88 @@ function toast(content, options = {}) {
974
896
  return { el, dismiss };
975
897
  }
976
898
 
899
+ // src/overlay-tooltip.ts
900
+ function tooltip(anchor, content, options = {}) {
901
+ const {
902
+ container,
903
+ className = "kerf-tooltip",
904
+ delay = 400,
905
+ hideDelay = 100,
906
+ role = "tooltip",
907
+ placement = "top",
908
+ align = "start",
909
+ gap = 4,
910
+ native = false
911
+ } = options;
912
+ const body = typeof content === "function" ? content : typeof content === "string" ? jsx("span", { class: `${className}__text`, children: content }) : content;
913
+ const timers = {};
914
+ let current;
915
+ let presence = 0;
916
+ function show() {
917
+ if (!anchor.isConnected) return;
918
+ const handle = overlay(body, {
919
+ container: container ?? overlayHost(anchor),
920
+ className,
921
+ dismiss: false,
922
+ trap: false,
923
+ initialFocus: false,
924
+ native
925
+ });
926
+ handle.el.setAttribute("role", role);
927
+ let stop;
928
+ try {
929
+ stop = autoReposition(handle.el, anchor, { placement, align, gap });
930
+ } catch (error) {
931
+ handle.close();
932
+ throw error;
933
+ }
934
+ const unwatch = attach(anchor, () => () => {
935
+ presence = 0;
936
+ if (timers.hide !== void 0) clearTimeout(timers.hide);
937
+ hide();
938
+ });
939
+ current = { handle, stop, unwatch };
940
+ void handle.result.then(() => {
941
+ if (current?.handle === handle) hide();
942
+ });
943
+ }
944
+ function hide() {
945
+ const shown = current;
946
+ if (shown === void 0) return;
947
+ current = void 0;
948
+ shown.unwatch();
949
+ shown.stop();
950
+ shown.handle.close();
951
+ }
952
+ const onEnter = (event) => {
953
+ presence |= event.type === "focus" ? 2 : 1;
954
+ if (timers.hide !== void 0) clearTimeout(timers.hide);
955
+ if (current !== void 0) return;
956
+ if (timers.show !== void 0) clearTimeout(timers.show);
957
+ timers.show = setTimeout(show, delay);
958
+ };
959
+ const onLeave = (event) => {
960
+ presence &= event.type === "blur" ? -3 : -2;
961
+ if (presence) return;
962
+ if (timers.show !== void 0) clearTimeout(timers.show);
963
+ if (current === void 0) return;
964
+ timers.hide = setTimeout(hide, hideDelay);
965
+ };
966
+ anchor.addEventListener("pointerenter", onEnter);
967
+ anchor.addEventListener("pointerleave", onLeave);
968
+ anchor.addEventListener("focus", onEnter);
969
+ anchor.addEventListener("blur", onLeave);
970
+ return () => {
971
+ anchor.removeEventListener("pointerenter", onEnter);
972
+ anchor.removeEventListener("pointerleave", onLeave);
973
+ anchor.removeEventListener("focus", onEnter);
974
+ anchor.removeEventListener("blur", onLeave);
975
+ if (timers.show !== void 0) clearTimeout(timers.show);
976
+ if (timers.hide !== void 0) clearTimeout(timers.hide);
977
+ hide();
978
+ };
979
+ }
980
+
977
981
  export { autoReposition, choice, confirm, form, overlay, popover, positionAnchored, prompt, toast, tooltip };
978
982
 
979
983
  //# sourceMappingURL=overlay.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/overlay-position.ts","../src/overlay-core.ts","../src/overlay-choice.ts","../src/overlay-confirm.ts","../src/overlay-prompt.ts","../src/overlay-form.ts","../src/overlay-toast.ts"],"names":["options"],"mappings":"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","file":"overlay.js","sourcesContent":["/**\n * Anchored positioning primitives for `kerfjs/overlay` — position an element\n * relative to an anchor, with viewport flip + clamp. These are standalone: they\n * take any element and have no overlay lifecycle, so `popover()` / `tooltip()`\n * build on them but you can also position your own element (an inline hint, a\n * custom menu). Re-exported from `src/overlay.ts` so the public `kerfjs/overlay`\n * surface is unchanged (KF-511 split out of overlay.ts's dialog + toast code).\n */\n\n/** Vertical placement relative to an anchor (used by `popover`, {@link positionAnchored}, `tooltip`). */\nexport type PopoverPlacement = 'bottom' | 'top';\n\n/** Placement options for {@link positionAnchored} / {@link autoReposition}. */\nexport interface AnchorPositionOptions {\n /** Preferred side of the anchor; flips to the other side if it would overflow the viewport. Default `'bottom'`. */\n placement?: PopoverPlacement;\n /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */\n align?: 'start' | 'end';\n /** Gap in px between the anchor and the element. Default `4`. */\n gap?: number;\n}\n\n/**\n * One-shot: position `el` relative to `anchor` — below by default, flipping above\n * if it would overflow the viewport, aligned to a horizontal edge and clamped into\n * view. Sets `el.style` `position: fixed`, `margin: 0`, `left`, and `top` (fixed so\n * `left`/`top` are viewport coordinates, matching `getBoundingClientRect`). When an\n * ancestor makes itself the containing block for fixed descendants (a\n * `transform`, `filter`, `perspective`, or `contain` on a wrapping `<dialog>`),\n * `left`/`top` are translated (and unscaled) into that box's coordinates so `el`\n * still lands next to the anchor. This is\n * `popover()`'s placement core, usable on any element (an inline hint, a tooltip) —\n * no overlay lifecycle. Pair with {@link autoReposition} to keep it glued while open.\n */\nexport function positionAnchored(\n el: HTMLElement,\n anchor: Element,\n options: AnchorPositionOptions = {},\n): void {\n const { placement = 'bottom', align = 'start', gap = 4 } = options;\n // Fix `el` FIRST, then measure it. Measuring a still-`display:block` wrapper\n // reports the full body-content width (≈ viewport minus body margins), which\n // collapses the horizontal clamp below and lands the element at the body's left\n // edge. As a fixed, shrink-to-fit box its `width`/`height` are its real size.\n el.style.position = 'fixed';\n el.style.margin = '0';\n const anchorRect = anchor.getBoundingClientRect();\n const elementRect = el.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Vertical: preferred side, flipped only if it overflows and the other side fits.\n const belowTop = anchorRect.bottom + gap;\n const aboveTop = anchorRect.top - gap - elementRect.height;\n let below = placement !== 'top';\n if (below && belowTop + elementRect.height > viewportHeight && aboveTop >= 0)\n below = false;\n else if (\n !below &&\n aboveTop < 0 &&\n belowTop + elementRect.height <= viewportHeight\n )\n below = true;\n\n // Horizontal: align to an anchor edge, then clamp into the viewport.\n let left =\n align === 'end' ? anchorRect.right - elementRect.width : anchorRect.left;\n left = Math.max(0, Math.min(left, viewportWidth - elementRect.width));\n\n // `left`/`top` so far are viewport coordinates. They are only the CSS values\n // too when `el`'s fixed-position containing block is the viewport; an\n // ancestor with a `transform`, `filter`, `perspective`, `contain`, … (say a\n // modal `<dialog>` holding an overlay host slot) captures fixed descendants,\n // so map the coordinates into that box's space.\n const [originX, originY, scaleX, scaleY] = fixedOrigin(el);\n el.style.left = `${(left - originX) / scaleX}px`;\n el.style.top = `${((below ? belowTop : aboveTop) - originY) / scaleY}px`;\n}\n\n/**\n * Where `left: 0; top: 0` actually lands for a fixed-position child of `el`'s\n * parent, plus that containing block's scale — `[x, y, scaleX, scaleY]`, which\n * is `[0, 0, 1, 1]` when the viewport is the containing block. Measured with a\n * 1px probe rather than `el` itself so `el`'s own transform or running entrance\n * animation cannot skew it. The probe is inserted and removed synchronously, so\n * it is never painted. Translation and scale are compensated; a rotated or\n * skewed containing block is not.\n */\nfunction fixedOrigin(el: HTMLElement): [number, number, number, number] {\n const parent = el.parentNode;\n if (!parent) return [0, 0, 1, 1];\n const probe = el.ownerDocument.createElement('div');\n probe.style.cssText =\n 'position:fixed;left:0;top:0;width:1px;height:1px;margin:0;padding:0;border:0';\n parent.insertBefore(probe, el);\n const rect = probe.getBoundingClientRect();\n probe.remove();\n // A zero size (a containing block mid `scale(0)` animation, or a DOM without\n // layout) would divide by zero; treat it as unscaled.\n return [rect.left, rect.top, rect.width || 1, rect.height || 1];\n}\n\n/**\n * Keep `el` positioned against `anchor` (via {@link positionAnchored}) as the page\n * scrolls or resizes. Positions once immediately, then re-runs on `scroll`\n * (capture phase — catches scrolls in any inner container, not just `window`) and\n * `resize`. Returns a disposer that removes the listeners.\n */\nexport function autoReposition(\n el: HTMLElement,\n anchor: Element,\n options: AnchorPositionOptions = {},\n): () => void {\n const reposition = (): void => positionAnchored(el, anchor, options);\n reposition();\n window.addEventListener('scroll', reposition, true);\n window.addEventListener('resize', reposition);\n return () => {\n window.removeEventListener('scroll', reposition, true);\n window.removeEventListener('resize', reposition);\n };\n}\n","/**\n * Internal overlay / popover / tooltip lifecycle implementation.\n *\n * Every real kerf app hand-rolls this: `toElement → body.appendChild → mount →\n * wire dismissal → remove`, plus the fiddly parts (Escape, backdrop / outside\n * click, focus trap, restoring focus on close). `window.confirm` is a no-op in\n * Tauri WKWebViews, so a hand-built overlay is mandatory there. This subpath\n * blesses the pattern as three functions over `mount()` — `overlay()`, and the\n * `confirm()` / `toast()` conveniences built on it. No per-instance framework\n * state: each call owns its DOM + listeners in a closure and returns a handle.\n *\n * import { overlay, confirm, toast } from 'kerfjs/overlay';\n *\n * const ok = await confirm('Delete this file?', { danger: true });\n * toast('Saved');\n * const dialog = overlay(<Settings />, { dismiss: ['escape', 'backdrop'] });\n * // …later: dialog.close(); or await dialog.result;\n *\n * Structural only — kerf ships no CSS. The wrapper gets your `className`; style\n * the backdrop / centering / animation yourself.\n */\nimport { attach } from './attach.js';\nimport { devHooks } from './dev-hooks.js';\nimport { jsx, type SafeHtml } from './jsx-runtime.js';\nimport { mount, type MountResult } from './mount.js';\nimport {\n type AnchorPositionOptions,\n autoReposition,\n type PopoverPlacement,\n positionAnchored,\n} from './overlay-position.js';\nimport { OVERLAY_HOST_SELECTOR } from './utils/overlay-host.js';\n\n/** A user-initiated dismissal trigger. */\nexport type DismissTrigger = 'escape' | 'backdrop' | 'outside';\n\n/** Content for an overlay: static `SafeHtml`, or a render function `mount()` drives reactively. */\nexport type OverlayContent = SafeHtml | (() => MountResult);\n\n/** Options for {@link overlay}. */\nexport interface OverlayOptions {\n /** Where to append the overlay wrapper. Default `document.body`. */\n container?: Element;\n /** Class on the wrapper element (you style it — kerf ships no CSS). Default `'kerf-overlay'`. */\n className?: string;\n /**\n * Which user actions dismiss the overlay. Default `['escape', 'backdrop']`.\n * `'backdrop'` = a click on the wrapper itself (not its content); `'outside'`\n * = a click anywhere outside the wrapper (for anchored popovers). `false`\n * disables user dismissal (close it programmatically).\n */\n dismiss?: DismissTrigger | DismissTrigger[] | false;\n /**\n * Where focus lands on open: a selector, `true` (first focusable element, or\n * the wrapper if none), or `false` (leave focus alone). Default `true`.\n */\n initialFocus?: string | boolean;\n /**\n * Trap Tab / Shift+Tab within the overlay while open and mark it\n * `role=\"dialog\"` / `aria-modal=\"true\"`. Default `true`. Set `false` for a\n * non-modal popover.\n */\n trap?: boolean;\n /** ARIA role for the wrapper when `trap` is on. Default `'dialog'`. */\n role?: string;\n /** Called on any user-initiated dismissal (before `close()` runs). */\n onDismiss?: () => void;\n /** For `'outside'` dismissal: clicks on these elements do NOT count as outside (e.g. the trigger button). */\n outsideIgnore?: Element | readonly Element[];\n /**\n * Opt into the browser **top layer** (`docs/19-native-overlay-backing.md`).\n * When `true` and the engine supports it, a modal overlay (`trap: true`) is\n * hosted in a `<dialog>` opened with `.showModal()` — real inerting of the rest\n * of the document + guaranteed stacking above any `z-index` — and a non-modal\n * one (`trap: false`) uses the Popover API (`[popover]` + `showPopover()`).\n * Feature-detected; falls back to today's plain `<div>` where unsupported.\n *\n * The `render` slot + promise API are unchanged — kerf just hosts your markup\n * in a `<dialog>` / `[popover]` instead of a `<div>`. Two caveats: native\n * `<dialog>` / `[popover]` carry **UA default styles** (a `::backdrop`,\n * centering, border, padding) that kerf does not reset — style the element (and\n * its `::backdrop`) via `className`; and `container` is effectively a **no-op**\n * for visual position, since the top layer ignores where the element lives in\n * the DOM. Default `false`.\n */\n native?: boolean;\n}\n\n/** Handle returned by {@link overlay}. Holds no framework state — it's a closure. */\nexport interface OverlayHandle {\n /** The wrapper element (mounted into, appended to `container`). */\n el: HTMLElement;\n /** Tear down: dispose the mount, remove listeners + the node, restore focus, resolve `result`. Idempotent. */\n close(result?: unknown): void;\n /** Resolves with the value passed to `close()` (or `undefined` on user dismissal). */\n result: Promise<unknown>;\n}\n\nconst FOCUSABLE =\n 'a[href],area[href],button:not([disabled]),input:not([disabled]),' +\n 'select:not([disabled]),textarea:not([disabled]),iframe,' +\n '[tabindex]:not([tabindex=\"-1\"]),[contenteditable=\"true\"]';\n\nfunction focusable(root: Element): HTMLElement[] {\n const items = Array.from(\n root.querySelectorAll<HTMLElement>(FOCUSABLE),\n ).filter((el) => !el.hasAttribute('hidden') && el.tabIndex >= 0);\n // WebKit on macOS follows the system's keyboard-navigation preference and\n // may omit implicitly tabbable controls from sequential focus navigation.\n // A focus trap promises stable traversal through every eligible control, so\n // make those implicit stops explicit while preserving authored tabindexes.\n for (const el of items) if (!el.hasAttribute('tabindex')) el.tabIndex = 0;\n return items;\n}\n\n// Native top-layer feature detection (KF-526). Modal → `<dialog>.showModal()`;\n// non-modal → the Popover API. Each is independent — an engine may ship one\n// without the other — and both fall back to the plain `<div>` where absent.\nfunction supportsDialog(): boolean {\n return (\n typeof HTMLDialogElement !== 'undefined' &&\n typeof HTMLDialogElement.prototype.showModal === 'function'\n );\n}\nfunction supportsPopover(): boolean {\n return (\n typeof HTMLElement !== 'undefined' &&\n typeof HTMLElement.prototype.showPopover === 'function'\n );\n}\n\n// Stacked-surface arbitration (KF-CW7GJ8: a tooltip inside a modal used to\n// become \"topmost\" and disable the modal's Escape, backdrop, and focus trap).\n// Every open overlay — native or fallback — is recorded, in open order, on a\n// per-document stack. An input kind (Escape, a backdrop / outside click, Tab\n// for the trap) belongs to the topmost surface that HANDLES that kind; a\n// surface that doesn't handle it is transparent, except that a modal surface\n// is a barrier nothing beneath it sees past. A tooltip (or any overlay with no\n// dismiss trigger and no trap) handles nothing, so it never intercepts. The\n// `handled` set marks an event a surface already acted on, so one click that is\n// both \"outside\" a popover and on the modal backdrop closes only the popover.\nconst OVERLAY_ARBITRATION = Symbol('kerf.overlayArbitration');\n\n/** An arbitration input: a dismiss trigger, or Tab for the focus trap. */\ntype ArbitrationKind = DismissTrigger | 'trap';\n\ninterface OverlaySurface {\n el: HTMLElement;\n triggers: readonly DismissTrigger[];\n modal: boolean;\n /** Where focus returns on close; re-pointed when the surface holding it closes first. */\n restoreTo: Element | null;\n /** Non-modal only: move (or re-show) into the top layer above a newly opened modal `<dialog>`. */\n liftAbove?: () => void;\n}\n\ninterface OverlayArbitration {\n stack: OverlaySurface[];\n handled: WeakSet<Event>;\n /** Document capture listener, installed only while the stack is non-empty. */\n onToggle: (event: Event) => void;\n}\n\ntype ArbitratedDocument = Document & {\n [OVERLAY_ARBITRATION]?: OverlayArbitration;\n};\n\nfunction overlayArbitration(doc: Document): OverlayArbitration {\n const arbitrated = doc as ArbitratedDocument;\n return (arbitrated[OVERLAY_ARBITRATION] ??= {\n stack: [],\n handled: new WeakSet(),\n // KF-AHY6H4: an app-owned modal `<dialog>` opened outside kerf would leave\n // the kerf surfaces already showing inert beneath it. A dialog fires\n // `toggle` after it opens (it does not bubble, so listen in the capture\n // phase); re-host above it exactly as kerf does for its own dialogs, which\n // are skipped here because `overlay()` already re-hosted synchronously.\n onToggle: (event) => {\n const dialog = event.target as Element;\n const arbitration = arbitrated[OVERLAY_ARBITRATION] as OverlayArbitration;\n if (\n dialog.tagName === 'DIALOG' &&\n !arbitration.stack.some(({ el }) => el === dialog) &&\n isOpenModal(dialog, arbitration)\n )\n rehostAbove(arbitration, dialog);\n },\n });\n}\n\n// Every non-modal kerf surface already open is blocked beneath a modal\n// `<dialog>` that just opened: lift (or re-show) it above (KF-FJ9VD8). One\n// inside that dialog is part of its subtree already.\nfunction rehostAbove(arbitration: OverlayArbitration, dialog: Element): void {\n for (const { el, liftAbove } of arbitration.stack)\n if (el !== dialog && el.isConnected && !dialog.contains(el)) liftAbove?.();\n}\n\n// Is `dialog` an open modal `<dialog>`? kerf's own are known from the stack;\n// an app-owned one is found through `:modal`, which an older engine may not\n// parse (then only kerf's own count).\nfunction isOpenModal(\n dialog: Element,\n arbitration: OverlayArbitration,\n): boolean {\n if (!dialog.isConnected || (dialog as HTMLDialogElement).open !== true)\n return false;\n if (arbitration.stack.some(({ el, modal }) => modal && el === dialog))\n return true;\n try {\n return dialog.matches(':modal');\n } catch {\n return false; // `:modal` unsupported\n }\n}\n\n// Is a modal `<dialog>` open (KF-0V9RTE: a plain surface opened in that state\n// is inert and painted beneath the dialog's top layer)?\nfunction modalDialogOpen(\n doc: Document,\n arbitration: OverlayArbitration,\n): boolean {\n return (\n arbitration.stack.some(({ el }) => isOpenModal(el, arbitration)) ||\n Array.from(doc.querySelectorAll('dialog[open]')).some((dialog) =>\n isOpenModal(dialog, arbitration),\n )\n );\n}\n\n// The in-dialog host slot (KF-FBHQEP: a surface lifted over a modal\n// `<dialog>` is visible but inert, because every engine inerts content outside\n// the modal). A `popover()` / `tooltip()` whose anchor sits inside an open\n// modal `<dialog>` renders into that dialog's `[data-kerf-overlay-host]`\n// element instead, so it is part of the modal subtree and fully interactive.\n// An app-owned dialog opts in by marking an element; a dialog kerf opened\n// itself gets one on demand — `display: contents` so it adds no layout box,\n// and `data-morph-skip` + `data-morph-preserve` so the dialog content's own\n// `mount()` neither re-renders nor removes it (`utils/overlay-host.ts` makes\n// the slot a nested-mount boundary).\nfunction overlayHost(anchor: Element): Element | undefined {\n const arbitration = overlayArbitration(document);\n const dialog = anchor.closest('dialog');\n if (dialog === null || !isOpenModal(dialog, arbitration)) return undefined;\n let host = Array.from(dialog.querySelectorAll(OVERLAY_HOST_SELECTOR)).find(\n (el) => el.closest('dialog') === dialog,\n );\n if (host === undefined && arbitration.stack.some(({ el }) => el === dialog)) {\n dialog.insertAdjacentHTML(\n 'beforeend',\n '<div data-kerf-overlay-host data-morph-skip data-morph-preserve style=\"display:contents\"></div>',\n );\n host = dialog.lastElementChild as Element;\n }\n return host;\n}\n\n// `self` is on the stack and handles `kind` (its callers are exactly the\n// handlers it installed for that kind), so it owns `kind` unless some surface\n// above it handles `kind` too or is modal.\nfunction ownsInput(\n stack: readonly OverlaySurface[],\n self: OverlaySurface,\n kind: ArbitrationKind,\n): boolean {\n for (let i = stack.indexOf(self) + 1; i < stack.length; i++) {\n const above = stack[i];\n if (above.modal || (kind !== 'trap' && above.triggers.includes(kind)))\n return false;\n }\n return true;\n}\n\n// Validate a string `initialFocus` BEFORE any DOM mutation: `querySelector`\n// throws a generic `SyntaxError` DOMException on a malformed selector, and the\n// focus pass runs last — after the wrapper, mount, listeners, and stack entry\n// already exist — so an unvalidated selector would strand all of them with no\n// handle to close. An inert fragment parses the selector without matching.\nfunction assertInitialFocusSelector(selector: string): void {\n try {\n document.createDocumentFragment().querySelector(selector);\n } catch (cause) {\n throw new Error(\n `overlay(): invalid initialFocus selector ${JSON.stringify(selector)}`,\n { cause },\n );\n }\n}\n\n/**\n * Open an overlay: append a wrapper to `container`, `mount()` `content` inside\n * it, wire the requested dismissals + (optionally) a focus trap, and return a\n * handle. Concurrent fallback overlays dismiss from the top down. See\n * {@link OverlayOptions}.\n *\n * Construction is transactional: a malformed `initialFocus` selector throws a\n * descriptive error before anything is touched, and if a later setup phase\n * throws (the content's first render, `showModal()` / `showPopover()`), every\n * piece already installed — wrapper node, mount, listeners, fallback-stack\n * entry, top-layer state, moved focus — is rolled back before the original\n * error is rethrown.\n */\nexport function overlay(\n content: OverlayContent,\n options: OverlayOptions = {},\n): OverlayHandle {\n const {\n container = document.body,\n className = 'kerf-overlay',\n dismiss = ['escape', 'backdrop'],\n initialFocus = true,\n trap = true,\n role = 'dialog',\n onDismiss,\n outsideIgnore,\n native = false,\n } = options;\n\n if (typeof initialFocus === 'string')\n assertInitialFocusSelector(initialFocus);\n\n const triggers: readonly DismissTrigger[] =\n dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];\n\n // Native top-layer backing (KF-526), feature-detected: a modal overlay\n // (`trap`) → `<dialog>.showModal()`; a non-modal one → `[popover]`. Each falls\n // back to the plain `<div>` where the API is missing, so behavior is unchanged\n // on unsupporting engines. A surface opened while a modal `<dialog>` is open\n // is lifted the same way even without `native` (KF-0V9RTE), because a plain\n // `<div>` would be inert and painted beneath the dialog.\n const arbitration = overlayArbitration(document);\n // A surface placed inside an open modal `<dialog>` (its host slot, or an\n // explicit `container` there) is already part of the modal subtree: no lift.\n const containerDialog = container.closest('dialog');\n const liftOverModal =\n !native &&\n !(containerDialog !== null && isOpenModal(containerDialog, arbitration)) &&\n modalDialogOpen(document, arbitration);\n const topLayer = native || liftOverModal;\n const useDialog = topLayer && trap && supportsDialog();\n const usePopover = topLayer && !trap && supportsPopover();\n\n const wrapper: HTMLElement = useDialog\n ? document.createElement('dialog')\n : document.createElement('div');\n wrapper.className = className;\n if (usePopover) wrapper.setAttribute('popover', 'manual');\n // `<dialog>.showModal()` conveys modality natively (role + inert), so the ARIA\n // attributes are only needed on the plain-`<div>` fallback.\n if (trap && !useDialog) {\n wrapper.setAttribute('role', role);\n wrapper.setAttribute('aria-modal', 'true');\n }\n const surface: OverlaySurface = {\n el: wrapper,\n triggers,\n modal: trap,\n restoreTo: document.activeElement,\n };\n\n // Does this surface own `kind` right now (and has no surface acted on `event`)?\n const owns = (kind: ArbitrationKind, event?: Event): boolean =>\n !(event !== undefined && arbitration.handled.has(event)) &&\n ownsInput(arbitration.stack, surface, kind);\n\n const removers: Array<() => void> = [];\n const resultBox: { resolve?: (value: unknown) => void } = {};\n const result = new Promise<unknown>((resolve) => {\n resultBox.resolve = resolve;\n });\n const state = { closed: false };\n let disposeMount: (() => void) | undefined;\n let nativeOpened = false;\n\n // KF-FJ9VD8: a modal `<dialog>` kerf opens later would leave this non-modal\n // surface inert beneath it, so the opener calls this to move it into the top\n // layer — or, if it is already a `[popover]`, re-show it so it stacks above\n // the new dialog (the top layer orders by most recent show).\n if (!trap)\n surface.liftAbove = () => {\n if (!supportsPopover()) {\n devHooks.overlayBlockedByModal?.('hidden');\n return;\n }\n const el = wrapper as HTMLElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n if (nativeOpened) el.hidePopover();\n else {\n wrapper.setAttribute('popover', 'manual');\n wrapper.style.inset = 'auto';\n }\n el.showPopover();\n nativeOpened = true;\n if (wrapper.querySelector(FOCUSABLE) !== null)\n devHooks.overlayBlockedByModal?.('inert');\n };\n\n // Also the construction rollback (see the transaction below): every step\n // tolerates a phase that never ran — no mount yet, no stack entry, never\n // appended, never shown.\n function close(value?: unknown): void {\n if (state.closed) return;\n state.closed = true;\n const { stack } = arbitration;\n const stackIndex = stack.indexOf(surface);\n if (stackIndex !== -1) stack.splice(stackIndex, 1);\n if (stack.length === 0)\n document.removeEventListener('toggle', arbitration.onToggle, true);\n // A surface opened from inside this one would restore focus into a node\n // that is about to be detached: hand it this surface's own restore target.\n for (const other of stack)\n if (other.restoreTo !== null && wrapper.contains(other.restoreTo))\n other.restoreTo = surface.restoreTo;\n const active = document.activeElement;\n for (const remove of removers) remove();\n disposeMount?.();\n // Exit the top layer before removing the node, so the native close steps run\n // (restore inert, fire the dialog's `close`). `<dialog>` also restores focus\n // itself; kerf's manual restore below stays as the fallback path's behavior.\n if (nativeOpened) {\n nativeOpened = false;\n if (useDialog) (wrapper as HTMLDialogElement).close();\n else (wrapper as HTMLElement & { hidePopover(): void }).hidePopover();\n }\n wrapper.remove();\n restoreFocus(active);\n resultBox.resolve?.(value);\n }\n\n // Closing a surface that doesn't hold focus (an out-of-order close beneath\n // another open surface) must not pull focus out of the surface that does;\n // otherwise focus returns to where it was when this surface opened.\n function restoreFocus(active: Element | null): void {\n if (\n active instanceof HTMLElement &&\n active.isConnected &&\n arbitration.stack.some((other) => other.el.contains(active))\n ) {\n if (document.activeElement !== active) active.focus();\n return;\n }\n const { restoreTo } = surface;\n if (restoreTo instanceof HTMLElement && restoreTo.isConnected)\n restoreTo.focus();\n }\n\n function userDismiss(): void {\n onDismiss?.();\n close();\n }\n\n // One transaction: if any phase below throws (the content's first render,\n // `showModal()` / `showPopover()`, …), roll back whatever the earlier phases\n // installed via `close()` and rethrow the original error. No handle is\n // returned on failure, so nothing may outlive the call.\n try {\n container.appendChild(wrapper);\n disposeMount = mount(\n wrapper,\n typeof content === 'function' ? content : () => content,\n );\n // Watch for app-owned modal dialogs while any kerf surface is open.\n if (arbitration.stack.push(surface) === 1)\n document.addEventListener('toggle', arbitration.onToggle, true);\n\n // Enter the top layer after the content is mounted + connected.\n // `showModal()` moves focus into the dialog by default; kerf's\n // `initialFocus` pass below runs afterward and wins.\n if (useDialog) {\n (wrapper as HTMLDialogElement).showModal();\n nativeOpened = true;\n rehostAbove(arbitration, wrapper);\n } else if (usePopover) {\n (wrapper as HTMLElement & { showPopover(): void }).showPopover();\n nativeOpened = true;\n // Neutralize the UA `[popover] { inset: 0; margin: auto }` anchoring so\n // `positionAnchored` (which sets `top`/`left`) controls placement —\n // otherwise the retained `right`/`bottom` insets would stretch/center it.\n wrapper.style.inset = 'auto';\n }\n\n installDismissal();\n if (container.closest(OVERLAY_HOST_SELECTOR) !== null) {\n makeTabReachable();\n // KF-WZ9KQM: a slot-hosted surface leaves with its dialog even when its\n // anchor (moved out of the dialog) stays connected, so the anchor watch\n // never fires. Watch the wrapper itself: close as cleanup (no\n // `onDismiss`) and leave the open-order stack.\n removers.push(attach(wrapper, () => close));\n }\n applyInitialFocus();\n } catch (error) {\n close();\n throw error;\n }\n\n // What the lift cannot repair: no top-layer API at all, or a lifted\n // non-modal surface whose controls the modal still inerts.\n if (liftOverModal) {\n if (!useDialog && !usePopover) devHooks.overlayBlockedByModal?.('hidden');\n else if (usePopover && wrapper.querySelector(FOCUSABLE) !== null)\n devHooks.overlayBlockedByModal?.('inert');\n }\n\n return { el: wrapper, close, result };\n\n function installDismissal(): void {\n const wantEscape = triggers.includes('escape');\n if (useDialog) {\n // A native modal `<dialog>` confines Tab focus itself and surfaces Escape as\n // a `cancel` event. Take that over: `preventDefault` so kerf owns teardown\n // (and so Escape is swallowed when it isn't a dismiss trigger), then dismiss.\n // A surface stacked above that handles Escape (or is modal) owns it; a\n // stray `cancel` then leaves this dialog open.\n const onCancel = (event: Event): void => {\n event.preventDefault();\n if (wantEscape && owns('escape')) userDismiss();\n };\n wrapper.addEventListener('cancel', onCancel);\n removers.push(() => wrapper.removeEventListener('cancel', onCancel));\n } else if (wantEscape || trap) {\n const onKeydown = (event: KeyboardEvent): void => {\n if (wantEscape && event.key === 'Escape') {\n if (!owns('escape', event)) return;\n // `preventDefault` also withholds the close request from a native\n // `<dialog>` beneath, so one Escape closes exactly one surface.\n event.stopPropagation();\n event.preventDefault();\n arbitration.handled.add(event);\n userDismiss();\n return;\n }\n if (trap && event.key === 'Tab' && owns('trap')) {\n const items = focusable(wrapper);\n if (items.length === 0) {\n event.preventDefault();\n return;\n }\n const first = items[0];\n const last = items[items.length - 1];\n const active = document.activeElement;\n const outside = !wrapper.contains(active);\n if (event.shiftKey && (active === first || outside)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (active === last || outside)) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n document.addEventListener('keydown', onKeydown, true);\n removers.push(() =>\n document.removeEventListener('keydown', onKeydown, true),\n );\n }\n\n if (triggers.includes('backdrop')) {\n const onClick = (event: Event): void => {\n if (event.target !== wrapper || !owns('backdrop', event)) return;\n arbitration.handled.add(event);\n userDismiss();\n };\n wrapper.addEventListener('click', onClick);\n removers.push(() => wrapper.removeEventListener('click', onClick));\n }\n\n if (triggers.includes('outside')) {\n const ignore =\n outsideIgnore === undefined\n ? []\n : Array.isArray(outsideIgnore)\n ? outsideIgnore\n : [outsideIgnore];\n // Capture phase: the click that opened this overlay already passed\n // document's capture phase, so this never fires for that opening click.\n const onDocClick = (event: Event): void => {\n const target = event.target as Node | null;\n if (target === null) return;\n if (wrapper.contains(target)) return;\n if (ignore.some((el) => el === target || el.contains(target))) return;\n if (!owns('outside', event)) return;\n arbitration.handled.add(event);\n userDismiss();\n };\n document.addEventListener('click', onDocClick, true);\n removers.push(() =>\n document.removeEventListener('click', onDocClick, true),\n );\n }\n }\n\n // KF-QZ9SFG (slot-hosted controls unreachable by Tab in macOS WebKit): a\n // surface in an overlay host slot sits in the modal dialog's own Tab order,\n // not behind a kerf trap, so WebKit's system keyboard-navigation preference\n // would skip its implicitly tabbable controls. Make those stops explicit, as\n // the trap does — now, and again before each Tab so a control a re-render\n // added (or whose tabindex the morph dropped) is reachable too.\n function makeTabReachable(): void {\n focusable(wrapper);\n const onTab = (event: KeyboardEvent): void => {\n if (event.key === 'Tab') focusable(wrapper);\n };\n document.addEventListener('keydown', onTab, true);\n removers.push(() => document.removeEventListener('keydown', onTab, true));\n }\n\n function applyInitialFocus(): void {\n if (initialFocus !== false) {\n if (typeof initialFocus === 'string') {\n wrapper.querySelector<HTMLElement>(initialFocus)?.focus();\n } else {\n const first = focusable(wrapper)[0];\n if (first !== undefined) {\n first.focus();\n } else {\n wrapper.tabIndex = -1;\n wrapper.focus();\n }\n }\n }\n }\n}\n\n/**\n * Internal: run a promise-dialog helper's post-open wiring (required-slot\n * lookups, `delegate()` handlers, key listeners) as the tail of `overlay()`'s\n * construction transaction. `wire` registers a disposer for every listener it\n * installs via `track`; if any step throws, those listeners are removed, the\n * just-opened overlay is closed (node, mount, dismissal listeners, stack\n * entry, top-layer state, focus), and the original error is rethrown — so a\n * failed helper call returns no promise and leaves no open overlay behind.\n *\n * After construction, `guard` wraps a user-action handler (OK click, Enter).\n * KF-B0CFQP (a throwing `validate` callback): a throw inside a guarded action\n * is a programming error, so it closes the dialog (full teardown, focus\n * restored) and the returned promise REJECTS with the original error, instead\n * of the error escaping the event handler and stranding an open dialog whose\n * OK can never succeed. Otherwise the returned promise settles with\n * `settle(handle.result's value)`. Not re-exported from `kerfjs/overlay`.\n */\nexport function wireDialog<T>(\n handle: OverlayHandle,\n wire: (\n track: (dispose: () => void) => void,\n guard: (action: () => void) => () => void,\n ) => void,\n settle: (value: unknown) => T,\n): Promise<T> {\n const disposers: Array<() => void> = [];\n // Holds a guarded action's error AND is the close() value that marks the\n // failure, so only a throw that actually settles the dialog rejects it.\n const failure: unknown[] = [];\n try {\n wire(\n (dispose) => void disposers.push(dispose),\n (action) => () => {\n try {\n action();\n } catch (error) {\n failure[0] = error;\n handle.close(failure);\n }\n },\n );\n } catch (error) {\n disposers.forEach((dispose) => dispose());\n handle.close();\n throw error;\n }\n // One hop, not a chain: `settle` maps the value in the same reaction, so a\n // helper's promise settles as soon after `close()` as it always has.\n return handle.result.then((value) => {\n if (value === failure) throw failure[0];\n return settle(value);\n });\n}\n\n// The anchored-positioning primitives — `positionAnchored` / `autoReposition`\n// plus their option types — live in `./overlay-position.ts` (KF-511) since they\n// stand alone (any element, no overlay lifecycle). Re-exported here so the\n// `kerfjs/overlay` surface is unchanged; `popover()` / `tooltip()` below build on\n// `autoReposition` (imported above).\nexport {\n type AnchorPositionOptions,\n autoReposition,\n type PopoverPlacement,\n positionAnchored,\n};\n\n/** Options for {@link popover}. */\nexport interface PopoverOptions {\n /**\n * Where to append the popover wrapper. Default: when `anchor` sits inside an\n * open modal `<dialog>`, that dialog's `[data-kerf-overlay-host]` element (a\n * dialog kerf opened gets one automatically), so the popover is part of the\n * modal subtree and stays interactive; otherwise `document.body`.\n */\n container?: Element;\n /** Class on the wrapper. Default `'kerf-popover'`. */\n className?: string;\n /** Preferred side of the anchor. Flips to the other side if it would overflow the viewport. Default `'bottom'`. */\n placement?: PopoverPlacement;\n /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */\n align?: 'start' | 'end';\n /** Gap in px between the anchor and the popover. Default `4`. */\n gap?: number;\n /**\n * Which user actions dismiss the popover. Default `['outside']` (a click\n * outside the popover, the anchor exempt). Pass `false` to close only via `close()`.\n */\n dismiss?: DismissTrigger | DismissTrigger[] | false;\n /** Focus behavior on open. Default `false` (non-modal — leave focus alone). */\n initialFocus?: string | boolean;\n /** Extra elements (besides the anchor) whose clicks do NOT count as outside. */\n outsideIgnore?: Element | readonly Element[];\n /** Called on any user-initiated dismissal. */\n onDismiss?: () => void;\n /**\n * Host the popover in the browser top layer (the Popover API — `[popover]` +\n * `showPopover()`) where supported, so it stacks above any `z-index` without a\n * z-index war. Falls back to today's plain `<div>` where unsupported. kerf keeps\n * owning positioning + its own dismiss wiring; the popover is `popover=\"manual\"`.\n * See {@link OverlayOptions.native}. Default `false`.\n */\n native?: boolean;\n}\n\n/**\n * Anchored, non-modal overlay: positions `content` relative to `anchor` (below by\n * default, flipping above if it would overflow, and clamped horizontally to the\n * viewport) and repositions on scroll / resize while open. A thin wrapper over\n * {@link overlay} with non-modal defaults — `trap: false`, `dismiss: ['outside']`,\n * and the anchor added to `outsideIgnore` so the trigger click doesn't self-close.\n * Returns the same {@link OverlayHandle}; `close()` also drops the reposition\n * listeners. `position: fixed` is set inline (you style everything else).\n */\nexport function popover(\n anchor: Element,\n content: OverlayContent,\n options: PopoverOptions = {},\n): OverlayHandle {\n const {\n container,\n className = 'kerf-popover',\n placement = 'bottom',\n align = 'start',\n gap = 4,\n dismiss = ['outside'],\n initialFocus = false,\n outsideIgnore,\n onDismiss,\n native = false,\n } = options;\n\n const extraIgnore =\n outsideIgnore === undefined\n ? []\n : Array.isArray(outsideIgnore)\n ? [...outsideIgnore]\n : [outsideIgnore];\n\n const handle = overlay(content, {\n container: container ?? overlayHost(anchor),\n className,\n dismiss,\n trap: false,\n initialFocus,\n onDismiss,\n outsideIgnore: [anchor, ...extraIgnore],\n native,\n });\n\n // Position + keep it glued while open; drop the listeners on close. A throw\n // while positioning (e.g. an anchor whose geometry read fails) is still part\n // of construction: close the just-opened overlay before rethrowing.\n let stopReposition: () => void;\n try {\n stopReposition = autoReposition(handle.el, anchor, {\n placement,\n align,\n gap,\n });\n } catch (error) {\n handle.close();\n throw error;\n }\n void handle.result.then(stopReposition);\n\n // KF-BAVCEV: never outlive the anchor. When it leaves the document (e.g. the\n // modal holding it closes) close the popover as cleanup — not a user\n // dismissal, so no `onDismiss`. A move within the document keeps it open.\n void handle.result.then(attach(anchor, () => handle.close));\n\n return handle;\n}\n\n/** Content for a {@link tooltip}: text (auto-escaped), `SafeHtml`, or a render function. */\nexport type TooltipContent = string | SafeHtml | (() => MountResult);\n\n/** Options for {@link tooltip}. */\nexport interface TooltipOptions extends AnchorPositionOptions {\n /** Where to append the tooltip wrapper. Default: the anchor's modal-dialog host slot (see {@link PopoverOptions.container}), else `document.body`. */\n container?: Element;\n /** Class on the wrapper. Default `'kerf-tooltip'`. */\n className?: string;\n /** Delay in ms before showing after hover/focus enters. Default `400`. */\n delay?: number;\n /** Delay in ms before hiding after hover/focus leaves. Default `100`. */\n hideDelay?: number;\n /** ARIA role on the wrapper. Default `'tooltip'`. */\n role?: string;\n /** Host the tooltip in the browser top layer (the Popover API) where supported. See {@link OverlayOptions.native}. Default `false`. */\n native?: boolean;\n}\n\n/**\n * A hover/focus-triggered, non-modal, auto-hiding tooltip anchored to `anchor`.\n * Shows after `delay` on `pointerenter`/`focus`, hides after `hideDelay` on\n * `pointerleave`/`blur`, and positions itself with {@link autoReposition} (above\n * the anchor by default). Unlike {@link popover} there is no click-dismiss model —\n * it follows the pointer/focus. Returns a disposer that removes the anchor\n * listeners and hides any shown tooltip. Structural only (kerf ships no CSS).\n */\nexport function tooltip(\n anchor: Element,\n content: TooltipContent,\n options: TooltipOptions = {},\n): () => void {\n const {\n container,\n className = 'kerf-tooltip',\n delay = 400,\n hideDelay = 100,\n role = 'tooltip',\n placement = 'top',\n align = 'start',\n gap = 4,\n native = false,\n } = options;\n\n const body: OverlayContent =\n typeof content === 'function'\n ? content\n : typeof content === 'string'\n ? jsx('span', { class: `${className}__text`, children: content })\n : content;\n\n const timers: {\n show?: ReturnType<typeof setTimeout>;\n hide?: ReturnType<typeof setTimeout>;\n } = {};\n let current:\n | { handle: OverlayHandle; stop: () => void; unwatch: () => void }\n | undefined;\n let presence = 0;\n\n // Runs from the `delay` timer, so there is no caller to throw to. A failed\n // show (a throwing render fn, `native` `showPopover()`, or positioning) is\n // rolled back before `current` is set — nothing stays on screen and the\n // next pointerenter / focus schedules a fresh attempt — and the original\n // error then escapes the timer callback for the host to report as uncaught\n // (a window `error` event in browsers), the same way kerf's other deferred\n // callbacks (debounce / throttle timers, attach teardown) surface errors.\n function show(): void {\n // The anchor left the document while the show was pending (KF-BAVCEV).\n if (!anchor.isConnected) return;\n const handle = overlay(body, {\n container: container ?? overlayHost(anchor),\n className,\n dismiss: false,\n trap: false,\n initialFocus: false,\n native,\n });\n handle.el.setAttribute('role', role);\n let stop: () => void;\n try {\n stop = autoReposition(handle.el, anchor, { placement, align, gap });\n } catch (error) {\n // Not yet tracked in `current`, so `hide()` could never reach it.\n handle.close();\n throw error;\n }\n // KF-BAVCEV: an anchor removed from the document (e.g. with the modal that\n // held it) fires no pointerleave / blur, so hide when it leaves and forget\n // its presence; a move within the document keeps the tooltip shown.\n const unwatch = attach(anchor, () => () => {\n presence = 0;\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n hide();\n });\n current = { handle, stop, unwatch };\n // A surface that closed itself (its host slot left the document with the\n // dialog) must not stay `current`, or the next hover would never show.\n void handle.result.then(() => {\n if (current?.handle === handle) hide();\n });\n }\n\n function hide(): void {\n const shown = current;\n if (shown === undefined) return;\n // Cleared first: `unwatch()` runs the anchor teardown, which re-enters here.\n current = undefined;\n shown.unwatch();\n shown.stop();\n shown.handle.close();\n }\n\n const onEnter = (event: Event): void => {\n presence |= event.type === 'focus' ? 2 : 1;\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n if (current !== undefined) return;\n if (timers.show !== undefined) clearTimeout(timers.show); // debounce: one pending show at a time\n timers.show = setTimeout(show, delay);\n };\n const onLeave = (event: Event): void => {\n presence &= event.type === 'blur' ? ~2 : ~1;\n if (presence) return;\n if (timers.show !== undefined) clearTimeout(timers.show);\n if (current === undefined) return;\n timers.hide = setTimeout(hide, hideDelay);\n };\n\n anchor.addEventListener('pointerenter', onEnter);\n anchor.addEventListener('pointerleave', onLeave);\n anchor.addEventListener('focus', onEnter);\n anchor.addEventListener('blur', onLeave);\n\n return () => {\n anchor.removeEventListener('pointerenter', onEnter);\n anchor.removeEventListener('pointerleave', onLeave);\n anchor.removeEventListener('focus', onEnter);\n anchor.removeEventListener('blur', onLeave);\n if (timers.show !== undefined) clearTimeout(timers.show);\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n hide();\n };\n}\n","/** `choice()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/** One choosable action in a {@link choice} dialog. */\nexport interface ChoiceAction<R> {\n value: R;\n label: string;\n className?: string;\n}\n\n/** Wiring slots for a {@link ChoiceOptions.render}. */\nexport interface ChoiceRenderSlots {\n message: string;\n actions: Array<Record<string, string>>;\n}\n\n/** Options for {@link choice}. */\nexport interface ChoiceOptions<R> {\n container?: Element;\n className?: string;\n title?: string;\n defaultValue?: R;\n native?: boolean;\n render?: (slots: ChoiceRenderSlots) => OverlayContent;\n}\n\n/** The N-way sibling of {@link confirm}. */\nexport function choice<R>(\n message: string,\n actions: ReadonlyArray<ChoiceAction<R>>,\n options: ChoiceOptions<R> = {},\n): Promise<R | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n defaultValue,\n native = false,\n render,\n } = options;\n const hasDefault = 'defaultValue' in options;\n const actionAttrs = actions.map((_, i) => ({ 'data-choice': String(i) }));\n\n const body: OverlayContent =\n render !== undefined\n ? render({ message, actions: actionAttrs })\n : jsx('div', {\n class: 'kerf-choice',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-choice__title', children: title })\n : '',\n jsx('p', { class: 'kerf-choice__message', children: message }),\n jsx('div', {\n class: 'kerf-choice__actions',\n children: actions.map((action, i) =>\n jsx('button', {\n type: 'button',\n class:\n action.className !== undefined\n ? `kerf-choice__action ${action.className}`\n : 'kerf-choice__action',\n ...actionAttrs[i],\n children: action.label,\n }),\n ),\n }),\n ],\n });\n\n let resolveChoice!: (result: R | null) => void;\n const result = new Promise<R | null>((resolve) => {\n resolveChoice = resolve;\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-choice]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a throw closes the overlay. Any\n // close settles a still-pending choice as a dismissal (`null`).\n void wireDialog(\n handle,\n (track) => {\n track(\n delegate(handle.el, 'click', '[data-choice]', (_event, el) => {\n resolveChoice(actions[Number(el.getAttribute('data-choice'))].value);\n handle.close();\n }),\n );\n\n if (hasDefault) {\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === 'Enter') {\n event.preventDefault();\n resolveChoice(defaultValue as R);\n handle.close();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n }\n },\n () => resolveChoice(null),\n );\n return result;\n}\n","/** `confirm()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/** Wiring slots passed to a {@link ConfirmOptions.render}. */\nexport interface ConfirmRenderSlots {\n message: string;\n /** Spread onto the confirm control. */\n ok: Record<string, string>;\n /** Spread onto the cancel control. */\n cancel: Record<string, string>;\n}\n\n/** Options for {@link confirm}. */\nexport interface ConfirmOptions {\n /** Where to append the overlay. Default `document.body`. */\n container?: Element;\n /** Wrapper class. Default `'kerf-overlay'`. */\n className?: string;\n /** Optional heading above the message. */\n title?: string;\n /** Confirm button label. Default `'OK'`. */\n okText?: string;\n /** Cancel button label. Default `'Cancel'`. */\n cancelText?: string;\n /** Add a `kerf-confirm--danger` class to the wrapper for destructive actions. */\n danger?: boolean;\n /** Host the dialog in the browser top layer where supported. */\n native?: boolean;\n /** Bring your own body while retaining kerf's dialog wiring. */\n render?: (slots: ConfirmRenderSlots) => OverlayContent;\n}\n\n/** A promise-based `window.confirm` replacement. */\nexport function confirm(\n message: string,\n options: ConfirmOptions = {},\n): Promise<boolean> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n okText = 'OK',\n cancelText = 'Cancel',\n danger = false,\n native = false,\n render,\n } = options;\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n message,\n ok: { 'data-confirm': 'ok' },\n cancel: { 'data-confirm': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-confirm',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-confirm__title', children: title })\n : '',\n jsx('p', { class: 'kerf-confirm__message', children: message }),\n jsx('div', {\n class: 'kerf-confirm__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-confirm': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-confirm': 'ok',\n class: 'kerf-confirm__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className: danger ? `${className} kerf-confirm--danger` : className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-confirm=\"ok\"]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a throw closes the overlay. The\n // click table is the only (and so the last) step, so it needs no rollback.\n return wireDialog(\n handle,\n () => {\n delegate(handle.el, 'click', '[data-confirm]', (_event, el) => {\n handle.close(el.getAttribute('data-confirm') === 'ok');\n });\n },\n (value) => value === true,\n );\n}\n","/** `prompt()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/**\n * Validate a single field's value, synchronously: return a non-empty message\n * to block OK, anything else to accept. A validator that throws is treated as\n * a programming error — the dialog closes and the returned promise rejects\n * with that error.\n */\nexport type FieldValidator = (\n value: string,\n) => string | null | undefined | void;\n\n/** Options for {@link prompt}. */\n/**\n * Run a {@link FieldValidator}: the message it reports, or `undefined` when the\n * value is valid. Validators are synchronous — a promise result is a\n * programming error that closes the dialog and rejects its promise (the stray\n * promise's own rejection is silenced so it is not reported twice).\n * Internal to the dialog helpers.\n */\nexport function runValidator(\n validate: FieldValidator | undefined,\n value: string,\n owner: string,\n): string | undefined {\n const result: unknown = validate?.(value);\n if (typeof (result as PromiseLike<unknown> | null)?.then === 'function') {\n (result as PromiseLike<unknown>).then(undefined, () => undefined);\n throw new TypeError(`${owner}: validate returned a promise.`);\n }\n return typeof result === 'string' && result.length > 0 ? result : undefined;\n}\n\nexport interface PromptOptions {\n container?: Element;\n className?: string;\n title?: string;\n defaultValue?: string;\n placeholder?: string;\n inputType?: string;\n okText?: string;\n cancelText?: string;\n validate?: FieldValidator;\n native?: boolean;\n render?: (slots: PromptRenderSlots) => OverlayContent;\n}\n\n/** Wiring slots for a {@link PromptOptions.render}. */\nexport interface PromptRenderSlots {\n message: string;\n input: Record<string, string>;\n error: Record<string, string>;\n ok: Record<string, string>;\n cancel: Record<string, string>;\n}\n\n/** A promise-based `window.prompt` replacement. */\nexport function prompt(\n message: string,\n options: PromptOptions = {},\n): Promise<string | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n defaultValue = '',\n placeholder,\n inputType = 'text',\n okText = 'OK',\n cancelText = 'Cancel',\n validate,\n native = false,\n render,\n } = options;\n\n const inputAttrs: Record<string, string> = {\n 'data-prompt-input': '',\n type: inputType,\n value: defaultValue,\n ...(placeholder !== undefined ? { placeholder } : {}),\n };\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n message,\n input: inputAttrs,\n error: { 'data-prompt-error': '' },\n ok: { 'data-prompt': 'ok' },\n cancel: { 'data-prompt': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-prompt',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-prompt__title', children: title })\n : '',\n jsx('label', { class: 'kerf-prompt__message', children: message }),\n jsx('input', { class: 'kerf-prompt__input', ...inputAttrs }),\n jsx('p', {\n class: 'kerf-prompt__error',\n 'data-prompt-error': '',\n children: '',\n }),\n jsx('div', {\n class: 'kerf-prompt__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-prompt': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-prompt': 'ok',\n class: 'kerf-prompt__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-prompt-input]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a missing required input or any\n // other throw below removes what was wired, closes the overlay, and rethrows.\n return wireDialog(\n handle,\n (track, guard) => {\n // Looked up again at OK: a reactive re-render may have replaced the\n // input, and a detached node would report a stale value. Missing at\n // construction is a render bug (rolls back, throws); missing at OK\n // rejects the promise through `guard`.\n const inputFor = (problem = 'render missing'): HTMLInputElement => {\n const input = handle.el.querySelector<HTMLInputElement>(\n 'input[data-prompt-input]',\n );\n if (input !== null) return input;\n throw new Error(`prompt(): ${problem} <input data-prompt-input>.`);\n };\n inputFor();\n const errorEl = handle.el.querySelector<HTMLElement>(\n '[data-prompt-error]',\n );\n if (errorEl !== null) errorEl.hidden = true;\n\n // A throwing (or promise-returning) `validate` closes the dialog and\n // rejects the promise (guard).\n const attemptOk = guard((): void => {\n const input = inputFor('removed after open:');\n const value = input.value;\n const error = runValidator(validate, value, 'prompt()');\n if (error !== undefined) {\n if (errorEl !== null) {\n errorEl.textContent = error;\n errorEl.hidden = false;\n }\n input.focus();\n return;\n }\n handle.close(value);\n });\n\n track(\n delegate(handle.el, 'click', '[data-prompt]', (_event, el) => {\n if (el.getAttribute('data-prompt') === 'ok') attemptOk();\n else handle.close(null);\n }),\n );\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (\n event.key === 'Enter' &&\n (event.target as Element | null)?.matches('input[data-prompt-input]')\n ) {\n event.preventDefault();\n attemptOk();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n },\n (value) => (typeof value === 'string' ? value : null),\n );\n}\n","/** `form()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\nimport { type FieldValidator, runValidator } from './overlay-prompt.js';\n\n/** A single field in a {@link form}. */\nexport interface FormField {\n name: string;\n label?: string;\n defaultValue?: string;\n placeholder?: string;\n type?: string;\n validate?: FieldValidator;\n}\n\n/** One field's wiring in a {@link FormRenderSlots}. */\nexport interface FormRenderField {\n name: string;\n label: string;\n input: Record<string, string>;\n error: Record<string, string>;\n}\n\n/** Wiring slots for a {@link FormOptions.render}. */\nexport interface FormRenderSlots {\n fields: FormRenderField[];\n ok: Record<string, string>;\n cancel: Record<string, string>;\n}\n\n/** Options for {@link form}. */\nexport interface FormOptions {\n container?: Element;\n className?: string;\n title?: string;\n okText?: string;\n cancelText?: string;\n native?: boolean;\n render?: (slots: FormRenderSlots) => OverlayContent;\n}\n\n/** A promise-based multi-field dialog. */\nexport function form(\n fields: readonly FormField[],\n options: FormOptions = {},\n): Promise<Record<string, string> | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n okText = 'OK',\n cancelText = 'Cancel',\n native = false,\n render,\n } = options;\n\n const fieldAttrs = (field: FormField): Record<string, string> => ({\n 'data-field': field.name,\n name: field.name,\n type: field.type ?? 'text',\n value: field.defaultValue ?? '',\n ...(field.placeholder !== undefined\n ? { placeholder: field.placeholder }\n : {}),\n });\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n fields: fields.map((field) => ({\n name: field.name,\n label: field.label ?? field.name,\n input: fieldAttrs(field),\n error: { 'data-field-error': field.name },\n })),\n ok: { 'data-form': 'ok' },\n cancel: { 'data-form': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-form',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-form__title', children: title })\n : '',\n ...fields.map((field) =>\n jsx('div', {\n class: 'kerf-form__field',\n children: [\n jsx('label', {\n class: 'kerf-form__label',\n children: field.label ?? field.name,\n }),\n jsx('input', {\n class: 'kerf-form__input',\n ...fieldAttrs(field),\n }),\n jsx('p', {\n class: 'kerf-form__error',\n 'data-field-error': field.name,\n children: '',\n }),\n ],\n }),\n ),\n jsx('div', {\n class: 'kerf-form__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-form': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-form': 'ok',\n class: 'kerf-form__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-field]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a missing required field input or\n // any other throw below removes what was wired, closes the overlay, and\n // rethrows.\n return wireDialog(\n handle,\n (track, guard) => {\n const errorFor = (name: string): HTMLElement | null =>\n Array.from(\n handle.el.querySelectorAll<HTMLElement>('[data-field-error]'),\n ).find((el) => el.getAttribute('data-field-error') === name) ?? null;\n // KF-HRNJ4T (a field input removed after open by a reactive re-render):\n // at construction a missing input is a render bug that rolls back and\n // throws synchronously; at OK time it throws inside `guard`, so the\n // dialog closes and the promise rejects naming the field — never a\n // `null` that reads as a user Cancel.\n const inputFor = (\n name: string,\n problem = 'render missing',\n ): HTMLInputElement => {\n const input = Array.from(\n handle.el.querySelectorAll<HTMLInputElement>('input[data-field]'),\n ).find((el) => el.getAttribute('data-field') === name);\n if (input !== undefined) return input;\n throw new Error(`form(): ${problem} <input data-field=\"${name}\">.`);\n };\n\n for (const field of fields) {\n inputFor(field.name);\n const errorEl = errorFor(field.name);\n if (errorEl !== null) errorEl.hidden = true;\n }\n\n // A throwing `field.validate` closes the dialog and rejects the promise.\n const attemptOk = guard((): void => {\n const record: Record<string, string> = {};\n let firstInvalid: HTMLInputElement | null = null;\n for (const field of fields) {\n const el = inputFor(field.name, 'removed after open:');\n const value = el.value;\n record[field.name] = value;\n const error = runValidator(field.validate, value, 'form()');\n const errorEl = errorFor(field.name);\n if (error !== undefined) {\n if (errorEl !== null) {\n errorEl.textContent = error;\n errorEl.hidden = false;\n }\n if (firstInvalid === null) firstInvalid = el;\n } else if (errorEl !== null) {\n errorEl.hidden = true;\n }\n }\n if (firstInvalid !== null) {\n firstInvalid.focus();\n return;\n }\n handle.close(record);\n });\n\n track(\n delegate(handle.el, 'click', '[data-form]', (_event, el) => {\n if (el.getAttribute('data-form') === 'ok') attemptOk();\n else handle.close(null);\n }),\n );\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (\n event.key === 'Enter' &&\n (event.target as Element | null)?.matches('[data-field]')\n ) {\n event.preventDefault();\n attemptOk();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n },\n (value) =>\n value !== null && typeof value === 'object'\n ? (value as Record<string, string>)\n : null,\n );\n}\n","/**\n * `toast()` for `kerfjs/overlay` — a non-modal, auto-dismissing notification that\n * stacks in a shared body-level region. Split out of `overlay.ts` (KF-513) since\n * it's a distinct transient-UI concern from the modal dialogs; re-exported from\n * `overlay.ts` so the public `kerfjs/overlay` surface is unchanged. Structural\n * only — kerf ships no CSS; you style the region / toast / animations.\n */\nimport { type SafeHtml } from './jsx-runtime.js';\nimport { mount, type MountResult } from './mount.js';\nimport { escapeHtml } from './utils/escapeHtml.js';\n\n/** Content for a {@link toast}: an escaped text string, trusted `SafeHtml`, or a render function. */\nexport type ToastContent = string | SafeHtml | (() => MountResult);\n\n/** Accent variant for a {@link toast} — mapped to a `${className}--${variant}` class. */\nexport type ToastVariant = 'info' | 'success' | 'warning';\n\n/** Options for {@link toast}. */\nexport interface ToastOptions {\n /** Where toasts stack. Default: a lazily-created `<div class=\"kerf-toasts\">` on `document.body`. */\n container?: Element;\n /** Class on the toast element. Default `'kerf-toast'`. */\n className?: string;\n /** Auto-dismiss after this many ms. `0` keeps it until dismissed by hand. Default `4000`. */\n duration?: number;\n /** ARIA role. Default `'status'`. */\n role?: string;\n /**\n * `'stack'` (default) shows toasts stacked in the region; `'replace'` dismisses\n * the region's current toast(s) first (collapse-to-latest for a rapid sequence).\n */\n mode?: 'stack' | 'replace';\n /**\n * How `mode: 'replace'` drops the prior toast(s): `'fade'` (default) runs their\n * full exit transition (nice for a STACKING region), or `'instant'` removes them\n * synchronously with no exit — what a single, exactly-centered toast slot wants,\n * so the outgoing and incoming messages never cross-fade in the same spot.\n */\n collapse?: 'fade' | 'instant';\n /** Accent variant — adds a `${className}--${variant}` class (kerf ships no CSS; you style it). */\n variant?: ToastVariant;\n /** Class added on the next animation frame after mount, so a CSS **entrance** transition can run. */\n enterClass?: string;\n /**\n * Class added when dismissing, so CSS owns the **exit**. On dismiss the\n * `enterClass` (if any) is also REMOVED, so `exitClass` doesn't have to\n * out-specify it — and a symmetric single-class fade (entrance = add\n * `enterClass`, exit = remove it) works by setting only `enterClass` +\n * `exitDuration`. The node is removed `exitDuration` ms later.\n */\n exitClass?: string;\n /** ms to wait before removing the node on dismiss — applies when `exitClass` is set OR when it's > 0 (to let a removed `enterClass` transition out). Default `0`. */\n exitDuration?: number;\n}\n\n/** Handle returned by {@link toast}. */\nexport interface ToastHandle {\n /** The toast element — inspect it, or run your own entrance/exit transitions. */\n el: HTMLElement;\n /**\n * Dismiss it early. Default runs the `exitClass` transition (removed after\n * `exitDuration`); pass `{ instant: true }` to remove it **synchronously** with\n * no exit — for an action button that immediately shows a replacement toast in a\n * single centered slot (no cross-fade). Idempotent.\n */\n dismiss(options?: { instant?: boolean }): void;\n}\n\n/** The region's active toasts live on the region element (in the DOM), not in module state. */\nconst TOAST_SET = Symbol('kerf.toasts');\n/** A dismiss function with an `.removeNow()` for instant (no-exit) teardown. */\ntype Dismisser = (() => void) & { removeNow: () => void };\ntype ToastCarrier = Element & { [TOAST_SET]?: Set<Dismisser> };\n\n/** The singleton toast region lives in the DOM (queried, not held in a module variable). */\nfunction toastRegion(container?: Element): Element {\n if (container !== undefined) return container;\n const existing = document.querySelector('.kerf-toasts');\n if (existing !== null) return existing;\n const region = document.createElement('div');\n region.className = 'kerf-toasts';\n region.setAttribute('aria-live', 'polite');\n document.body.appendChild(region);\n return region;\n}\n\n/**\n * Show a non-modal, auto-dismissing notification. Stacks in a shared body-level\n * region (or your `container`). Returns a {@link ToastHandle} (`{ el, dismiss }`)\n * so you can run entrance/exit transitions, wire an action button, or inspect the\n * node. `mode: 'replace'` collapses a rapid sequence to the latest; `variant`\n * adds an accent class; `enterClass`/`exitClass` let CSS own the animation.\n */\nexport function toast(\n content: ToastContent,\n options: ToastOptions = {},\n): ToastHandle {\n const {\n container,\n className = 'kerf-toast',\n duration = 4000,\n role = 'status',\n mode = 'stack',\n collapse = 'fade',\n variant,\n enterClass,\n exitClass,\n exitDuration = 0,\n } = options;\n\n const region = toastRegion(container) as ToastCarrier;\n const active = (region[TOAST_SET] ??= new Set<Dismisser>());\n // collapse-to-latest: 'instant' removes priors synchronously (no cross-fade in a\n // centered single slot); 'fade' runs their exit transition (nice for a stack).\n if (mode === 'replace') {\n for (const d of [...active]) {\n if (collapse === 'instant') d.removeNow();\n else d();\n }\n }\n\n const el = document.createElement('div');\n el.className = className;\n if (variant !== undefined) el.classList.add(`${className}--${variant}`);\n el.setAttribute('role', role);\n region.appendChild(el);\n\n const render =\n typeof content === 'function'\n ? content\n : () => (typeof content === 'string' ? escapeHtml(content) : content);\n const disposeMount = mount(el, render);\n const state: {\n dismissed: boolean;\n removed: boolean;\n timer: ReturnType<typeof setTimeout> | undefined;\n exitTimer: ReturnType<typeof setTimeout> | undefined;\n } = {\n dismissed: false,\n removed: false,\n timer: undefined,\n exitTimer: undefined,\n };\n\n if (enterClass !== undefined) {\n globalThis.requestAnimationFrame(() => {\n if (!state.dismissed) el.classList.add(enterClass);\n });\n }\n\n const remove = (): void => {\n if (state.removed) return;\n state.removed = true;\n state.dismissed = true; // once removed, a later dismiss() is a clean no-op\n if (state.exitTimer !== undefined) clearTimeout(state.exitTimer);\n disposeMount();\n el.remove();\n active.delete(dismiss as Dismisser);\n };\n\n // Force synchronous teardown NOW, with no exit transition — even if a fade is\n // already in flight (so `mode:'replace'` collapse can clean up a mid-exit toast,\n // and `dismiss({ instant: true })` drops it immediately).\n const removeNow = (): void => {\n if (state.timer !== undefined) clearTimeout(state.timer);\n remove();\n };\n\n const fadeOut = (): void => {\n if (state.dismissed) return;\n state.dismissed = true;\n if (state.timer !== undefined) clearTimeout(state.timer);\n // Reverse the entrance (drop enterClass so exitClass needn't out-specify it),\n // add exitClass, and delay removal for the transition — including the\n // single-class idiom (enterClass removed + exitDuration, no exitClass).\n if (enterClass !== undefined) el.classList.remove(enterClass);\n if (exitClass !== undefined) el.classList.add(exitClass);\n if (exitClass !== undefined || exitDuration > 0) {\n state.exitTimer = setTimeout(remove, exitDuration);\n } else {\n remove();\n }\n };\n\n function dismiss(options?: { instant?: boolean }): void {\n if (options?.instant === true) removeNow();\n else fadeOut();\n }\n (dismiss as Dismisser).removeNow = removeNow;\n\n active.add(dismiss as Dismisser);\n if (duration > 0) state.timer = setTimeout(fadeOut, duration);\n return { el, dismiss };\n}\n"]}
1
+ {"version":3,"sources":["../src/overlay-core.ts","../src/overlay-choice.ts","../src/overlay-confirm.ts","../src/overlay-prompt.ts","../src/overlay-form.ts","../src/overlay-position.ts","../src/overlay-popover.ts","../src/overlay-toast.ts","../src/overlay-tooltip.ts"],"names":["options"],"mappings":"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","file":"overlay.js","sourcesContent":["/**\n * Shared overlay lifecycle and document arbitration implementation.\n *\n * Every real kerf app hand-rolls this: `toElement → body.appendChild → mount →\n * wire dismissal → remove`, plus the fiddly parts (Escape, backdrop / outside\n * click, focus trap, restoring focus on close). `window.confirm` is a no-op in\n * Tauri WKWebViews, so a hand-built overlay is mandatory there. This subpath\n * blesses the pattern through `overlay()`, with anchored surfaces and dialog\n * helpers building on it. No per-instance framework state: each call owns its\n * DOM + listeners in a closure and returns a handle.\n *\n * import { overlay, confirm, toast } from 'kerfjs/overlay';\n *\n * const ok = await confirm('Delete this file?', { danger: true });\n * toast('Saved');\n * const dialog = overlay(<Settings />, { dismiss: ['escape', 'backdrop'] });\n * // …later: dialog.close(); or await dialog.result;\n *\n * Structural only — kerf ships no CSS. The wrapper gets your `className`; style\n * the backdrop / centering / animation yourself.\n */\nimport { attach } from './attach.js';\nimport { devHooks } from './dev-hooks.js';\nimport type { SafeHtml } from './jsx-runtime.js';\nimport { mount, type MountResult } from './mount.js';\nimport { OVERLAY_HOST_SELECTOR } from './utils/overlay-host.js';\n\n/** A user-initiated dismissal trigger. */\nexport type DismissTrigger = 'escape' | 'backdrop' | 'outside';\n\n/** Content for an overlay: static `SafeHtml`, or a render function `mount()` drives reactively. */\nexport type OverlayContent = SafeHtml | (() => MountResult);\n\n/** Options for {@link overlay}. */\nexport interface OverlayOptions {\n /** Where to append the overlay wrapper. Default `document.body`. */\n container?: Element;\n /** Class on the wrapper element (you style it — kerf ships no CSS). Default `'kerf-overlay'`. */\n className?: string;\n /**\n * Which user actions dismiss the overlay. Default `['escape', 'backdrop']`.\n * `'backdrop'` = a click on the wrapper itself (not its content); `'outside'`\n * = a click anywhere outside the wrapper (for anchored popovers). `false`\n * disables user dismissal (close it programmatically).\n */\n dismiss?: DismissTrigger | DismissTrigger[] | false;\n /**\n * Where focus lands on open: a selector, `true` (first focusable element, or\n * the wrapper if none), or `false` (leave focus alone). Default `true`.\n */\n initialFocus?: string | boolean;\n /**\n * Trap Tab / Shift+Tab within the overlay while open and mark it\n * `role=\"dialog\"` / `aria-modal=\"true\"`. Default `true`. Set `false` for a\n * non-modal popover.\n */\n trap?: boolean;\n /** ARIA role for the wrapper when `trap` is on. Default `'dialog'`. */\n role?: string;\n /** Called on any user-initiated dismissal (before `close()` runs). */\n onDismiss?: () => void;\n /** For `'outside'` dismissal: clicks on these elements do NOT count as outside (e.g. the trigger button). */\n outsideIgnore?: Element | readonly Element[];\n /**\n * Opt into the browser **top layer** (`docs/19-native-overlay-backing.md`).\n * When `true` and the engine supports it, a modal overlay (`trap: true`) is\n * hosted in a `<dialog>` opened with `.showModal()` — real inerting of the rest\n * of the document + guaranteed stacking above any `z-index` — and a non-modal\n * one (`trap: false`) uses the Popover API (`[popover]` + `showPopover()`).\n * Feature-detected; falls back to today's plain `<div>` where unsupported.\n *\n * The `render` slot + promise API are unchanged — kerf just hosts your markup\n * in a `<dialog>` / `[popover]` instead of a `<div>`. Two caveats: native\n * `<dialog>` / `[popover]` carry **UA default styles** (a `::backdrop`,\n * centering, border, padding) that kerf does not reset — style the element (and\n * its `::backdrop`) via `className`; and `container` is effectively a **no-op**\n * for visual position, since the top layer ignores where the element lives in\n * the DOM. Default `false`.\n */\n native?: boolean;\n}\n\n/** Handle returned by {@link overlay}. Holds no framework state — it's a closure. */\nexport interface OverlayHandle {\n /** The wrapper element (mounted into, appended to `container`). */\n el: HTMLElement;\n /** Tear down: dispose the mount, remove listeners + the node, restore focus, resolve `result`. Idempotent. */\n close(result?: unknown): void;\n /** Resolves with the value passed to `close()` (or `undefined` on user dismissal). */\n result: Promise<unknown>;\n}\n\nconst FOCUSABLE =\n 'a[href],area[href],button:not([disabled]),input:not([disabled]),' +\n 'select:not([disabled]),textarea:not([disabled]),iframe,' +\n '[tabindex]:not([tabindex=\"-1\"]),[contenteditable=\"true\"]';\n\nfunction focusable(root: Element): HTMLElement[] {\n const items = Array.from(\n root.querySelectorAll<HTMLElement>(FOCUSABLE),\n ).filter((el) => !el.hasAttribute('hidden') && el.tabIndex >= 0);\n // WebKit on macOS follows the system's keyboard-navigation preference and\n // may omit implicitly tabbable controls from sequential focus navigation.\n // A focus trap promises stable traversal through every eligible control, so\n // make those implicit stops explicit while preserving authored tabindexes.\n for (const el of items) if (!el.hasAttribute('tabindex')) el.tabIndex = 0;\n return items;\n}\n\n// Native top-layer feature detection (KF-526). Modal → `<dialog>.showModal()`;\n// non-modal → the Popover API. Each is independent — an engine may ship one\n// without the other — and both fall back to the plain `<div>` where absent.\nfunction supportsDialog(): boolean {\n return (\n typeof HTMLDialogElement !== 'undefined' &&\n typeof HTMLDialogElement.prototype.showModal === 'function'\n );\n}\nfunction supportsPopover(): boolean {\n return (\n typeof HTMLElement !== 'undefined' &&\n typeof HTMLElement.prototype.showPopover === 'function'\n );\n}\n\n// Stacked-surface arbitration (KF-CW7GJ8: a tooltip inside a modal used to\n// become \"topmost\" and disable the modal's Escape, backdrop, and focus trap).\n// Every open overlay — native or fallback — is recorded, in open order, on a\n// per-document stack. An input kind (Escape, a backdrop / outside click, Tab\n// for the trap) belongs to the topmost surface that HANDLES that kind; a\n// surface that doesn't handle it is transparent, except that a modal surface\n// is a barrier nothing beneath it sees past. A tooltip (or any overlay with no\n// dismiss trigger and no trap) handles nothing, so it never intercepts. The\n// `handled` set marks an event a surface already acted on, so one click that is\n// both \"outside\" a popover and on the modal backdrop closes only the popover.\nconst OVERLAY_ARBITRATION = Symbol('kerf.overlayArbitration');\n\n/** An arbitration input: a dismiss trigger, or Tab for the focus trap. */\ntype ArbitrationKind = DismissTrigger | 'trap';\n\ninterface OverlaySurface {\n el: HTMLElement;\n triggers: readonly DismissTrigger[];\n modal: boolean;\n /** Where focus returns on close; re-pointed when the surface holding it closes first. */\n restoreTo: Element | null;\n /** Non-modal only: move (or re-show) into the top layer above a newly opened modal `<dialog>`. */\n liftAbove?: () => void;\n}\n\ninterface OverlayArbitration {\n stack: OverlaySurface[];\n handled: WeakSet<Event>;\n /** Document capture listener, installed only while the stack is non-empty. */\n onToggle: (event: Event) => void;\n}\n\ntype ArbitratedDocument = Document & {\n [OVERLAY_ARBITRATION]?: OverlayArbitration;\n};\n\nfunction overlayArbitration(doc: Document): OverlayArbitration {\n const arbitrated = doc as ArbitratedDocument;\n return (arbitrated[OVERLAY_ARBITRATION] ??= {\n stack: [],\n handled: new WeakSet(),\n // KF-AHY6H4: an app-owned modal `<dialog>` opened outside kerf would leave\n // the kerf surfaces already showing inert beneath it. A dialog fires\n // `toggle` after it opens (it does not bubble, so listen in the capture\n // phase); re-host above it exactly as kerf does for its own dialogs, which\n // are skipped here because `overlay()` already re-hosted synchronously.\n onToggle: (event) => {\n const dialog = event.target as Element;\n const arbitration = arbitrated[OVERLAY_ARBITRATION] as OverlayArbitration;\n if (\n dialog.tagName === 'DIALOG' &&\n !arbitration.stack.some(({ el }) => el === dialog) &&\n isOpenModal(dialog, arbitration)\n )\n rehostAbove(arbitration, dialog);\n },\n });\n}\n\n// Every non-modal kerf surface already open is blocked beneath a modal\n// `<dialog>` that just opened: lift (or re-show) it above (KF-FJ9VD8). One\n// inside that dialog is part of its subtree already.\nfunction rehostAbove(arbitration: OverlayArbitration, dialog: Element): void {\n for (const { el, liftAbove } of arbitration.stack)\n if (el !== dialog && el.isConnected && !dialog.contains(el)) liftAbove?.();\n}\n\n// Is `dialog` an open modal `<dialog>`? kerf's own are known from the stack;\n// an app-owned one is found through `:modal`, which an older engine may not\n// parse (then only kerf's own count).\nfunction isOpenModal(\n dialog: Element,\n arbitration: OverlayArbitration,\n): boolean {\n if (!dialog.isConnected || (dialog as HTMLDialogElement).open !== true)\n return false;\n if (arbitration.stack.some(({ el, modal }) => modal && el === dialog))\n return true;\n try {\n return dialog.matches(':modal');\n } catch {\n return false; // `:modal` unsupported\n }\n}\n\n// Is a modal `<dialog>` open (KF-0V9RTE: a plain surface opened in that state\n// is inert and painted beneath the dialog's top layer)?\nfunction modalDialogOpen(\n doc: Document,\n arbitration: OverlayArbitration,\n): boolean {\n return (\n arbitration.stack.some(({ el }) => isOpenModal(el, arbitration)) ||\n Array.from(doc.querySelectorAll('dialog[open]')).some((dialog) =>\n isOpenModal(dialog, arbitration),\n )\n );\n}\n\n// The in-dialog host slot (KF-FBHQEP: a surface lifted over a modal\n// `<dialog>` is visible but inert, because every engine inerts content outside\n// the modal). A `popover()` / `tooltip()` whose anchor sits inside an open\n// modal `<dialog>` renders into that dialog's `[data-kerf-overlay-host]`\n// element instead, so it is part of the modal subtree and fully interactive.\n// An app-owned dialog opts in by marking an element; a dialog kerf opened\n// itself gets one on demand — `display: contents` so it adds no layout box,\n// and `data-morph-skip` + `data-morph-preserve` so the dialog content's own\n// `mount()` neither re-renders nor removes it (`utils/overlay-host.ts` makes\n// the slot a nested-mount boundary).\nexport function overlayHost(anchor: Element): Element | undefined {\n const arbitration = overlayArbitration(document);\n const dialog = anchor.closest('dialog');\n if (dialog === null || !isOpenModal(dialog, arbitration)) return undefined;\n let host = Array.from(dialog.querySelectorAll(OVERLAY_HOST_SELECTOR)).find(\n (el) => el.closest('dialog') === dialog,\n );\n if (host === undefined && arbitration.stack.some(({ el }) => el === dialog)) {\n dialog.insertAdjacentHTML(\n 'beforeend',\n '<div data-kerf-overlay-host data-morph-skip data-morph-preserve style=\"display:contents\"></div>',\n );\n host = dialog.lastElementChild as Element;\n }\n return host;\n}\n\n// `self` is on the stack and handles `kind` (its callers are exactly the\n// handlers it installed for that kind), so it owns `kind` unless some surface\n// above it handles `kind` too or is modal.\nfunction ownsInput(\n stack: readonly OverlaySurface[],\n self: OverlaySurface,\n kind: ArbitrationKind,\n): boolean {\n for (let i = stack.indexOf(self) + 1; i < stack.length; i++) {\n const above = stack[i];\n if (above.modal || (kind !== 'trap' && above.triggers.includes(kind)))\n return false;\n }\n return true;\n}\n\n// Validate a string `initialFocus` BEFORE any DOM mutation: `querySelector`\n// throws a generic `SyntaxError` DOMException on a malformed selector, and the\n// focus pass runs last — after the wrapper, mount, listeners, and stack entry\n// already exist — so an unvalidated selector would strand all of them with no\n// handle to close. An inert fragment parses the selector without matching.\nfunction assertInitialFocusSelector(selector: string): void {\n try {\n document.createDocumentFragment().querySelector(selector);\n } catch (cause) {\n throw new Error(\n `overlay(): invalid initialFocus selector ${JSON.stringify(selector)}`,\n { cause },\n );\n }\n}\n\n/**\n * Open an overlay: append a wrapper to `container`, `mount()` `content` inside\n * it, wire the requested dismissals + (optionally) a focus trap, and return a\n * handle. Concurrent fallback overlays dismiss from the top down. See\n * {@link OverlayOptions}.\n *\n * Construction is transactional: a malformed `initialFocus` selector throws a\n * descriptive error before anything is touched, and if a later setup phase\n * throws (the content's first render, `showModal()` / `showPopover()`), every\n * piece already installed — wrapper node, mount, listeners, fallback-stack\n * entry, top-layer state, moved focus — is rolled back before the original\n * error is rethrown.\n */\nexport function overlay(\n content: OverlayContent,\n options: OverlayOptions = {},\n): OverlayHandle {\n const {\n container = document.body,\n className = 'kerf-overlay',\n dismiss = ['escape', 'backdrop'],\n initialFocus = true,\n trap = true,\n role = 'dialog',\n onDismiss,\n outsideIgnore,\n native = false,\n } = options;\n\n if (typeof initialFocus === 'string')\n assertInitialFocusSelector(initialFocus);\n\n const triggers: readonly DismissTrigger[] =\n dismiss === false ? [] : Array.isArray(dismiss) ? dismiss : [dismiss];\n\n // Native top-layer backing (KF-526), feature-detected: a modal overlay\n // (`trap`) → `<dialog>.showModal()`; a non-modal one → `[popover]`. Each falls\n // back to the plain `<div>` where the API is missing, so behavior is unchanged\n // on unsupporting engines. A surface opened while a modal `<dialog>` is open\n // is lifted the same way even without `native` (KF-0V9RTE), because a plain\n // `<div>` would be inert and painted beneath the dialog.\n const arbitration = overlayArbitration(document);\n // A surface placed inside an open modal `<dialog>` (its host slot, or an\n // explicit `container` there) is already part of the modal subtree: no lift.\n const containerDialog = container.closest('dialog');\n const liftOverModal =\n !native &&\n !(containerDialog !== null && isOpenModal(containerDialog, arbitration)) &&\n modalDialogOpen(document, arbitration);\n const topLayer = native || liftOverModal;\n const useDialog = topLayer && trap && supportsDialog();\n const usePopover = topLayer && !trap && supportsPopover();\n\n const wrapper: HTMLElement = useDialog\n ? document.createElement('dialog')\n : document.createElement('div');\n wrapper.className = className;\n if (usePopover) wrapper.setAttribute('popover', 'manual');\n // `<dialog>.showModal()` conveys modality natively (role + inert), so the ARIA\n // attributes are only needed on the plain-`<div>` fallback.\n if (trap && !useDialog) {\n wrapper.setAttribute('role', role);\n wrapper.setAttribute('aria-modal', 'true');\n }\n const surface: OverlaySurface = {\n el: wrapper,\n triggers,\n modal: trap,\n restoreTo: document.activeElement,\n };\n\n // Does this surface own `kind` right now (and has no surface acted on `event`)?\n const owns = (kind: ArbitrationKind, event?: Event): boolean =>\n !(event !== undefined && arbitration.handled.has(event)) &&\n ownsInput(arbitration.stack, surface, kind);\n\n const removers: Array<() => void> = [];\n const resultBox: { resolve?: (value: unknown) => void } = {};\n const result = new Promise<unknown>((resolve) => {\n resultBox.resolve = resolve;\n });\n const state = { closed: false };\n let disposeMount: (() => void) | undefined;\n let nativeOpened = false;\n\n // KF-FJ9VD8: a modal `<dialog>` kerf opens later would leave this non-modal\n // surface inert beneath it, so the opener calls this to move it into the top\n // layer — or, if it is already a `[popover]`, re-show it so it stacks above\n // the new dialog (the top layer orders by most recent show).\n if (!trap)\n surface.liftAbove = () => {\n if (!supportsPopover()) {\n devHooks.overlayBlockedByModal?.('hidden');\n return;\n }\n const el = wrapper as HTMLElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n if (nativeOpened) el.hidePopover();\n else {\n wrapper.setAttribute('popover', 'manual');\n wrapper.style.inset = 'auto';\n }\n el.showPopover();\n nativeOpened = true;\n if (wrapper.querySelector(FOCUSABLE) !== null)\n devHooks.overlayBlockedByModal?.('inert');\n };\n\n // Also the construction rollback (see the transaction below): every step\n // tolerates a phase that never ran — no mount yet, no stack entry, never\n // appended, never shown.\n function close(value?: unknown): void {\n if (state.closed) return;\n state.closed = true;\n const { stack } = arbitration;\n const stackIndex = stack.indexOf(surface);\n if (stackIndex !== -1) stack.splice(stackIndex, 1);\n if (stack.length === 0)\n document.removeEventListener('toggle', arbitration.onToggle, true);\n // A surface opened from inside this one would restore focus into a node\n // that is about to be detached: hand it this surface's own restore target.\n for (const other of stack)\n if (other.restoreTo !== null && wrapper.contains(other.restoreTo))\n other.restoreTo = surface.restoreTo;\n const active = document.activeElement;\n for (const remove of removers) remove();\n disposeMount?.();\n // Exit the top layer before removing the node, so the native close steps run\n // (restore inert, fire the dialog's `close`). `<dialog>` also restores focus\n // itself; kerf's manual restore below stays as the fallback path's behavior.\n if (nativeOpened) {\n nativeOpened = false;\n if (useDialog) (wrapper as HTMLDialogElement).close();\n else (wrapper as HTMLElement & { hidePopover(): void }).hidePopover();\n }\n wrapper.remove();\n restoreFocus(active);\n resultBox.resolve?.(value);\n }\n\n // Closing a surface that doesn't hold focus (an out-of-order close beneath\n // another open surface) must not pull focus out of the surface that does;\n // otherwise focus returns to where it was when this surface opened.\n function restoreFocus(active: Element | null): void {\n if (\n active instanceof HTMLElement &&\n active.isConnected &&\n arbitration.stack.some((other) => other.el.contains(active))\n ) {\n if (document.activeElement !== active) active.focus();\n return;\n }\n const { restoreTo } = surface;\n if (restoreTo instanceof HTMLElement && restoreTo.isConnected)\n restoreTo.focus();\n }\n\n function userDismiss(): void {\n onDismiss?.();\n close();\n }\n\n // One transaction: if any phase below throws (the content's first render,\n // `showModal()` / `showPopover()`, …), roll back whatever the earlier phases\n // installed via `close()` and rethrow the original error. No handle is\n // returned on failure, so nothing may outlive the call.\n try {\n container.appendChild(wrapper);\n disposeMount = mount(\n wrapper,\n typeof content === 'function' ? content : () => content,\n );\n // Watch for app-owned modal dialogs while any kerf surface is open.\n if (arbitration.stack.push(surface) === 1)\n document.addEventListener('toggle', arbitration.onToggle, true);\n\n // Enter the top layer after the content is mounted + connected.\n // `showModal()` moves focus into the dialog by default; kerf's\n // `initialFocus` pass below runs afterward and wins.\n if (useDialog) {\n (wrapper as HTMLDialogElement).showModal();\n nativeOpened = true;\n rehostAbove(arbitration, wrapper);\n } else if (usePopover) {\n (wrapper as HTMLElement & { showPopover(): void }).showPopover();\n nativeOpened = true;\n // Neutralize the UA `[popover] { inset: 0; margin: auto }` anchoring so\n // `positionAnchored` (which sets `top`/`left`) controls placement —\n // otherwise the retained `right`/`bottom` insets would stretch/center it.\n wrapper.style.inset = 'auto';\n }\n\n installDismissal();\n if (container.closest(OVERLAY_HOST_SELECTOR) !== null) {\n makeTabReachable();\n // KF-WZ9KQM: a slot-hosted surface leaves with its dialog even when its\n // anchor (moved out of the dialog) stays connected, so the anchor watch\n // never fires. Watch the wrapper itself: close as cleanup (no\n // `onDismiss`) and leave the open-order stack.\n removers.push(attach(wrapper, () => close));\n }\n applyInitialFocus();\n } catch (error) {\n close();\n throw error;\n }\n\n // What the lift cannot repair: no top-layer API at all, or a lifted\n // non-modal surface whose controls the modal still inerts.\n if (liftOverModal) {\n if (!useDialog && !usePopover) devHooks.overlayBlockedByModal?.('hidden');\n else if (usePopover && wrapper.querySelector(FOCUSABLE) !== null)\n devHooks.overlayBlockedByModal?.('inert');\n }\n\n return { el: wrapper, close, result };\n\n function installDismissal(): void {\n const wantEscape = triggers.includes('escape');\n if (useDialog) {\n // A native modal `<dialog>` confines Tab focus itself and surfaces Escape as\n // a `cancel` event. Take that over: `preventDefault` so kerf owns teardown\n // (and so Escape is swallowed when it isn't a dismiss trigger), then dismiss.\n // A surface stacked above that handles Escape (or is modal) owns it; a\n // stray `cancel` then leaves this dialog open.\n const onCancel = (event: Event): void => {\n event.preventDefault();\n if (wantEscape && owns('escape')) userDismiss();\n };\n wrapper.addEventListener('cancel', onCancel);\n removers.push(() => wrapper.removeEventListener('cancel', onCancel));\n } else if (wantEscape || trap) {\n const onKeydown = (event: KeyboardEvent): void => {\n if (wantEscape && event.key === 'Escape') {\n if (!owns('escape', event)) return;\n // `preventDefault` also withholds the close request from a native\n // `<dialog>` beneath, so one Escape closes exactly one surface.\n event.stopPropagation();\n event.preventDefault();\n arbitration.handled.add(event);\n userDismiss();\n return;\n }\n if (trap && event.key === 'Tab' && owns('trap')) {\n const items = focusable(wrapper);\n if (items.length === 0) {\n event.preventDefault();\n return;\n }\n const first = items[0];\n const last = items[items.length - 1];\n const active = document.activeElement;\n const outside = !wrapper.contains(active);\n if (event.shiftKey && (active === first || outside)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (active === last || outside)) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n document.addEventListener('keydown', onKeydown, true);\n removers.push(() =>\n document.removeEventListener('keydown', onKeydown, true),\n );\n }\n\n if (triggers.includes('backdrop')) {\n const onClick = (event: Event): void => {\n if (event.target !== wrapper || !owns('backdrop', event)) return;\n arbitration.handled.add(event);\n userDismiss();\n };\n wrapper.addEventListener('click', onClick);\n removers.push(() => wrapper.removeEventListener('click', onClick));\n }\n\n if (triggers.includes('outside')) {\n const ignore =\n outsideIgnore === undefined\n ? []\n : Array.isArray(outsideIgnore)\n ? outsideIgnore\n : [outsideIgnore];\n // Capture phase: the click that opened this overlay already passed\n // document's capture phase, so this never fires for that opening click.\n const onDocClick = (event: Event): void => {\n const target = event.target as Node | null;\n if (target === null) return;\n if (wrapper.contains(target)) return;\n if (ignore.some((el) => el === target || el.contains(target))) return;\n if (!owns('outside', event)) return;\n arbitration.handled.add(event);\n userDismiss();\n };\n document.addEventListener('click', onDocClick, true);\n removers.push(() =>\n document.removeEventListener('click', onDocClick, true),\n );\n }\n }\n\n // KF-QZ9SFG (slot-hosted controls unreachable by Tab in macOS WebKit): a\n // surface in an overlay host slot sits in the modal dialog's own Tab order,\n // not behind a kerf trap, so WebKit's system keyboard-navigation preference\n // would skip its implicitly tabbable controls. Make those stops explicit, as\n // the trap does — now, and again before each Tab so a control a re-render\n // added (or whose tabindex the morph dropped) is reachable too.\n function makeTabReachable(): void {\n focusable(wrapper);\n const onTab = (event: KeyboardEvent): void => {\n if (event.key === 'Tab') focusable(wrapper);\n };\n document.addEventListener('keydown', onTab, true);\n removers.push(() => document.removeEventListener('keydown', onTab, true));\n }\n\n function applyInitialFocus(): void {\n if (initialFocus !== false) {\n if (typeof initialFocus === 'string') {\n wrapper.querySelector<HTMLElement>(initialFocus)?.focus();\n } else {\n const first = focusable(wrapper)[0];\n if (first !== undefined) {\n first.focus();\n } else {\n wrapper.tabIndex = -1;\n wrapper.focus();\n }\n }\n }\n }\n}\n\n/**\n * Internal: run a promise-dialog helper's post-open wiring (required-slot\n * lookups, `delegate()` handlers, key listeners) as the tail of `overlay()`'s\n * construction transaction. `wire` registers a disposer for every listener it\n * installs via `track`; if any step throws, those listeners are removed, the\n * just-opened overlay is closed (node, mount, dismissal listeners, stack\n * entry, top-layer state, focus), and the original error is rethrown — so a\n * failed helper call returns no promise and leaves no open overlay behind.\n *\n * After construction, `guard` wraps a user-action handler (OK click, Enter).\n * KF-B0CFQP (a throwing `validate` callback): a throw inside a guarded action\n * is a programming error, so it closes the dialog (full teardown, focus\n * restored) and the returned promise REJECTS with the original error, instead\n * of the error escaping the event handler and stranding an open dialog whose\n * OK can never succeed. Otherwise the returned promise settles with\n * `settle(handle.result's value)`. Not re-exported from `kerfjs/overlay`.\n */\nexport function wireDialog<T>(\n handle: OverlayHandle,\n wire: (\n track: (dispose: () => void) => void,\n guard: (action: () => void) => () => void,\n ) => void,\n settle: (value: unknown) => T,\n): Promise<T> {\n const disposers: Array<() => void> = [];\n // Holds a guarded action's error AND is the close() value that marks the\n // failure, so only a throw that actually settles the dialog rejects it.\n const failure: unknown[] = [];\n try {\n wire(\n (dispose) => void disposers.push(dispose),\n (action) => () => {\n try {\n action();\n } catch (error) {\n failure[0] = error;\n handle.close(failure);\n }\n },\n );\n } catch (error) {\n disposers.forEach((dispose) => dispose());\n handle.close();\n throw error;\n }\n // One hop, not a chain: `settle` maps the value in the same reaction, so a\n // helper's promise settles as soon after `close()` as it always has.\n return handle.result.then((value) => {\n if (value === failure) throw failure[0];\n return settle(value);\n });\n}\n","/** `choice()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/** One choosable action in a {@link choice} dialog. */\nexport interface ChoiceAction<R> {\n value: R;\n label: string;\n className?: string;\n}\n\n/** Wiring slots for a {@link ChoiceOptions.render}. */\nexport interface ChoiceRenderSlots {\n message: string;\n actions: Array<Record<string, string>>;\n}\n\n/** Options for {@link choice}. */\nexport interface ChoiceOptions<R> {\n container?: Element;\n className?: string;\n title?: string;\n defaultValue?: R;\n native?: boolean;\n render?: (slots: ChoiceRenderSlots) => OverlayContent;\n}\n\n/** The N-way sibling of {@link confirm}. */\nexport function choice<R>(\n message: string,\n actions: ReadonlyArray<ChoiceAction<R>>,\n options: ChoiceOptions<R> = {},\n): Promise<R | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n defaultValue,\n native = false,\n render,\n } = options;\n const hasDefault = 'defaultValue' in options;\n const actionAttrs = actions.map((_, i) => ({ 'data-choice': String(i) }));\n\n const body: OverlayContent =\n render !== undefined\n ? render({ message, actions: actionAttrs })\n : jsx('div', {\n class: 'kerf-choice',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-choice__title', children: title })\n : '',\n jsx('p', { class: 'kerf-choice__message', children: message }),\n jsx('div', {\n class: 'kerf-choice__actions',\n children: actions.map((action, i) =>\n jsx('button', {\n type: 'button',\n class:\n action.className !== undefined\n ? `kerf-choice__action ${action.className}`\n : 'kerf-choice__action',\n ...actionAttrs[i],\n children: action.label,\n }),\n ),\n }),\n ],\n });\n\n let resolveChoice!: (result: R | null) => void;\n const result = new Promise<R | null>((resolve) => {\n resolveChoice = resolve;\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-choice]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a throw closes the overlay. Any\n // close settles a still-pending choice as a dismissal (`null`).\n void wireDialog(\n handle,\n (track) => {\n track(\n delegate(handle.el, 'click', '[data-choice]', (_event, el) => {\n resolveChoice(actions[Number(el.getAttribute('data-choice'))].value);\n handle.close();\n }),\n );\n\n if (hasDefault) {\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === 'Enter') {\n event.preventDefault();\n resolveChoice(defaultValue as R);\n handle.close();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n }\n },\n () => resolveChoice(null),\n );\n return result;\n}\n","/** `confirm()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/** Wiring slots passed to a {@link ConfirmOptions.render}. */\nexport interface ConfirmRenderSlots {\n message: string;\n /** Spread onto the confirm control. */\n ok: Record<string, string>;\n /** Spread onto the cancel control. */\n cancel: Record<string, string>;\n}\n\n/** Options for {@link confirm}. */\nexport interface ConfirmOptions {\n /** Where to append the overlay. Default `document.body`. */\n container?: Element;\n /** Wrapper class. Default `'kerf-overlay'`. */\n className?: string;\n /** Optional heading above the message. */\n title?: string;\n /** Confirm button label. Default `'OK'`. */\n okText?: string;\n /** Cancel button label. Default `'Cancel'`. */\n cancelText?: string;\n /** Add a `kerf-confirm--danger` class to the wrapper for destructive actions. */\n danger?: boolean;\n /** Host the dialog in the browser top layer where supported. */\n native?: boolean;\n /** Bring your own body while retaining kerf's dialog wiring. */\n render?: (slots: ConfirmRenderSlots) => OverlayContent;\n}\n\n/** A promise-based `window.confirm` replacement. */\nexport function confirm(\n message: string,\n options: ConfirmOptions = {},\n): Promise<boolean> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n okText = 'OK',\n cancelText = 'Cancel',\n danger = false,\n native = false,\n render,\n } = options;\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n message,\n ok: { 'data-confirm': 'ok' },\n cancel: { 'data-confirm': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-confirm',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-confirm__title', children: title })\n : '',\n jsx('p', { class: 'kerf-confirm__message', children: message }),\n jsx('div', {\n class: 'kerf-confirm__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-confirm': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-confirm': 'ok',\n class: 'kerf-confirm__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className: danger ? `${className} kerf-confirm--danger` : className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-confirm=\"ok\"]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a throw closes the overlay. The\n // click table is the only (and so the last) step, so it needs no rollback.\n return wireDialog(\n handle,\n () => {\n delegate(handle.el, 'click', '[data-confirm]', (_event, el) => {\n handle.close(el.getAttribute('data-confirm') === 'ok');\n });\n },\n (value) => value === true,\n );\n}\n","/** `prompt()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\n\n/**\n * Validate a single field's value, synchronously: return a non-empty message\n * to block OK, anything else to accept. A validator that throws is treated as\n * a programming error — the dialog closes and the returned promise rejects\n * with that error.\n */\nexport type FieldValidator = (\n value: string,\n) => string | null | undefined | void;\n\n/** Options for {@link prompt}. */\n/**\n * Run a {@link FieldValidator}: the message it reports, or `undefined` when the\n * value is valid. Validators are synchronous — a promise result is a\n * programming error that closes the dialog and rejects its promise (the stray\n * promise's own rejection is silenced so it is not reported twice).\n * Internal to the dialog helpers.\n */\nexport function runValidator(\n validate: FieldValidator | undefined,\n value: string,\n owner: string,\n): string | undefined {\n const result: unknown = validate?.(value);\n if (typeof (result as PromiseLike<unknown> | null)?.then === 'function') {\n (result as PromiseLike<unknown>).then(undefined, () => undefined);\n throw new TypeError(`${owner}: validate returned a promise.`);\n }\n return typeof result === 'string' && result.length > 0 ? result : undefined;\n}\n\nexport interface PromptOptions {\n container?: Element;\n className?: string;\n title?: string;\n defaultValue?: string;\n placeholder?: string;\n inputType?: string;\n okText?: string;\n cancelText?: string;\n validate?: FieldValidator;\n native?: boolean;\n render?: (slots: PromptRenderSlots) => OverlayContent;\n}\n\n/** Wiring slots for a {@link PromptOptions.render}. */\nexport interface PromptRenderSlots {\n message: string;\n input: Record<string, string>;\n error: Record<string, string>;\n ok: Record<string, string>;\n cancel: Record<string, string>;\n}\n\n/** A promise-based `window.prompt` replacement. */\nexport function prompt(\n message: string,\n options: PromptOptions = {},\n): Promise<string | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n defaultValue = '',\n placeholder,\n inputType = 'text',\n okText = 'OK',\n cancelText = 'Cancel',\n validate,\n native = false,\n render,\n } = options;\n\n const inputAttrs: Record<string, string> = {\n 'data-prompt-input': '',\n type: inputType,\n value: defaultValue,\n ...(placeholder !== undefined ? { placeholder } : {}),\n };\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n message,\n input: inputAttrs,\n error: { 'data-prompt-error': '' },\n ok: { 'data-prompt': 'ok' },\n cancel: { 'data-prompt': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-prompt',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-prompt__title', children: title })\n : '',\n jsx('label', { class: 'kerf-prompt__message', children: message }),\n jsx('input', { class: 'kerf-prompt__input', ...inputAttrs }),\n jsx('p', {\n class: 'kerf-prompt__error',\n 'data-prompt-error': '',\n children: '',\n }),\n jsx('div', {\n class: 'kerf-prompt__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-prompt': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-prompt': 'ok',\n class: 'kerf-prompt__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-prompt-input]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a missing required input or any\n // other throw below removes what was wired, closes the overlay, and rethrows.\n return wireDialog(\n handle,\n (track, guard) => {\n // Looked up again at OK: a reactive re-render may have replaced the\n // input, and a detached node would report a stale value. Missing at\n // construction is a render bug (rolls back, throws); missing at OK\n // rejects the promise through `guard`.\n const inputFor = (problem = 'render missing'): HTMLInputElement => {\n const input = handle.el.querySelector<HTMLInputElement>(\n 'input[data-prompt-input]',\n );\n if (input !== null) return input;\n throw new Error(`prompt(): ${problem} <input data-prompt-input>.`);\n };\n inputFor();\n const errorEl = handle.el.querySelector<HTMLElement>(\n '[data-prompt-error]',\n );\n if (errorEl !== null) errorEl.hidden = true;\n\n // A throwing (or promise-returning) `validate` closes the dialog and\n // rejects the promise (guard).\n const attemptOk = guard((): void => {\n const input = inputFor('removed after open:');\n const value = input.value;\n const error = runValidator(validate, value, 'prompt()');\n if (error !== undefined) {\n if (errorEl !== null) {\n errorEl.textContent = error;\n errorEl.hidden = false;\n }\n input.focus();\n return;\n }\n handle.close(value);\n });\n\n track(\n delegate(handle.el, 'click', '[data-prompt]', (_event, el) => {\n if (el.getAttribute('data-prompt') === 'ok') attemptOk();\n else handle.close(null);\n }),\n );\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (\n event.key === 'Enter' &&\n (event.target as Element | null)?.matches('input[data-prompt-input]')\n ) {\n event.preventDefault();\n attemptOk();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n },\n (value) => (typeof value === 'string' ? value : null),\n );\n}\n","/** `form()` implementation and public option types. */\nimport { delegate } from './delegate.js';\nimport { jsx } from './jsx-runtime.js';\nimport { overlay, type OverlayContent, wireDialog } from './overlay-core.js';\nimport { type FieldValidator, runValidator } from './overlay-prompt.js';\n\n/** A single field in a {@link form}. */\nexport interface FormField {\n name: string;\n label?: string;\n defaultValue?: string;\n placeholder?: string;\n type?: string;\n validate?: FieldValidator;\n}\n\n/** One field's wiring in a {@link FormRenderSlots}. */\nexport interface FormRenderField {\n name: string;\n label: string;\n input: Record<string, string>;\n error: Record<string, string>;\n}\n\n/** Wiring slots for a {@link FormOptions.render}. */\nexport interface FormRenderSlots {\n fields: FormRenderField[];\n ok: Record<string, string>;\n cancel: Record<string, string>;\n}\n\n/** Options for {@link form}. */\nexport interface FormOptions {\n container?: Element;\n className?: string;\n title?: string;\n okText?: string;\n cancelText?: string;\n native?: boolean;\n render?: (slots: FormRenderSlots) => OverlayContent;\n}\n\n/** A promise-based multi-field dialog. */\nexport function form(\n fields: readonly FormField[],\n options: FormOptions = {},\n): Promise<Record<string, string> | null> {\n const {\n container,\n className = 'kerf-overlay',\n title,\n okText = 'OK',\n cancelText = 'Cancel',\n native = false,\n render,\n } = options;\n\n const fieldAttrs = (field: FormField): Record<string, string> => ({\n 'data-field': field.name,\n name: field.name,\n type: field.type ?? 'text',\n value: field.defaultValue ?? '',\n ...(field.placeholder !== undefined\n ? { placeholder: field.placeholder }\n : {}),\n });\n\n const body: OverlayContent =\n render !== undefined\n ? render({\n fields: fields.map((field) => ({\n name: field.name,\n label: field.label ?? field.name,\n input: fieldAttrs(field),\n error: { 'data-field-error': field.name },\n })),\n ok: { 'data-form': 'ok' },\n cancel: { 'data-form': 'cancel' },\n })\n : jsx('div', {\n class: 'kerf-form',\n children: [\n title !== undefined\n ? jsx('h2', { class: 'kerf-form__title', children: title })\n : '',\n ...fields.map((field) =>\n jsx('div', {\n class: 'kerf-form__field',\n children: [\n jsx('label', {\n class: 'kerf-form__label',\n children: field.label ?? field.name,\n }),\n jsx('input', {\n class: 'kerf-form__input',\n ...fieldAttrs(field),\n }),\n jsx('p', {\n class: 'kerf-form__error',\n 'data-field-error': field.name,\n children: '',\n }),\n ],\n }),\n ),\n jsx('div', {\n class: 'kerf-form__actions',\n children: [\n jsx('button', {\n type: 'button',\n 'data-form': 'cancel',\n children: cancelText,\n }),\n jsx('button', {\n type: 'button',\n 'data-form': 'ok',\n class: 'kerf-form__ok',\n children: okText,\n }),\n ],\n }),\n ],\n });\n\n const handle = overlay(body, {\n container,\n className,\n dismiss: ['escape', 'backdrop'],\n initialFocus: '[data-field]',\n trap: true,\n native,\n });\n\n // Post-open wiring is still construction: a missing required field input or\n // any other throw below removes what was wired, closes the overlay, and\n // rethrows.\n return wireDialog(\n handle,\n (track, guard) => {\n const errorFor = (name: string): HTMLElement | null =>\n Array.from(\n handle.el.querySelectorAll<HTMLElement>('[data-field-error]'),\n ).find((el) => el.getAttribute('data-field-error') === name) ?? null;\n // KF-HRNJ4T (a field input removed after open by a reactive re-render):\n // at construction a missing input is a render bug that rolls back and\n // throws synchronously; at OK time it throws inside `guard`, so the\n // dialog closes and the promise rejects naming the field — never a\n // `null` that reads as a user Cancel.\n const inputFor = (\n name: string,\n problem = 'render missing',\n ): HTMLInputElement => {\n const input = Array.from(\n handle.el.querySelectorAll<HTMLInputElement>('input[data-field]'),\n ).find((el) => el.getAttribute('data-field') === name);\n if (input !== undefined) return input;\n throw new Error(`form(): ${problem} <input data-field=\"${name}\">.`);\n };\n\n for (const field of fields) {\n inputFor(field.name);\n const errorEl = errorFor(field.name);\n if (errorEl !== null) errorEl.hidden = true;\n }\n\n // A throwing `field.validate` closes the dialog and rejects the promise.\n const attemptOk = guard((): void => {\n const record: Record<string, string> = {};\n let firstInvalid: HTMLInputElement | null = null;\n for (const field of fields) {\n const el = inputFor(field.name, 'removed after open:');\n const value = el.value;\n record[field.name] = value;\n const error = runValidator(field.validate, value, 'form()');\n const errorEl = errorFor(field.name);\n if (error !== undefined) {\n if (errorEl !== null) {\n errorEl.textContent = error;\n errorEl.hidden = false;\n }\n if (firstInvalid === null) firstInvalid = el;\n } else if (errorEl !== null) {\n errorEl.hidden = true;\n }\n }\n if (firstInvalid !== null) {\n firstInvalid.focus();\n return;\n }\n handle.close(record);\n });\n\n track(\n delegate(handle.el, 'click', '[data-form]', (_event, el) => {\n if (el.getAttribute('data-form') === 'ok') attemptOk();\n else handle.close(null);\n }),\n );\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (\n event.key === 'Enter' &&\n (event.target as Element | null)?.matches('[data-field]')\n ) {\n event.preventDefault();\n attemptOk();\n }\n };\n // Last wiring step: nothing after it can throw, so it needs no rollback.\n handle.el.addEventListener('keydown', onKeydown);\n },\n (value) =>\n value !== null && typeof value === 'object'\n ? (value as Record<string, string>)\n : null,\n );\n}\n","/**\n * Anchored positioning primitives for `kerfjs/overlay` — position an element\n * relative to an anchor, with viewport flip + clamp. These are standalone: they\n * take any element and have no overlay lifecycle, so `popover()` / `tooltip()`\n * build on them but you can also position your own element (an inline hint, a\n * custom menu). Re-exported from `src/overlay.ts` so the public `kerfjs/overlay`\n * surface is unchanged (KF-511 split out of overlay.ts's dialog + toast code).\n */\n\n/** Vertical placement relative to an anchor (used by `popover`, {@link positionAnchored}, `tooltip`). */\nexport type PopoverPlacement = 'bottom' | 'top';\n\n/** Placement options for {@link positionAnchored} / {@link autoReposition}. */\nexport interface AnchorPositionOptions {\n /** Preferred side of the anchor; flips to the other side if it would overflow the viewport. Default `'bottom'`. */\n placement?: PopoverPlacement;\n /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */\n align?: 'start' | 'end';\n /** Gap in px between the anchor and the element. Default `4`. */\n gap?: number;\n}\n\n/**\n * One-shot: position `el` relative to `anchor` — below by default, flipping above\n * if it would overflow the viewport, aligned to a horizontal edge and clamped into\n * view. Sets `el.style` `position: fixed`, `margin: 0`, `left`, and `top` (fixed so\n * `left`/`top` are viewport coordinates, matching `getBoundingClientRect`). When an\n * ancestor makes itself the containing block for fixed descendants (a\n * `transform`, `filter`, `perspective`, or `contain` on a wrapping `<dialog>`),\n * `left`/`top` are translated (and unscaled) into that box's coordinates so `el`\n * still lands next to the anchor. This is\n * `popover()`'s placement core, usable on any element (an inline hint, a tooltip) —\n * no overlay lifecycle. Pair with {@link autoReposition} to keep it glued while open.\n */\nexport function positionAnchored(\n el: HTMLElement,\n anchor: Element,\n options: AnchorPositionOptions = {},\n): void {\n const { placement = 'bottom', align = 'start', gap = 4 } = options;\n // Fix `el` FIRST, then measure it. Measuring a still-`display:block` wrapper\n // reports the full body-content width (≈ viewport minus body margins), which\n // collapses the horizontal clamp below and lands the element at the body's left\n // edge. As a fixed, shrink-to-fit box its `width`/`height` are its real size.\n el.style.position = 'fixed';\n el.style.margin = '0';\n const anchorRect = anchor.getBoundingClientRect();\n const elementRect = el.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Vertical: preferred side, flipped only if it overflows and the other side fits.\n const belowTop = anchorRect.bottom + gap;\n const aboveTop = anchorRect.top - gap - elementRect.height;\n let below = placement !== 'top';\n if (below && belowTop + elementRect.height > viewportHeight && aboveTop >= 0)\n below = false;\n else if (\n !below &&\n aboveTop < 0 &&\n belowTop + elementRect.height <= viewportHeight\n )\n below = true;\n\n // Horizontal: align to an anchor edge, then clamp into the viewport.\n let left =\n align === 'end' ? anchorRect.right - elementRect.width : anchorRect.left;\n left = Math.max(0, Math.min(left, viewportWidth - elementRect.width));\n\n // `left`/`top` so far are viewport coordinates. They are only the CSS values\n // too when `el`'s fixed-position containing block is the viewport; an\n // ancestor with a `transform`, `filter`, `perspective`, `contain`, … (say a\n // modal `<dialog>` holding an overlay host slot) captures fixed descendants,\n // so map the coordinates into that box's space.\n const [originX, originY, scaleX, scaleY] = fixedOrigin(el);\n el.style.left = `${(left - originX) / scaleX}px`;\n el.style.top = `${((below ? belowTop : aboveTop) - originY) / scaleY}px`;\n}\n\n/**\n * Where `left: 0; top: 0` actually lands for a fixed-position child of `el`'s\n * parent, plus that containing block's scale — `[x, y, scaleX, scaleY]`, which\n * is `[0, 0, 1, 1]` when the viewport is the containing block. Measured with a\n * 1px probe rather than `el` itself so `el`'s own transform or running entrance\n * animation cannot skew it. The probe is inserted and removed synchronously, so\n * it is never painted. Translation and scale are compensated; a rotated or\n * skewed containing block is not.\n */\nfunction fixedOrigin(el: HTMLElement): [number, number, number, number] {\n const parent = el.parentNode;\n if (!parent) return [0, 0, 1, 1];\n const probe = el.ownerDocument.createElement('div');\n probe.style.cssText =\n 'position:fixed;left:0;top:0;width:1px;height:1px;margin:0;padding:0;border:0';\n parent.insertBefore(probe, el);\n const rect = probe.getBoundingClientRect();\n probe.remove();\n // A zero size (a containing block mid `scale(0)` animation, or a DOM without\n // layout) would divide by zero; treat it as unscaled.\n return [rect.left, rect.top, rect.width || 1, rect.height || 1];\n}\n\n/**\n * Keep `el` positioned against `anchor` (via {@link positionAnchored}) as the page\n * scrolls or resizes. Positions once immediately, then re-runs on `scroll`\n * (capture phase — catches scrolls in any inner container, not just `window`) and\n * `resize`. Returns a disposer that removes the listeners.\n */\nexport function autoReposition(\n el: HTMLElement,\n anchor: Element,\n options: AnchorPositionOptions = {},\n): () => void {\n const reposition = (): void => positionAnchored(el, anchor, options);\n reposition();\n window.addEventListener('scroll', reposition, true);\n window.addEventListener('resize', reposition);\n return () => {\n window.removeEventListener('scroll', reposition, true);\n window.removeEventListener('resize', reposition);\n };\n}\n","/** Anchored popover lifecycle built on the shared overlay transaction. */\nimport { attach } from './attach.js';\nimport {\n type DismissTrigger,\n overlay,\n type OverlayContent,\n type OverlayHandle,\n overlayHost,\n} from './overlay-core.js';\nimport { autoReposition, type PopoverPlacement } from './overlay-position.js';\n\n/** Options for {@link popover}. */\nexport interface PopoverOptions {\n /**\n * Where to append the popover wrapper. Default: when `anchor` sits inside an\n * open modal `<dialog>`, that dialog's `[data-kerf-overlay-host]` element (a\n * dialog kerf opened gets one automatically), so the popover is part of the\n * modal subtree and stays interactive; otherwise `document.body`.\n */\n container?: Element;\n /** Class on the wrapper. Default `'kerf-popover'`. */\n className?: string;\n /** Preferred side of the anchor. Flips to the other side if it would overflow the viewport. Default `'bottom'`. */\n placement?: PopoverPlacement;\n /** Horizontal edge to line up with the anchor: `'start'` (left edges) or `'end'` (right edges). Default `'start'`. */\n align?: 'start' | 'end';\n /** Gap in px between the anchor and the popover. Default `4`. */\n gap?: number;\n /**\n * Which user actions dismiss the popover. Default `['outside']` (a click\n * outside the popover, the anchor exempt). Pass `false` to close only via `close()`.\n */\n dismiss?: DismissTrigger | DismissTrigger[] | false;\n /** Focus behavior on open. Default `false` (non-modal — leave focus alone). */\n initialFocus?: string | boolean;\n /** Extra elements (besides the anchor) whose clicks do NOT count as outside. */\n outsideIgnore?: Element | readonly Element[];\n /** Called on any user-initiated dismissal. */\n onDismiss?: () => void;\n /**\n * Host the popover in the browser top layer (the Popover API — `[popover]` +\n * `showPopover()`) where supported, so it stacks above any `z-index` without a\n * z-index war. Falls back to today's plain `<div>` where unsupported. kerf keeps\n * owning positioning + its own dismiss wiring; the popover is `popover=\"manual\"`.\n * See {@link OverlayOptions.native}. Default `false`.\n */\n native?: boolean;\n}\n\n/**\n * Anchored, non-modal overlay: positions `content` relative to `anchor` (below by\n * default, flipping above if it would overflow, and clamped horizontally to the\n * viewport) and repositions on scroll / resize while open. A thin wrapper over\n * {@link overlay} with non-modal defaults — `trap: false`, `dismiss: ['outside']`,\n * and the anchor added to `outsideIgnore` so the trigger click doesn't self-close.\n * Returns the same {@link OverlayHandle}; `close()` also drops the reposition\n * listeners. `position: fixed` is set inline (you style everything else).\n */\nexport function popover(\n anchor: Element,\n content: OverlayContent,\n options: PopoverOptions = {},\n): OverlayHandle {\n const {\n container,\n className = 'kerf-popover',\n placement = 'bottom',\n align = 'start',\n gap = 4,\n dismiss = ['outside'],\n initialFocus = false,\n outsideIgnore,\n onDismiss,\n native = false,\n } = options;\n\n const extraIgnore =\n outsideIgnore === undefined\n ? []\n : Array.isArray(outsideIgnore)\n ? [...outsideIgnore]\n : [outsideIgnore];\n\n const handle = overlay(content, {\n container: container ?? overlayHost(anchor),\n className,\n dismiss,\n trap: false,\n initialFocus,\n onDismiss,\n outsideIgnore: [anchor, ...extraIgnore],\n native,\n });\n\n // Position + keep it glued while open; drop the listeners on close. A throw\n // while positioning (e.g. an anchor whose geometry read fails) is still part\n // of construction: close the just-opened overlay before rethrowing.\n let stopReposition: () => void;\n try {\n stopReposition = autoReposition(handle.el, anchor, {\n placement,\n align,\n gap,\n });\n } catch (error) {\n handle.close();\n throw error;\n }\n void handle.result.then(stopReposition);\n\n // KF-BAVCEV: never outlive the anchor. When it leaves the document (e.g. the\n // modal holding it closes) close the popover as cleanup — not a user\n // dismissal, so no `onDismiss`. A move within the document keeps it open.\n void handle.result.then(attach(anchor, () => handle.close));\n\n return handle;\n}\n","/**\n * `toast()` for `kerfjs/overlay` — a non-modal, auto-dismissing notification that\n * stacks in a shared body-level region. Split out of `overlay.ts` (KF-513) since\n * it's a distinct transient-UI concern from the modal dialogs; re-exported from\n * `overlay.ts` so the public `kerfjs/overlay` surface is unchanged. Structural\n * only — kerf ships no CSS; you style the region / toast / animations.\n */\nimport { type SafeHtml } from './jsx-runtime.js';\nimport { mount, type MountResult } from './mount.js';\nimport { escapeHtml } from './utils/escapeHtml.js';\n\n/** Content for a {@link toast}: an escaped text string, trusted `SafeHtml`, or a render function. */\nexport type ToastContent = string | SafeHtml | (() => MountResult);\n\n/** Accent variant for a {@link toast} — mapped to a `${className}--${variant}` class. */\nexport type ToastVariant = 'info' | 'success' | 'warning';\n\n/** Options for {@link toast}. */\nexport interface ToastOptions {\n /** Where toasts stack. Default: a lazily-created `<div class=\"kerf-toasts\">` on `document.body`. */\n container?: Element;\n /** Class on the toast element. Default `'kerf-toast'`. */\n className?: string;\n /** Auto-dismiss after this many ms. `0` keeps it until dismissed by hand. Default `4000`. */\n duration?: number;\n /** ARIA role. Default `'status'`. */\n role?: string;\n /**\n * `'stack'` (default) shows toasts stacked in the region; `'replace'` dismisses\n * the region's current toast(s) first (collapse-to-latest for a rapid sequence).\n */\n mode?: 'stack' | 'replace';\n /**\n * How `mode: 'replace'` drops the prior toast(s): `'fade'` (default) runs their\n * full exit transition (nice for a STACKING region), or `'instant'` removes them\n * synchronously with no exit — what a single, exactly-centered toast slot wants,\n * so the outgoing and incoming messages never cross-fade in the same spot.\n */\n collapse?: 'fade' | 'instant';\n /** Accent variant — adds a `${className}--${variant}` class (kerf ships no CSS; you style it). */\n variant?: ToastVariant;\n /** Class added on the next animation frame after mount, so a CSS **entrance** transition can run. */\n enterClass?: string;\n /**\n * Class added when dismissing, so CSS owns the **exit**. On dismiss the\n * `enterClass` (if any) is also REMOVED, so `exitClass` doesn't have to\n * out-specify it — and a symmetric single-class fade (entrance = add\n * `enterClass`, exit = remove it) works by setting only `enterClass` +\n * `exitDuration`. The node is removed `exitDuration` ms later.\n */\n exitClass?: string;\n /** ms to wait before removing the node on dismiss — applies when `exitClass` is set OR when it's > 0 (to let a removed `enterClass` transition out). Default `0`. */\n exitDuration?: number;\n}\n\n/** Handle returned by {@link toast}. */\nexport interface ToastHandle {\n /** The toast element — inspect it, or run your own entrance/exit transitions. */\n el: HTMLElement;\n /**\n * Dismiss it early. Default runs the `exitClass` transition (removed after\n * `exitDuration`); pass `{ instant: true }` to remove it **synchronously** with\n * no exit — for an action button that immediately shows a replacement toast in a\n * single centered slot (no cross-fade). Idempotent.\n */\n dismiss(options?: { instant?: boolean }): void;\n}\n\n/** The region's active toasts live on the region element (in the DOM), not in module state. */\nconst TOAST_SET = Symbol('kerf.toasts');\n/** A dismiss function with an `.removeNow()` for instant (no-exit) teardown. */\ntype Dismisser = (() => void) & { removeNow: () => void };\ntype ToastCarrier = Element & { [TOAST_SET]?: Set<Dismisser> };\n\n/** The singleton toast region lives in the DOM (queried, not held in a module variable). */\nfunction toastRegion(container?: Element): Element {\n if (container !== undefined) return container;\n const existing = document.querySelector('.kerf-toasts');\n if (existing !== null) return existing;\n const region = document.createElement('div');\n region.className = 'kerf-toasts';\n region.setAttribute('aria-live', 'polite');\n document.body.appendChild(region);\n return region;\n}\n\n/**\n * Show a non-modal, auto-dismissing notification. Stacks in a shared body-level\n * region (or your `container`). Returns a {@link ToastHandle} (`{ el, dismiss }`)\n * so you can run entrance/exit transitions, wire an action button, or inspect the\n * node. `mode: 'replace'` collapses a rapid sequence to the latest; `variant`\n * adds an accent class; `enterClass`/`exitClass` let CSS own the animation.\n */\nexport function toast(\n content: ToastContent,\n options: ToastOptions = {},\n): ToastHandle {\n const {\n container,\n className = 'kerf-toast',\n duration = 4000,\n role = 'status',\n mode = 'stack',\n collapse = 'fade',\n variant,\n enterClass,\n exitClass,\n exitDuration = 0,\n } = options;\n\n const region = toastRegion(container) as ToastCarrier;\n const active = (region[TOAST_SET] ??= new Set<Dismisser>());\n // collapse-to-latest: 'instant' removes priors synchronously (no cross-fade in a\n // centered single slot); 'fade' runs their exit transition (nice for a stack).\n if (mode === 'replace') {\n for (const d of [...active]) {\n if (collapse === 'instant') d.removeNow();\n else d();\n }\n }\n\n const el = document.createElement('div');\n el.className = className;\n if (variant !== undefined) el.classList.add(`${className}--${variant}`);\n el.setAttribute('role', role);\n region.appendChild(el);\n\n const render =\n typeof content === 'function'\n ? content\n : () => (typeof content === 'string' ? escapeHtml(content) : content);\n const disposeMount = mount(el, render);\n const state: {\n dismissed: boolean;\n removed: boolean;\n timer: ReturnType<typeof setTimeout> | undefined;\n exitTimer: ReturnType<typeof setTimeout> | undefined;\n } = {\n dismissed: false,\n removed: false,\n timer: undefined,\n exitTimer: undefined,\n };\n\n if (enterClass !== undefined) {\n globalThis.requestAnimationFrame(() => {\n if (!state.dismissed) el.classList.add(enterClass);\n });\n }\n\n const remove = (): void => {\n if (state.removed) return;\n state.removed = true;\n state.dismissed = true; // once removed, a later dismiss() is a clean no-op\n if (state.exitTimer !== undefined) clearTimeout(state.exitTimer);\n disposeMount();\n el.remove();\n active.delete(dismiss as Dismisser);\n };\n\n // Force synchronous teardown NOW, with no exit transition — even if a fade is\n // already in flight (so `mode:'replace'` collapse can clean up a mid-exit toast,\n // and `dismiss({ instant: true })` drops it immediately).\n const removeNow = (): void => {\n if (state.timer !== undefined) clearTimeout(state.timer);\n remove();\n };\n\n const fadeOut = (): void => {\n if (state.dismissed) return;\n state.dismissed = true;\n if (state.timer !== undefined) clearTimeout(state.timer);\n // Reverse the entrance (drop enterClass so exitClass needn't out-specify it),\n // add exitClass, and delay removal for the transition — including the\n // single-class idiom (enterClass removed + exitDuration, no exitClass).\n if (enterClass !== undefined) el.classList.remove(enterClass);\n if (exitClass !== undefined) el.classList.add(exitClass);\n if (exitClass !== undefined || exitDuration > 0) {\n state.exitTimer = setTimeout(remove, exitDuration);\n } else {\n remove();\n }\n };\n\n function dismiss(options?: { instant?: boolean }): void {\n if (options?.instant === true) removeNow();\n else fadeOut();\n }\n (dismiss as Dismisser).removeNow = removeNow;\n\n active.add(dismiss as Dismisser);\n if (duration > 0) state.timer = setTimeout(fadeOut, duration);\n return { el, dismiss };\n}\n","/** Hover and focus tooltip lifecycle built on the shared overlay transaction. */\nimport { attach } from './attach.js';\nimport { jsx, type SafeHtml } from './jsx-runtime.js';\nimport type { MountResult } from './mount.js';\nimport {\n overlay,\n type OverlayContent,\n type OverlayHandle,\n overlayHost,\n} from './overlay-core.js';\nimport {\n type AnchorPositionOptions,\n autoReposition,\n} from './overlay-position.js';\n\n/** Content for a {@link tooltip}: text (auto-escaped), `SafeHtml`, or a render function. */\nexport type TooltipContent = string | SafeHtml | (() => MountResult);\n\n/** Options for {@link tooltip}. */\nexport interface TooltipOptions extends AnchorPositionOptions {\n /** Where to append the tooltip wrapper. Default: the anchor's modal-dialog host slot (see {@link PopoverOptions.container}), else `document.body`. */\n container?: Element;\n /** Class on the wrapper. Default `'kerf-tooltip'`. */\n className?: string;\n /** Delay in ms before showing after hover/focus enters. Default `400`. */\n delay?: number;\n /** Delay in ms before hiding after hover/focus leaves. Default `100`. */\n hideDelay?: number;\n /** ARIA role on the wrapper. Default `'tooltip'`. */\n role?: string;\n /** Host the tooltip in the browser top layer (the Popover API) where supported. See {@link OverlayOptions.native}. Default `false`. */\n native?: boolean;\n}\n\n/**\n * A hover/focus-triggered, non-modal, auto-hiding tooltip anchored to `anchor`.\n * Shows after `delay` on `pointerenter`/`focus`, hides after `hideDelay` on\n * `pointerleave`/`blur`, and positions itself with {@link autoReposition} (above\n * the anchor by default). Unlike {@link popover} there is no click-dismiss model —\n * it follows the pointer/focus. Returns a disposer that removes the anchor\n * listeners and hides any shown tooltip. Structural only (kerf ships no CSS).\n */\nexport function tooltip(\n anchor: Element,\n content: TooltipContent,\n options: TooltipOptions = {},\n): () => void {\n const {\n container,\n className = 'kerf-tooltip',\n delay = 400,\n hideDelay = 100,\n role = 'tooltip',\n placement = 'top',\n align = 'start',\n gap = 4,\n native = false,\n } = options;\n\n const body: OverlayContent =\n typeof content === 'function'\n ? content\n : typeof content === 'string'\n ? jsx('span', { class: `${className}__text`, children: content })\n : content;\n\n const timers: {\n show?: ReturnType<typeof setTimeout>;\n hide?: ReturnType<typeof setTimeout>;\n } = {};\n let current:\n | { handle: OverlayHandle; stop: () => void; unwatch: () => void }\n | undefined;\n let presence = 0;\n\n // Runs from the `delay` timer, so there is no caller to throw to. A failed\n // show (a throwing render fn, `native` `showPopover()`, or positioning) is\n // rolled back before `current` is set — nothing stays on screen and the\n // next pointerenter / focus schedules a fresh attempt — and the original\n // error then escapes the timer callback for the host to report as uncaught\n // (a window `error` event in browsers), the same way kerf's other deferred\n // callbacks (debounce / throttle timers, attach teardown) surface errors.\n function show(): void {\n // The anchor left the document while the show was pending (KF-BAVCEV).\n if (!anchor.isConnected) return;\n const handle = overlay(body, {\n container: container ?? overlayHost(anchor),\n className,\n dismiss: false,\n trap: false,\n initialFocus: false,\n native,\n });\n handle.el.setAttribute('role', role);\n let stop: () => void;\n try {\n stop = autoReposition(handle.el, anchor, { placement, align, gap });\n } catch (error) {\n // Not yet tracked in `current`, so `hide()` could never reach it.\n handle.close();\n throw error;\n }\n // KF-BAVCEV: an anchor removed from the document (e.g. with the modal that\n // held it) fires no pointerleave / blur, so hide when it leaves and forget\n // its presence; a move within the document keeps the tooltip shown.\n const unwatch = attach(anchor, () => () => {\n presence = 0;\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n hide();\n });\n current = { handle, stop, unwatch };\n // A surface that closed itself (its host slot left the document with the\n // dialog) must not stay `current`, or the next hover would never show.\n void handle.result.then(() => {\n if (current?.handle === handle) hide();\n });\n }\n\n function hide(): void {\n const shown = current;\n if (shown === undefined) return;\n // Cleared first: `unwatch()` runs the anchor teardown, which re-enters here.\n current = undefined;\n shown.unwatch();\n shown.stop();\n shown.handle.close();\n }\n\n const onEnter = (event: Event): void => {\n presence |= event.type === 'focus' ? 2 : 1;\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n if (current !== undefined) return;\n if (timers.show !== undefined) clearTimeout(timers.show); // debounce: one pending show at a time\n timers.show = setTimeout(show, delay);\n };\n const onLeave = (event: Event): void => {\n presence &= event.type === 'blur' ? ~2 : ~1;\n if (presence) return;\n if (timers.show !== undefined) clearTimeout(timers.show);\n if (current === undefined) return;\n timers.hide = setTimeout(hide, hideDelay);\n };\n\n anchor.addEventListener('pointerenter', onEnter);\n anchor.addEventListener('pointerleave', onLeave);\n anchor.addEventListener('focus', onEnter);\n anchor.addEventListener('blur', onLeave);\n\n return () => {\n anchor.removeEventListener('pointerenter', onEnter);\n anchor.removeEventListener('pointerleave', onLeave);\n anchor.removeEventListener('focus', onEnter);\n anchor.removeEventListener('blur', onLeave);\n if (timers.show !== undefined) clearTimeout(timers.show);\n if (timers.hide !== undefined) clearTimeout(timers.hide);\n hide();\n };\n}\n"]}
package/llms.txt CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A tiny (~13 KB minified + gzipped including its one runtime dependency `@preact/signals-core`; still ~13 KB with `arraySignal`) reactive UI framework — fine-grained signals + DOM morphing + JSX. No virtual DOM, no compiler. Apply the smallest possible cut to update your DOM.
4
4
 
5
- kerf renders JSX to a structured `SafeHtml` (string for static content; tagged "list"/"mixed" segments where `each(...)` was used) and reconciles it against the live tree with a custom segment-aware morph. Static surrounds go through a general-purpose tree-morph; list contents go through a keyed reconciler that operates directly on live children. Snapshot reconciliation scans O(rows) but limits rendering and DOM mutations to cache misses and structural changes; eligible `arraySignal` patch delivery runs in O(patches). Reactivity is provided by [@preact/signals-core](https://github.com/preactjs/signals). It pairs well with server-rendered HTML, embedded widgets, and any UI where preserving focus / selection across re-renders matters. Public API is one import: `signal`, `computed`, `effect`, `batch`, `defineStore`, `resetAllStores`, `mount`, `morph`, `each`, `attr`, `delegate`, `delegateCapture`, `toElement`, `renderDocument`, `SafeHtml`, `isSafeHtml`, `raw`, `Fragment`. (Two more subpaths: `kerfjs/testing` exposes `clearStoreRegistry` for unit-test isolation; `kerfjs/jsx-runtime` exposes the typed JSX building blocks for declaration-merging custom-element types.) An optional subpath at `kerfjs/array-signal` adds `arraySignal()` — a granular keyed-list signal whose patch events let `each()` reconcile in O(patches) instead of O(N). An optional subpath at `kerfjs/dev` installs the development diagnostics — kerf does NOT infer dev mode, so you import it behind your own build's dev flag (`if (import.meta.env.DEV) await import('kerfjs/dev');`); omitting it is production and sheds ~4.7 KB min+gzip. Another optional subpath at `kerfjs/html` adds the `html` tagged template — JSX-identical runtime semantics with no JSX transform, so CDN/importmap projects can author kerf UIs with literally no build step. A family of optional, tree-shakeable **companion-utility** subpaths cover patterns real apps hand-roll: `kerfjs/list` (`bindList` — a keyed list with per-row fine-grained mounts and fixed / declared / measured-height viewport virtualization, plus `observeRowHeights`), `kerfjs/router` (`createRouter` — the opt-in "postcard router": route matching + `navigate` + `<a>` link interception + a keyed outlet, core stays router-free), `kerfjs/overlay` (`overlay` / `confirm` / `prompt` / `form` / `choice` / `popover` / `tooltip` / `toast` + `positionAnchored` / `autoReposition`; `native: true` top-layer backing via `<dialog>` / the Popover API applies to the seven overlay/dialog/popover/tooltip surfaces), `kerfjs/scope` (`disposeScope` / `disposeSubtree` / `observeRemovals`), `kerfjs/async` (`resource` async-state with a stale-response guard + SWR cache), `kerfjs/timing` (`debounce` / `throttle` / `debouncedSignal`), `kerfjs/remount` (`remountOn` — key-driven wholesale subtree replacement), `kerfjs/attach` (`attach` — bind a non-kerf widget's lifecycle to one node), and `kerfjs/actions` (`action` / `delegateActions` — the delegated `data-action` table idiom).
5
+ kerf renders JSX to a structured `SafeHtml` (string for static content; tagged "list"/"mixed" segments where `each(...)` was used) and reconciles it against the live tree with a custom segment-aware morph. Static surrounds go through a general-purpose tree-morph; list contents go through a keyed reconciler that operates directly on live children. Snapshot reconciliation scans O(rows) but limits rendering and DOM mutations to cache misses and structural changes; eligible `arraySignal` patch delivery runs in O(patches). Reactivity is provided by [@preact/signals-core](https://github.com/preactjs/signals). It pairs well with server-rendered HTML, embedded widgets, and any UI where preserving focus / selection across re-renders matters. Public API is one import: `signal`, `computed`, `effect`, `batch`, `defineStore`, `resetAllStores`, `mount`, `morph`, `each`, `attr`, `delegate`, `delegateCapture`, `toElement`, `renderDocument`, `SafeHtml`, `isSafeHtml`, `raw`, `Fragment`. (Two more subpaths: `kerfjs/testing` exposes `clearStoreRegistry` for unit-test isolation; `kerfjs/jsx-runtime` exposes the typed JSX building blocks for declaration-merging custom-element types.) An optional subpath at `kerfjs/array-signal` adds `arraySignal()` — a granular keyed-list signal whose patch events let `each()` reconcile in O(patches) instead of O(N). An optional subpath at `kerfjs/dev` installs the development diagnostics — kerf does NOT infer dev mode, so you import it behind your own build's dev flag (`if (import.meta.env.DEV) await import('kerfjs/dev');`); omitting it is production and sheds ~4.7 KB min+gzip. Another optional subpath at `kerfjs/html` adds the `html` tagged template — JSX-identical runtime semantics with no JSX transform, so CDN/importmap projects can author kerf UIs with literally no build step. A family of optional, tree-shakeable **companion-utility** subpaths cover patterns real apps hand-roll: `kerfjs/list` (`bindList` — a keyed list with per-row fine-grained mounts and fixed / declared / measured-height viewport virtualization, plus `observeRowHeights`), `kerfjs/router` (`createRouter` — the opt-in "postcard router": route matching + `navigate` + `<a>` link interception + a keyed outlet, core stays router-free), `kerfjs/overlay` (`overlay` / `confirm` / `prompt` / `form` / `choice` / `popover` / `tooltip` / `toast` + `positionAnchored` / `autoReposition`; `native: true` top-layer backing via `<dialog>` / the Popover API applies to the seven overlay/dialog/popover/tooltip surfaces), `kerfjs/scope` (`createScope` / `disposeScope` / `disposeSubtree` / `observeRemovals`), `kerfjs/async` (`resource` async-state with a stale-response guard + SWR cache), `kerfjs/timing` (`debounce` / `throttle` / `debouncedSignal`), `kerfjs/remount` (`remountOn` — key-driven wholesale subtree replacement), `kerfjs/attach` (`attach` — bind a non-kerf widget's lifecycle to one node), and `kerfjs/actions` (`action` / `delegateActions` — the delegated `data-action` table idiom).
6
6
 
7
7
  ## For humans new to the codebase
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kerfjs",
3
- "version": "5.0.0-beta.77",
3
+ "version": "5.0.0-beta.79",
4
4
  "description": "Tiny reactive UI framework — fine-grained signals + DOM morphing + JSX. Apply the smallest possible cut to update your DOM.",
5
5
  "type": "module",
6
6
  "sideEffects": [