@fuzdev/fuz_ui 0.202.0 → 0.203.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/ApiIndex.svelte +6 -3
  2. package/dist/ApiIndex.svelte.d.ts +1 -1
  3. package/dist/ApiIndex.svelte.d.ts.map +1 -1
  4. package/dist/ApiModule.svelte +72 -21
  5. package/dist/ApiModule.svelte.d.ts +1 -1
  6. package/dist/ApiModule.svelte.d.ts.map +1 -1
  7. package/dist/ContextmenuEntry.svelte +11 -10
  8. package/dist/ContextmenuEntry.svelte.d.ts +1 -1
  9. package/dist/ContextmenuEntry.svelte.d.ts.map +1 -1
  10. package/dist/ContextmenuLinkEntry.svelte +30 -12
  11. package/dist/ContextmenuLinkEntry.svelte.d.ts +2 -1
  12. package/dist/ContextmenuLinkEntry.svelte.d.ts.map +1 -1
  13. package/dist/ContextmenuMenu.svelte +207 -0
  14. package/dist/ContextmenuMenu.svelte.d.ts +41 -0
  15. package/dist/ContextmenuMenu.svelte.d.ts.map +1 -0
  16. package/dist/ContextmenuRoot.svelte +58 -260
  17. package/dist/ContextmenuRoot.svelte.d.ts +2 -60
  18. package/dist/ContextmenuRoot.svelte.d.ts.map +1 -1
  19. package/dist/ContextmenuRootForSafariCompatibility.svelte +72 -283
  20. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts +2 -58
  21. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts.map +1 -1
  22. package/dist/ContextmenuSeparator.svelte +2 -1
  23. package/dist/ContextmenuSeparator.svelte.d.ts.map +1 -1
  24. package/dist/ContextmenuSubmenu.svelte +27 -23
  25. package/dist/ContextmenuSubmenu.svelte.d.ts +1 -1
  26. package/dist/ContextmenuSubmenu.svelte.d.ts.map +1 -1
  27. package/dist/ContextmenuTextEntry.svelte +7 -3
  28. package/dist/ContextmenuTextEntry.svelte.d.ts +2 -1
  29. package/dist/ContextmenuTextEntry.svelte.d.ts.map +1 -1
  30. package/dist/DeclarationLink.svelte +15 -2
  31. package/dist/DeclarationLink.svelte.d.ts +7 -0
  32. package/dist/DeclarationLink.svelte.d.ts.map +1 -1
  33. package/dist/DocsLink.svelte +3 -1
  34. package/dist/DocsLink.svelte.d.ts.map +1 -1
  35. package/dist/DocsTertiaryNav.svelte +2 -1
  36. package/dist/DocsTertiaryNav.svelte.d.ts.map +1 -1
  37. package/dist/LibraryDetail.svelte +9 -3
  38. package/dist/LibraryDetail.svelte.d.ts +1 -1
  39. package/dist/LibraryDetail.svelte.d.ts.map +1 -1
  40. package/dist/ModuleLink.svelte +2 -1
  41. package/dist/ModuleLink.svelte.d.ts.map +1 -1
  42. package/dist/TypeLink.svelte +2 -1
  43. package/dist/TypeLink.svelte.d.ts.map +1 -1
  44. package/dist/contextmenu_helpers.d.ts +324 -1
  45. package/dist/contextmenu_helpers.d.ts.map +1 -1
  46. package/dist/contextmenu_helpers.js +403 -2
  47. package/dist/contextmenu_state.svelte.d.ts +61 -15
  48. package/dist/contextmenu_state.svelte.d.ts.map +1 -1
  49. package/dist/contextmenu_state.svelte.js +206 -119
  50. package/dist/declaration.svelte.d.ts +1 -0
  51. package/dist/declaration.svelte.d.ts.map +1 -1
  52. package/dist/declaration.svelte.js +2 -1
  53. package/dist/icons.d.ts +15 -3
  54. package/dist/icons.d.ts.map +1 -1
  55. package/dist/icons.js +17 -3
  56. package/dist/library.svelte.d.ts +30 -3
  57. package/dist/library.svelte.d.ts.map +1 -1
  58. package/dist/library.svelte.js +38 -0
  59. package/dist/module.svelte.d.ts +62 -1
  60. package/dist/module.svelte.d.ts.map +1 -1
  61. package/dist/module.svelte.js +71 -1
  62. package/package.json +2 -2
  63. package/src/lib/contextmenu_helpers.ts +546 -3
  64. package/src/lib/contextmenu_state.svelte.ts +219 -119
  65. package/src/lib/declaration.svelte.ts +2 -1
  66. package/src/lib/icons.ts +19 -3
  67. package/src/lib/library.svelte.ts +43 -1
  68. package/src/lib/module.svelte.ts +97 -2
@@ -1,4 +1,6 @@
1
1
  import { is_editable, swallow, inside_editable } from '@fuzdev/fuz_util/dom.js';
2
+ import { EMPTY_OBJECT } from '@fuzdev/fuz_util/object.js';
3
+ import { contextmenu_open, } from './contextmenu_state.svelte.js';
2
4
  // Constants for default prop values
3
5
  export const CONTEXTMENU_DEFAULT_OPEN_OFFSET_X = -2;
4
6
  export const CONTEXTMENU_DEFAULT_OPEN_OFFSET_Y = -2;
@@ -33,5 +35,404 @@ export const contextmenu_create_keydown_handler = (keyboard_handlers) => (e) =>
33
35
  swallow(e);
34
36
  handler();
35
37
  };
36
- export const contextmenu_calculate_constrained_x = (menu_x, menu_width, layout_width) => menu_x + Math.min(0, layout_width - (menu_x + menu_width));
37
- export const contextmenu_calculate_constrained_y = (menu_y, menu_height, layout_height) => menu_y + Math.min(0, layout_height - (menu_y + menu_height));
38
+ /**
39
+ * Constrains the menu's x coordinate to the layout, shifting left to fit the right edge.
40
+ * Clamps at `0` so a menu wider than the layout pins its left edge - the start of each
41
+ * item stays visible.
42
+ */
43
+ export const contextmenu_calculate_constrained_x = (menu_x, menu_width, layout_width) => Math.max(0, menu_x + Math.min(0, layout_width - (menu_x + menu_width)));
44
+ /**
45
+ * Constrains the menu's y coordinate to the layout, shifting up to fit the bottom edge.
46
+ * Clamps at `0` so a menu taller than the layout pins its top edge - the first
47
+ * items stay visible.
48
+ */
49
+ export const contextmenu_calculate_constrained_y = (menu_y, menu_height, layout_height) => Math.max(0, menu_y + Math.min(0, layout_height - (menu_y + menu_height)));
50
+ /**
51
+ * Calculates a submenu flyout's translation so it fits the layout.
52
+ *
53
+ * Preference order on the x axis: fly out to the right of the parent menu,
54
+ * else flip fully to the left of it, else shift to pin whichever side
55
+ * overflows less. The y axis shifts up only as far as needed to fit the
56
+ * bottom edge.
57
+ *
58
+ * Used by `ContextmenuSubmenu.svelte`.
59
+ */
60
+ export const contextmenu_calculate_submenu_translate = (options) => {
61
+ const { base_x, base_y, width, height, parent_width, layout_width, layout_height } = options;
62
+ let x;
63
+ const overflow_right = base_x + width + parent_width - layout_width;
64
+ if (overflow_right <= 0) {
65
+ x = parent_width;
66
+ }
67
+ else {
68
+ const overflow_left = width - base_x;
69
+ if (overflow_left <= 0) {
70
+ x = -width;
71
+ }
72
+ else if (overflow_left > overflow_right) {
73
+ x = parent_width - overflow_right;
74
+ }
75
+ else {
76
+ x = overflow_left - width;
77
+ }
78
+ }
79
+ const y = Math.min(0, layout_height - (base_y + height));
80
+ return { x, y };
81
+ };
82
+ /**
83
+ * Handles a `contextmenu` event by opening the contextmenu from the event target,
84
+ * unless the target is invalid or inside the open menu element.
85
+ * Swallows the event when the menu opens.
86
+ *
87
+ * @param e - the `contextmenu` event
88
+ * @param contextmenu - the contextmenu state
89
+ * @param menu_el - the open menu element, if any, so events inside it are ignored
90
+ * @param options - offsets and entry filtering forwarded to `contextmenu_open`
91
+ * @returns whether the contextmenu was opened
92
+ */
93
+ export const contextmenu_open_from_event = (e, contextmenu, menu_el, options) => {
94
+ const { open_offset_x = CONTEXTMENU_DEFAULT_OPEN_OFFSET_X, open_offset_y = CONTEXTMENU_DEFAULT_OPEN_OFFSET_Y, } = options ?? EMPTY_OBJECT;
95
+ const { target } = e;
96
+ if (!contextmenu_is_valid_target(target, e.shiftKey))
97
+ return false;
98
+ // don't open the contextmenu when clicking on the menu itself
99
+ if (menu_el?.contains(target))
100
+ return false;
101
+ if (!contextmenu_open(target, e.clientX + open_offset_x, e.clientY + open_offset_y, contextmenu, options)) {
102
+ return false;
103
+ }
104
+ swallow(e);
105
+ return true;
106
+ };
107
+ /**
108
+ * Resolves a `contextmenu` event: opens the menu from the event target when possible
109
+ * (arming `open_guard` against the gesture's residual events), otherwise lets the
110
+ * native contextmenu show - closing ours unless the press was on the menu itself.
111
+ *
112
+ * Shared by `ContextmenuRoot.svelte` and `ContextmenuRootForSafariCompatibility.svelte`,
113
+ * after their root-specific bypass and longpress handling.
114
+ *
115
+ * @param e - the `contextmenu` event
116
+ * @param contextmenu - the contextmenu state
117
+ * @param menu_el - the open menu element, if any
118
+ * @param open_guard - guard that identifies presses belonging to the gesture that opened the menu
119
+ * @param options - offsets and entry filtering forwarded to `contextmenu_open`
120
+ * @returns whether the contextmenu was opened
121
+ */
122
+ export const contextmenu_resolve_contextmenu_event = (e, contextmenu, menu_el, open_guard, options) => {
123
+ if (contextmenu_open_from_event(e, contextmenu, menu_el, options)) {
124
+ // guard the menu from the residual events of the gesture that opened it
125
+ open_guard.opened();
126
+ return true;
127
+ }
128
+ // The right-click didn't (re)open the menu - a press on the menu itself, an invalid
129
+ // target, shift bypass, or no entries - so the native contextmenu shows.
130
+ if (contextmenu.opened && menu_el && !menu_el.contains(e.target)) {
131
+ // Close ours and let the native contextmenu show. Unmodified secondary-button
132
+ // presses never close via the mousedown handler; this is where their gesture
133
+ // resolves (shift+rightclick closes on the press - Firefox suppresses its
134
+ // `contextmenu` event entirely).
135
+ contextmenu.close();
136
+ }
137
+ return false;
138
+ };
139
+ /**
140
+ * Creates a `mousedown` handler that closes the contextmenu when pressing outside of
141
+ * the menu element, deferring to `open_guard` for presses that belong to the gesture
142
+ * that opened the menu: gesture presses outside don't close, and gesture presses on the
143
+ * menu arm the click blocker instead of activating the entry under the pointer.
144
+ *
145
+ * Secondary-button presses outside the menu never close here - their own `contextmenu`
146
+ * event resolves the menu in the roots' handlers (reopening it elsewhere, or closing it
147
+ * when there's nothing to open) - with one exception: shift+rightclick, an explicit
148
+ * native-menu request whose `contextmenu` event Firefox suppresses entirely, closes on
149
+ * the press itself.
150
+ *
151
+ * Registered on the window during the bubble phase deliberately -
152
+ * consumers keep the menu open through a press by swallowing the event
153
+ * (e.g. menu controller buttons that use `onmousedowncapture` + `swallow`).
154
+ *
155
+ * @param contextmenu - the contextmenu state
156
+ * @param get_menu_el - getter for the open menu element, if any
157
+ * @param open_guard - guard that identifies presses belonging to the gesture that opened the menu
158
+ */
159
+ // TODO consider `popover="auto"` instead of `"manual"` (see `contextmenu_popover_attachment`) -
160
+ // its light dismiss would replace this handler and fix Escape ordering over dialogs
161
+ // via close watchers, but it would break consumers that swallow `mousedown` to keep
162
+ // the menu open through presses on their own controls
163
+ export const contextmenu_create_mousedown_handler = (contextmenu, get_menu_el, open_guard) => (e) => {
164
+ const menu_el = get_menu_el();
165
+ if (!menu_el)
166
+ return;
167
+ if (menu_el.contains(e.target)) {
168
+ // a press on the menu belonging to the opening gesture must not click-activate
169
+ open_guard?.mousedown_on_menu(e);
170
+ return;
171
+ }
172
+ // A shift+rightclick is an explicit native-menu request that our handlers may
173
+ // never see resolve - Firefox suppresses its `contextmenu` event entirely - so
174
+ // close on the press itself, matching the unsuppressed outcome in other browsers.
175
+ if (e.button === 2 && e.shiftKey) {
176
+ contextmenu.close();
177
+ return;
178
+ }
179
+ // Presses belonging to the opening gesture must not close the menu. This includes
180
+ // all secondary-button presses - their own `contextmenu` event resolves the menu
181
+ // (reopening it elsewhere, or closing it when there's nothing to open).
182
+ if (open_guard?.press_belongs_to_open_gesture(e))
183
+ return;
184
+ contextmenu.close();
185
+ };
186
+ /**
187
+ * Resolves the element that must host the contextmenu popover for it to stay
188
+ * interactive: the modal `<dialog>` containing `target`, if any.
189
+ *
190
+ * A modal dialog makes every element outside its subtree inert, and the top layer
191
+ * fixes painting order, not inertness - so a popover shown from outside the dialog
192
+ * paints above it but receives no pointer or focus events (hit-testing skips inert
193
+ * elements). Only the topmost modal dialog's subtree is interactive, so the dialog
194
+ * containing the menu's open target is by construction the one the menu must join.
195
+ *
196
+ * @param target - the element the menu was opened from
197
+ * @returns the modal dialog to reparent the menu into, or `null` when the menu
198
+ * doesn't need a host
199
+ */
200
+ export const contextmenu_resolve_popover_host = (target) => target?.closest('dialog:modal') ?? null;
201
+ /**
202
+ * Creates an attachment that shows the contextmenu element as a manual popover,
203
+ * promoting it into the top layer so it paints above modal `<dialog>` elements
204
+ * (e.g. `Dialog.svelte`) - top-layer elements paint in insertion order.
205
+ *
206
+ * Painting is only half of it: a modal dialog also makes everything outside its
207
+ * subtree inert. When the menu opens from inside a modal dialog, the menu element
208
+ * is reparented into that dialog (see `contextmenu_resolve_popover_host`) so it
209
+ * escapes the inert-ness and stays interactive - top-layer positioning is relative
210
+ * to the viewport regardless of ancestors, so the menu's fixed coordinates are
211
+ * unaffected. The host dialog's `close` also closes the menu, since the menu's DOM
212
+ * node vanishes with the dialog.
213
+ *
214
+ * No-ops where the Popover API is unavailable (older browsers, jsdom),
215
+ * falling back to `--contextmenu_z_index` stacking - the menu then renders
216
+ * beneath and inert to any open modal dialog.
217
+ *
218
+ * Used with the `popover="manual"` attribute - `"manual"` rather than `"auto"`
219
+ * so opening, closing, and keyboard handling stay fully owned by `ContextmenuState`.
220
+ */
221
+ export const contextmenu_popover_attachment = (contextmenu) => (el) => {
222
+ if (!el.showPopover)
223
+ return;
224
+ const host = contextmenu_resolve_popover_host(contextmenu.target);
225
+ // reparent before showing - moving a shown popover would hide it
226
+ if (host)
227
+ host.appendChild(el);
228
+ // guard the reactive re-run when the `contextmenu` prop changes identity -
229
+ // `showPopover()` throws on an already-shown popover
230
+ if (!el.matches(':popover-open'))
231
+ el.showPopover();
232
+ if (!host)
233
+ return;
234
+ const onclose = () => {
235
+ contextmenu.close();
236
+ };
237
+ host.addEventListener('close', onclose);
238
+ return () => {
239
+ host.removeEventListener('close', onclose);
240
+ };
241
+ };
242
+ /**
243
+ * Guards the menu from the residual events of the gesture that opened it,
244
+ * using exact gesture causality - no timing heuristics or tunable windows.
245
+ *
246
+ * Touch: when the menu opens during a touch (the native longpress `contextmenu` event,
247
+ * or the Safari-compat custom longpress), the release of that same gesture must not
248
+ * interact with the menu - an unprevented `touchend` lets the browser synthesize
249
+ * compatibility mouse events (`mousedown`/`mouseup`/`click`) at the touch point, and the
250
+ * open offsets place the first menu item exactly there, activating it immediately.
251
+ * `touchend` swallows the release to stop the synthesis, and `consume_blocked_click`
252
+ * blocks the next click on the menu as belt and braces (iOS can synthesize the click
253
+ * regardless).
254
+ *
255
+ * Mouse: tap-style input devices (e.g. some touchpads) can register an overlapping
256
+ * primary-button press during the right-click gesture that opened the menu - the
257
+ * compositor serializes the event stream, but the press's hardware `timeStamp` falls
258
+ * inside the gesture, and its delivery can lag long after the menu opened. Because the
259
+ * open offsets place the first menu item under the pointer, that press's `click` would
260
+ * activate the entry. `press_belongs_to_open_gesture` identifies overlap presses
261
+ * exactly: the press's own `buttons` bitmask shows the secondary button still down
262
+ * at generation time, or its `timeStamp` predates the release tracked by
263
+ * `track_mouseup`. No pressed-state is tracked across events deliberately: the native
264
+ * contextmenu's pointer grab swallows the secondary `mouseup` whenever it opens
265
+ * (right-click on our menu, shift+rightclick - which in Firefox doesn't even fire
266
+ * the `contextmenu` event), so a tracked flag wedges stuck, while the judged press's
267
+ * own `buttons` self-corrects. A deliberate right-then-left click - however fast -
268
+ * is sequential in hardware time and is never blocked.
269
+ *
270
+ * Plain DOM-event bookkeeping with no reactive state - used only inside event handlers
271
+ * by `ContextmenuRoot.svelte` and `ContextmenuRootForSafariCompatibility.svelte`.
272
+ */
273
+ export class ContextmenuOpenGuard {
274
+ #touch_active = false;
275
+ #opened_by_touch = false;
276
+ #block_next_click = false;
277
+ #last_secondary_up_time = -Infinity;
278
+ #last_touch_end_time = -Infinity;
279
+ /**
280
+ * Begins a new gesture on `touchstart`, clearing stale flags from the previous one.
281
+ */
282
+ touchstart() {
283
+ this.#touch_active = true;
284
+ this.#opened_by_touch = false;
285
+ this.#block_next_click = false;
286
+ }
287
+ /**
288
+ * Arms the touch release guard for the gesture that just opened the menu.
289
+ * Call after a successful open.
290
+ */
291
+ opened() {
292
+ if (this.#touch_active)
293
+ this.#opened_by_touch = true;
294
+ }
295
+ /**
296
+ * Tracks the physical secondary button's release - call from an always-on
297
+ * window `mouseup` capture listener. The release may never be delivered
298
+ * (the native contextmenu's pointer grab eats it), which is why
299
+ * `press_belongs_to_open_gesture` never depends on it alone.
300
+ */
301
+ track_mouseup(e) {
302
+ if (e.button === 2) {
303
+ this.#last_secondary_up_time = e.timeStamp;
304
+ }
305
+ }
306
+ /**
307
+ * Returns `true` when a press belongs to the gesture that opened the menu
308
+ * rather than being a deliberate response to it:
309
+ * secondary-button presses (their own `contextmenu` event resolves them),
310
+ * presses during or predating an active touch (synthesized compatibility events),
311
+ * and presses overlapping the secondary button in hardware time - the press's
312
+ * own `buttons` bitmask shows the secondary button still down at generation
313
+ * time, or its `timeStamp` predates the release tracked by `track_mouseup`.
314
+ */
315
+ press_belongs_to_open_gesture(e) {
316
+ if (e.button === 2)
317
+ return true;
318
+ if (this.#touch_active || e.timeStamp <= this.#last_touch_end_time)
319
+ return true;
320
+ return (e.buttons & 2) !== 0 || e.timeStamp <= this.#last_secondary_up_time;
321
+ }
322
+ /**
323
+ * Handles a `mousedown` that landed on the menu element: when a primary-button
324
+ * press belongs to the opening gesture, its `click` is blocked from activating the
325
+ * entry that the open offsets placed under the pointer. Non-primary presses never
326
+ * arm the blocker - they produce no `click`, so an armed blocker would linger and
327
+ * eat the next deliberate click on the menu.
328
+ */
329
+ mousedown_on_menu(e) {
330
+ if (e.button === 0 && this.press_belongs_to_open_gesture(e)) {
331
+ this.#block_next_click = true;
332
+ }
333
+ }
334
+ /**
335
+ * Handles `touchend`: when the release belongs to the gesture that opened the menu,
336
+ * swallows it (stopping mouse event synthesis) and arms the click blocker,
337
+ * returning `true`.
338
+ */
339
+ touchend(e) {
340
+ this.#touch_active = e.touches.length > 0;
341
+ this.#last_touch_end_time = e.timeStamp;
342
+ if (!this.#opened_by_touch)
343
+ return false;
344
+ this.#opened_by_touch = false;
345
+ swallow(e);
346
+ this.#block_next_click = true;
347
+ return true;
348
+ }
349
+ /**
350
+ * Clears gesture state, including any armed click blocker. Call on `touchcancel`.
351
+ * The secondary release timestamp persists - it mirrors hardware history,
352
+ * not gesture state.
353
+ */
354
+ reset() {
355
+ this.#touch_active = false;
356
+ this.#opened_by_touch = false;
357
+ this.#block_next_click = false;
358
+ }
359
+ /**
360
+ * Consumes an armed click blocker, returning `true` if the click should be swallowed.
361
+ * Call from the menu element's `click` capture handler.
362
+ */
363
+ consume_blocked_click() {
364
+ if (!this.#block_next_click)
365
+ return false;
366
+ this.#block_next_click = false;
367
+ return true;
368
+ }
369
+ }
370
+ /**
371
+ * Tracks the tap-then-longpress gesture that bypasses the Fuz contextmenu,
372
+ * letting users reach the system contextmenu by tapping once
373
+ * then longpressing/rightclicking within a time window.
374
+ *
375
+ * Plain DOM-event bookkeeping with no reactive state - used only inside event handlers
376
+ * by `ContextmenuRoot.svelte` and `ContextmenuRootForSafariCompatibility.svelte`.
377
+ */
378
+ export class ContextmenuBypassTracker {
379
+ #first_tap_time = null;
380
+ #touch_x = 0;
381
+ #touch_y = 0;
382
+ #timeout = null;
383
+ /**
384
+ * Set when a tap-then-longpress is detected,
385
+ * telling the next `contextmenu` event handler to let the system contextmenu through.
386
+ */
387
+ bypassed = false;
388
+ /**
389
+ * Records a single-touch `touchstart` at the given coordinates.
390
+ * Detects a tap-then-longpress when the previous tap happened within `bypass_window`
391
+ * milliseconds and moved less than `bypass_move_tolerance` pixels,
392
+ * setting `bypassed` and returning `true`.
393
+ * Otherwise records the tap for future detection and returns `false`.
394
+ */
395
+ track(x, y, bypass_window, bypass_move_tolerance) {
396
+ if (this.#first_tap_time !== null &&
397
+ performance.now() - this.#first_tap_time < bypass_window &&
398
+ Math.hypot(x - this.#touch_x, y - this.#touch_y) < bypass_move_tolerance) {
399
+ this.bypassed = true;
400
+ this.#clear_tap_tracking();
401
+ return true;
402
+ }
403
+ this.#first_tap_time = performance.now();
404
+ this.#touch_x = x;
405
+ this.#touch_y = y;
406
+ // clear stale tap tracking after the detection window expires
407
+ if (this.#timeout !== null)
408
+ clearTimeout(this.#timeout);
409
+ this.#timeout = setTimeout(() => {
410
+ this.reset();
411
+ }, bypass_window);
412
+ return false;
413
+ }
414
+ /**
415
+ * Consumes a pending bypass, returning `true` and resetting all state if `bypassed` was set,
416
+ * otherwise returning `false` with no effect so tap tracking is preserved.
417
+ */
418
+ consume() {
419
+ if (!this.bypassed)
420
+ return false;
421
+ this.reset();
422
+ return true;
423
+ }
424
+ /**
425
+ * Clears all tracking state including any pending bypass.
426
+ */
427
+ reset() {
428
+ this.bypassed = false;
429
+ this.#clear_tap_tracking();
430
+ }
431
+ #clear_tap_tracking() {
432
+ this.#first_tap_time = null;
433
+ if (this.#timeout !== null) {
434
+ clearTimeout(this.#timeout);
435
+ this.#timeout = null;
436
+ }
437
+ }
438
+ }
@@ -3,6 +3,7 @@ import type { Result } from '@fuzdev/fuz_util/result.js';
3
3
  import type { SvelteHTMLElements } from 'svelte/elements';
4
4
  import type { Attachment } from 'svelte/attachments';
5
5
  import { Dimensions } from './dimensions.svelte.js';
6
+ import type { SvgData } from './svg.js';
6
7
  export declare const contextmenu_context: {
7
8
  get: (error_message?: string) => () => ContextmenuState;
8
9
  get_maybe: () => (() => ContextmenuState) | undefined;
@@ -27,7 +28,7 @@ export type ContextmenuParams = Snippet | {
27
28
  snippet: 'text';
28
29
  props: {
29
30
  content: string;
30
- icon: string;
31
+ icon: SvgData | string;
31
32
  run: ContextmenuRun;
32
33
  };
33
34
  } | {
@@ -51,31 +52,54 @@ export declare class EntryState {
51
52
  promise: Promise<ContextmenuActivateResult> | null;
52
53
  constructor(menu: SubmenuState | RootMenuState, run: () => ContextmenuRun, disabled?: () => boolean);
53
54
  }
54
- export declare class SubmenuState {
55
+ /**
56
+ * Shared `items` state for `SubmenuState` and `RootMenuState`.
57
+ *
58
+ * The source of truth is a plain non-reactive array because items register and
59
+ * unregister from component lifecycles that can interleave within a single batch -
60
+ * effect teardowns can observe stale signal values mid-batch, so read-copy-write
61
+ * against the reactive array can lose concurrent registrations (e.g. reopening the
62
+ * menu while it's open). Every mutation publishes an immutable snapshot, preserving
63
+ * the reassignment (not mutation) contract for readers.
64
+ */
65
+ export declare class ContextmenuItemsState {
66
+ #private;
67
+ get items(): ReadonlyArray<ItemState>;
68
+ set items(value: ReadonlyArray<ItemState>);
69
+ /**
70
+ * Appends `item`, publishing a new immutable `items`.
71
+ */
72
+ add_item(item: ItemState): void;
73
+ /**
74
+ * Removes `item` if present, publishing a new immutable `items`.
75
+ * Safe to call from effect teardown - it reads only the non-reactive source array.
76
+ */
77
+ remove_item(item: ItemState): void;
78
+ }
79
+ export declare class SubmenuState extends ContextmenuItemsState {
55
80
  readonly is_menu = true;
56
81
  readonly menu: SubmenuState | RootMenuState;
57
82
  readonly depth: number;
58
83
  selected: boolean;
59
- items: ReadonlyArray<ItemState>;
60
84
  constructor(menu: SubmenuState | RootMenuState, depth: number);
61
85
  }
62
- export declare class RootMenuState {
86
+ export declare class RootMenuState extends ContextmenuItemsState {
63
87
  readonly is_menu = true;
64
88
  readonly menu: null;
65
89
  readonly depth = 1;
66
- items: ReadonlyArray<ItemState>;
67
90
  }
68
91
  export type ContextmenuRun = () => ContextmenuActivateResult | Promise<ContextmenuActivateResult>;
69
92
  export interface ContextmenuStateOptions {
70
93
  layout?: Dimensions;
71
94
  }
72
95
  /**
73
- * Creates a contextmenu store.
96
+ * Manages contextmenu state.
74
97
  * See usage with `ContextmenuRoot.svelte` and `Contextmenu.svelte`.
75
98
  *
76
99
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event}
77
100
  */
78
101
  export declare class ContextmenuState {
102
+ #private;
79
103
  layout: Dimensions;
80
104
  /**
81
105
  * If an initial layout is provided, control is deferred externally.
@@ -87,21 +111,42 @@ export declare class ContextmenuState {
87
111
  y: number;
88
112
  params: ReadonlyArray<ContextmenuParams>;
89
113
  error: string | undefined;
114
+ /**
115
+ * The element the menu was opened from, while opened, else `undefined`.
116
+ * Resolves the popover host when the menu opens inside a modal `<dialog>` -
117
+ * see `contextmenu_resolve_popover_host`. Deliberately not reactive -
118
+ * read it in event handlers and attachments, not in templates.
119
+ */
120
+ target: HTMLElement | SVGElement | undefined;
90
121
  readonly root_menu: RootMenuState;
91
122
  selections: ReadonlyArray<ItemState>;
92
123
  can_collapse: boolean;
93
124
  can_expand: boolean;
94
- can_select_next: boolean;
95
- can_select_previous: boolean;
125
+ /**
126
+ * Whether `select_next` and `select_previous` can move the selection -
127
+ * the selected menu has more than one item.
128
+ */
129
+ can_select_sibling: boolean;
96
130
  can_activate: boolean;
97
131
  constructor(options?: ContextmenuStateOptions);
98
- open(params: Array<ContextmenuParams>, x: number, y: number): void;
132
+ open(params: Array<ContextmenuParams>, x: number, y: number, target?: HTMLElement | SVGElement): void;
99
133
  close(): void;
100
134
  reset_items(items: ReadonlyArray<ItemState>): void;
135
+ /**
136
+ * Activates `item` - expanding submenus, running entries.
137
+ *
138
+ * @returns for async runs, the activation promise; for sync runs, `false` when the
139
+ * activation didn't run (disabled) or failed (a throw or `{ok: false}`), else `true`
140
+ */
101
141
  activate(item: ItemState): boolean | Promise<ContextmenuActivateResult>;
142
+ /**
143
+ * Activates the selected item, or if none is selected, selects the first.
144
+ * Returns `false` without activating when the selected item has unregistered
145
+ * out from under the selection (e.g. its component unmounted).
146
+ */
102
147
  activate_selected(): void | boolean | Promise<ContextmenuActivateResult>;
103
148
  /**
104
- * Activates the selected entry, or if none, selects the first.
149
+ * Selects `item` and its ancestor menus, deselecting everything else.
105
150
  */
106
151
  select(item: ItemState): void;
107
152
  collapse_selected(): void;
@@ -124,7 +169,7 @@ export declare class ContextmenuState {
124
169
  * Creates an attachment that sets up contextmenu behavior on an element.
125
170
  * @param params - contextmenu parameters or nullish to disable
126
171
  */
127
- export declare const contextmenu_attachment: <T extends ContextmenuParams, U extends T | Array<T>>(params: U | null | undefined) => Attachment<HTMLElement | SVGElement>;
172
+ export declare const contextmenu_attachment: (params: ContextmenuParams | Array<ContextmenuParams> | null | undefined) => Attachment<HTMLElement | SVGElement>;
128
173
  export interface ContextmenuOpenOptions {
129
174
  link_enabled?: boolean;
130
175
  text_enabled?: boolean;
@@ -135,16 +180,17 @@ export interface ContextmenuOpenOptions {
135
180
  * Opens the contextmenu, if appropriate,
136
181
  * querying the menu items from the DOM starting at the event target.
137
182
  * @param target - the leaf element from which to open the contextmenu
138
- * @param x - the page X coordinate at which to open the contextmenu, typically the mouse `pageX`
139
- * @param y - the page Y coordinate at which to open the contextmenu, typically the mouse `pageY`
140
- * @param contextmenu - the contextmenu store
183
+ * @param x - the client (viewport) X coordinate at which to open the contextmenu, typically the mouse `clientX` - the menu positions with `fixed`
184
+ * @param y - the client (viewport) Y coordinate at which to open the contextmenu, typically the mouse `clientY` - the menu positions with `fixed`
185
+ * @param contextmenu - the contextmenu state
141
186
  * @param options - optional configuration for filtering entries and haptic feedback
142
187
  * @returns a boolean indicating if the menu was opened or not
143
188
  */
144
189
  export declare const contextmenu_open: (target: HTMLElement | SVGElement, x: number, y: number, contextmenu: ContextmenuState, options?: ContextmenuOpenOptions) => boolean;
145
190
  /**
146
191
  * Registers a contextmenu root and warns if multiple non-scoped roots are detected.
147
- * Only active in development mode. Automatically handles cleanup on unmount.
192
+ * Only active in development mode - `DEV` is a build-time constant, so production
193
+ * bundles eliminate the check. Automatically handles cleanup on unmount.
148
194
  *
149
195
  * @param get_scoped - getter function that returns the current scoped value
150
196
  */
@@ -1 +1 @@
1
- {"version":3,"file":"contextmenu_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/contextmenu_state.svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contextmenu_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/contextmenu_state.svelte.ts"],"names":[],"mappings":"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"}