@vizejs/ui 0.345.0 → 0.350.2

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 (96) hide show
  1. package/dist/{button-D7sM9Xmj.d.mts → button-CVX8UBXj.d.mts} +6 -7
  2. package/dist/{button-8BOlFJNu.mjs → button-DT8AKlds.mjs} +2 -2
  3. package/dist/button.d.mts +1 -1
  4. package/dist/button.mjs +1 -1
  5. package/dist/catalog.d.mts +541 -0
  6. package/dist/catalog.mjs +784 -0
  7. package/dist/{checkbox-B4y9GUen.mjs → checkbox-BgIvwjyC.mjs} +2 -2
  8. package/dist/{checkbox-DkwZFC80.d.mts → checkbox-DP3_ko7D.d.mts} +7 -8
  9. package/dist/checkbox.d.mts +1 -1
  10. package/dist/checkbox.mjs +1 -1
  11. package/dist/collection-B_dFZOHO.d.mts +185 -0
  12. package/dist/collection-eHN150dT.mjs +453 -0
  13. package/dist/collection.d.mts +2 -0
  14. package/dist/collection.mjs +2 -0
  15. package/dist/composite-navigation-QINW9GLy.d.mts +115 -0
  16. package/dist/composite-navigation-Skx3LZsv.mjs +354 -0
  17. package/dist/composite-navigation.d.mts +2 -0
  18. package/dist/composite-navigation.mjs +2 -0
  19. package/dist/controllable-state.d.mts +1 -1
  20. package/dist/dismissable-layer-4icKahVs.d.mts +119 -0
  21. package/dist/dismissable-layer-CwG1gtdz.mjs +488 -0
  22. package/dist/dismissable-layer.d.mts +2 -0
  23. package/dist/dismissable-layer.mjs +2 -0
  24. package/dist/focus-CAWi_I-0.mjs +318 -0
  25. package/dist/focus-K6dOifoZ.d.mts +112 -0
  26. package/dist/focus-guards-Bt0C-0qS.d.mts +81 -0
  27. package/dist/focus-guards-DhMPQAT8.mjs +299 -0
  28. package/dist/focus-guards.d.mts +2 -0
  29. package/dist/focus-guards.mjs +2 -0
  30. package/dist/focus-scope-CavhKWx0.d.mts +100 -0
  31. package/dist/focus-scope-D9U1aj67.mjs +340 -0
  32. package/dist/focus-scope-dom-DBwNEWxG.mjs +264 -0
  33. package/dist/focus-scope.d.mts +2 -0
  34. package/dist/focus-scope.mjs +2 -0
  35. package/dist/focus.d.mts +2 -0
  36. package/dist/focus.mjs +2 -0
  37. package/dist/hover-BXwwbSaO.d.mts +80 -0
  38. package/dist/hover.d.mts +2 -0
  39. package/dist/hover.mjs +197 -0
  40. package/dist/id-5OAUyVPd.d.mts +126 -0
  41. package/dist/id-mziSyAse.mjs +137 -0
  42. package/dist/id.d.mts +2 -0
  43. package/dist/id.mjs +2 -0
  44. package/dist/index.d.mts +23 -6
  45. package/dist/index.mjs +21 -5
  46. package/dist/inert-outside-CyqtoKQ4.mjs +346 -0
  47. package/dist/inert-outside-tuHRmaqJ.d.mts +43 -0
  48. package/dist/inert-outside.d.mts +2 -0
  49. package/dist/inert-outside.mjs +2 -0
  50. package/dist/interaction-modality-DOZK0BpZ.mjs +304 -0
  51. package/dist/interaction-modality-jgHKjPFB.d.mts +89 -0
  52. package/dist/interaction-modality.d.mts +2 -0
  53. package/dist/interaction-modality.mjs +2 -0
  54. package/dist/long-press-Dsul69gk.mjs +340 -0
  55. package/dist/long-press-cll6z2K9.d.mts +105 -0
  56. package/dist/long-press.d.mts +2 -0
  57. package/dist/long-press.mjs +2 -0
  58. package/dist/media-pdf.d.mts +1 -1
  59. package/dist/media-pdf.mjs +1 -1
  60. package/dist/media.d.mts +1 -1
  61. package/dist/media.mjs +1 -1
  62. package/dist/move-BOmXDYbh.d.mts +103 -0
  63. package/dist/move-BVvMHzxr.mjs +386 -0
  64. package/dist/move.d.mts +2 -0
  65. package/dist/move.mjs +2 -0
  66. package/dist/press-N_mE3Mgx.mjs +469 -0
  67. package/dist/press-event-Cd2OPpmw.mjs +149 -0
  68. package/dist/press-types-CNqStzJf.d.mts +112 -0
  69. package/dist/press.d.mts +14 -0
  70. package/dist/press.mjs +2 -0
  71. package/dist/{primitive-DJB7pOf3.mjs → primitive-BX31dogp.mjs} +2 -2
  72. package/dist/{primitive-BtvwikH1.d.mts → primitive-C8jW7DLd.d.mts} +3 -4
  73. package/dist/primitive.d.mts +1 -1
  74. package/dist/primitive.mjs +1 -1
  75. package/dist/scroll-lock-BgVtX4wT.d.mts +49 -0
  76. package/dist/scroll-lock-Ckbmm0-J.mjs +313 -0
  77. package/dist/scroll-lock.d.mts +2 -0
  78. package/dist/scroll-lock.mjs +2 -0
  79. package/dist/spatial-navigation-CHj9mDZH.d.mts +106 -0
  80. package/dist/spatial-navigation-D6-UDavU.mjs +301 -0
  81. package/dist/spatial-navigation.d.mts +2 -0
  82. package/dist/spatial-navigation.mjs +2 -0
  83. package/dist/typeahead-B7KDxE_u.mjs +175 -0
  84. package/dist/typeahead-BbgUB2Bj.d.mts +71 -0
  85. package/dist/typeahead.d.mts +2 -0
  86. package/dist/typeahead.mjs +2 -0
  87. package/dist/visually-hidden-BOqfqBFt.d.mts +17 -0
  88. package/dist/{visually-hidden-QENRapzW.mjs → visually-hidden-BwDOx5yf.mjs} +2 -2
  89. package/dist/visually-hidden.d.mts +1 -1
  90. package/dist/visually-hidden.mjs +1 -1
  91. package/package.json +99 -11
  92. package/dist/visually-hidden-BegtnMng.d.mts +0 -19
  93. /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
  94. /package/dist/{controllable-state-DXsYJ3yl.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
  95. /package/dist/{pdf-source-COxN3A1l.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
  96. /package/dist/{pdf-source-C52YE8tp.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
@@ -0,0 +1,112 @@
1
+ import { MaybeRefOrGetter, ShallowRef } from "vue";
2
+
3
+ //#region src/press-types.d.ts
4
+ /** Stable input family reported by a press interaction. */
5
+ type PressPointerType = "keyboard" | "mouse" | "pen" | "pointer" | "touch" | "virtual";
6
+ /** Lifecycle notification emitted by a press controller. */
7
+ type PressEventType = "press" | "pressend" | "pressstart" | "pressup";
8
+ /** Keyboard semantics applied when the host is not natively activatable. */
9
+ type PressKeyboardBehavior = "button" | "link" | "none";
10
+ /** Immutable, renderer-independent snapshot of one press lifecycle event. */
11
+ interface PressEvent {
12
+ /** Press lifecycle phase represented by this snapshot. */
13
+ readonly type: PressEventType;
14
+ /** Input family that initiated the interaction. */
15
+ readonly pointerType: PressPointerType;
16
+ /** Element whose bound press props own the interaction. */
17
+ readonly target: Element;
18
+ /** Native event responsible for this phase, or `null` for manual cancellation. */
19
+ readonly originalEvent: Event | null;
20
+ /** Viewport coordinate when supplied by pointing hardware. */
21
+ readonly x: number | null;
22
+ /** Viewport coordinate when supplied by pointing hardware. */
23
+ readonly y: number | null;
24
+ /** Modifier-key snapshots captured from the native event. */
25
+ readonly altKey: boolean;
26
+ readonly ctrlKey: boolean;
27
+ readonly metaKey: boolean;
28
+ readonly shiftKey: boolean;
29
+ /** Whether the lifecycle ended without an activation. */
30
+ readonly isCanceled: boolean;
31
+ }
32
+ /** Options shared by {@link createPress} and {@link usePress}. */
33
+ interface PressOptions {
34
+ /**
35
+ * Suppress every activation while retaining the bound props.
36
+ *
37
+ * Reactive values are read for every event, so disabling an interaction
38
+ * between pointer-down and pointer-up cancels it deterministically.
39
+ *
40
+ * @default false
41
+ */
42
+ readonly isDisabled?: MaybeRefOrGetter<boolean | undefined>;
43
+ /**
44
+ * Keyboard contract for hosts without native activation behavior.
45
+ * Native buttons, links, inputs, and summaries always keep browser timing.
46
+ *
47
+ * @default "button"
48
+ */
49
+ readonly keyboardBehavior?: MaybeRefOrGetter<PressKeyboardBehavior | undefined>;
50
+ /**
51
+ * End the interaction permanently on its first pointer exit.
52
+ * When false, leaving pauses pressed state and re-entering resumes it.
53
+ *
54
+ * @default false
55
+ */
56
+ readonly shouldCancelOnPointerExit?: MaybeRefOrGetter<boolean | undefined>;
57
+ /**
58
+ * Prevent the compatibility mousedown default that normally moves focus.
59
+ * Keyboard and virtual activation never lose focus.
60
+ *
61
+ * @default false
62
+ */
63
+ readonly preventFocusOnPress?: MaybeRefOrGetter<boolean | undefined>;
64
+ /**
65
+ * Preserve selectable text during an active pointer press. When false, the
66
+ * host's exact inline user-select declarations are restored at press end.
67
+ *
68
+ * @default false
69
+ */
70
+ readonly allowTextSelectionOnPress?: MaybeRefOrGetter<boolean | undefined>;
71
+ /** Called after pressed state becomes active. */
72
+ readonly onPressStart?: (event: PressEvent) => void;
73
+ /** Called after pressed state ends or pauses at the pointer boundary. */
74
+ readonly onPressEnd?: (event: PressEvent) => void;
75
+ /** Called for every distinct pressed-state transition. */
76
+ readonly onPressChange?: (isPressed: boolean) => void;
77
+ /** Called when keyboard or pointing hardware is released over the host. */
78
+ readonly onPressUp?: (event: PressEvent) => void;
79
+ /** Called exactly once for a completed activation. */
80
+ readonly onPress?: (event: PressEvent) => void;
81
+ }
82
+ /** Framework props to spread onto the element that owns a press interaction. */
83
+ interface PressProps {
84
+ readonly onClick: (event: MouseEvent) => void;
85
+ readonly onDragstart: (event: DragEvent) => void;
86
+ readonly onKeydown: (event: KeyboardEvent) => void;
87
+ readonly onKeyup: (event: KeyboardEvent) => void;
88
+ readonly onMousedown: (event: MouseEvent) => void;
89
+ readonly onMousemove: (event: MouseEvent) => void;
90
+ readonly onMouseup: (event: MouseEvent) => void;
91
+ readonly onPointercancel: (event: PointerEvent) => void;
92
+ readonly onPointerdown: (event: PointerEvent) => void;
93
+ readonly onPointermove: (event: PointerEvent) => void;
94
+ readonly onPointerup: (event: PointerEvent) => void;
95
+ readonly onTouchcancel: (event: TouchEvent) => void;
96
+ readonly onTouchend: (event: TouchEvent) => void;
97
+ readonly onTouchmove: (event: TouchEvent) => void;
98
+ readonly onTouchstart: (event: TouchEvent) => void;
99
+ }
100
+ /** Stateful press normalizer with explicit lifecycle ownership. */
101
+ interface PressController {
102
+ /** Whether the active input is currently within the pressed region. */
103
+ readonly isPressed: Readonly<ShallowRef<boolean>>;
104
+ /** Stable handlers to merge or spread onto exactly one host element. */
105
+ readonly pressProps: Readonly<PressProps>;
106
+ /** Cancel the current interaction without producing an activation. */
107
+ readonly cancel: () => boolean;
108
+ /** Release document listeners, timers, and transient selection changes. */
109
+ readonly dispose: () => void;
110
+ }
111
+ //#endregion
112
+ export { PressOptions as a, PressKeyboardBehavior as i, PressEvent as n, PressPointerType as o, PressEventType as r, PressProps as s, PressController as t };
@@ -0,0 +1,14 @@
1
+ import { a as PressOptions, i as PressKeyboardBehavior, n as PressEvent, o as PressPointerType, r as PressEventType, s as PressProps, t as PressController } from "./press-types-CNqStzJf.mjs";
2
+
3
+ //#region src/press.d.ts
4
+ /**
5
+ * Create an SSR-safe press normalizer for one host element.
6
+ *
7
+ * Spread the returned `pressProps` onto the host and call `dispose` when using
8
+ * this factory outside a Vue effect scope. No DOM global is read at setup.
9
+ */
10
+ declare function createPress(options?: PressOptions): PressController;
11
+ /** Create a press normalizer disposed with the current Vue effect scope. */
12
+ declare function usePress(options?: PressOptions): PressController;
13
+ //#endregion
14
+ export { type PressController, type PressEvent, type PressEventType, type PressKeyboardBehavior, type PressOptions, type PressPointerType, type PressProps, createPress, usePress };
package/dist/press.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { n as usePress, t as createPress } from "./press-N_mE3Mgx.mjs";
2
+ export { createPress, usePress };
@@ -1,8 +1,8 @@
1
- import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BVN2DL-U.mjs";
1
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.mjs";
2
2
  import { createBlock, createSlots, defineComponent, openBlock, renderList, renderSlot, resolveDynamicComponent, useSlots, useTemplateRef, withCtx } from "vue";
3
3
  //#endregion
4
4
  //#region src/PrimitiveElement.vue
5
- var PrimitiveElement_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
5
+ var PrimitiveElement_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
6
6
  __name: "PrimitiveElement",
7
7
  props: { as: {
8
8
  type: null,
@@ -1,4 +1,3 @@
1
- import * as _$vue from "vue";
2
1
  import { Component, ComponentPublicInstance } from "vue";
3
2
 
4
3
  //#region src/PrimitiveElement.vue.d.ts
@@ -12,9 +11,9 @@ type __VLS_Props = {
12
11
  };
13
12
  declare var __VLS_11: string, __VLS_12: {};
14
13
  type __VLS_Slots = {} & { [K in NonNullable<typeof __VLS_11>]?: (props: typeof __VLS_12) => any };
15
- declare const __VLS_base: _$vue.DefineComponent<__VLS_Props, {
16
- element: Readonly<_$vue.ShallowRef<PrimitiveElement | null>>;
17
- }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
14
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
15
+ element: Readonly<import("vue").ShallowRef<PrimitiveElement | null>>;
16
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
17
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
19
18
  declare const _default: typeof __VLS_export;
20
19
  type __VLS_WithSlots<T, S> = T & {
@@ -1,2 +1,2 @@
1
- import { n as PrimitiveElement, r as _default, t as PrimitiveAs } from "./primitive-BtvwikH1.mjs";
1
+ import { n as PrimitiveElement, r as _default, t as PrimitiveAs } from "./primitive-C8jW7DLd.mjs";
2
2
  export { _default as Primitive, PrimitiveAs, PrimitiveElement };
@@ -1,2 +1,2 @@
1
- import { t as PrimitiveElement_default } from "./primitive-DJB7pOf3.mjs";
1
+ import { t as PrimitiveElement_default } from "./primitive-BX31dogp.mjs";
2
2
  export { PrimitiveElement_default as Primitive };
@@ -0,0 +1,49 @@
1
+ import { MaybeRefOrGetter, ShallowRef } from "vue";
2
+
3
+ //#region src/scroll-lock-types.d.ts
4
+ /** Viewport-locking strategy selected for a document. */
5
+ type ScrollLockStrategy = "auto" | "fixed" | "overflow";
6
+ /** Reactive configuration for one document scroll-lock owner. */
7
+ interface ScrollLockOptions {
8
+ /** Document whose layout viewport is locked. It may be `null` during SSR. */
9
+ readonly document: MaybeRefOrGetter<Document | null | undefined>;
10
+ /** Whether an activated controller currently participates in the lock stack. @default true */
11
+ readonly enabled?: MaybeRefOrGetter<boolean | undefined>;
12
+ /**
13
+ * Lock using root overflow or a fixed body. `auto` uses fixed positioning on iOS-like
14
+ * touch platforms and root overflow elsewhere.
15
+ * @default "auto"
16
+ */
17
+ readonly strategy?: MaybeRefOrGetter<ScrollLockStrategy | undefined>;
18
+ /** Reserve a classic scrollbar gutter so viewport-width content does not shift. @default true */
19
+ readonly preserveScrollbarGap?: MaybeRefOrGetter<boolean | undefined>;
20
+ /** Restore the captured layout-viewport offset when the final owner releases. @default true */
21
+ readonly restoreScroll?: MaybeRefOrGetter<boolean | undefined>;
22
+ }
23
+ /** Lifecycle and inspection interface returned by `createScrollLock`. */
24
+ interface ScrollLockController {
25
+ /** Whether this controller has been activated, independently of reactive enablement. */
26
+ readonly isActive: Readonly<ShallowRef<boolean>>;
27
+ /** Whether this controller currently contributes to a document lock. */
28
+ readonly isLocked: Readonly<ShallowRef<boolean>>;
29
+ /** Classic scrollbar width measured before the current document lock. */
30
+ readonly scrollbarGap: Readonly<ShallowRef<number>>;
31
+ /** Effective strategy after platform resolution and nested-lock composition. */
32
+ readonly resolvedStrategy: Readonly<ShallowRef<Exclude<ScrollLockStrategy, "auto"> | null>>;
33
+ /** Join the document lock stack. Safe to call repeatedly. */
34
+ readonly activate: () => void;
35
+ /** Leave the lock stack and restore document state when the final owner exits. */
36
+ readonly deactivate: () => void;
37
+ /** Re-read reactive options and recover after imperative document changes. */
38
+ readonly refresh: () => void;
39
+ /** Permanently release reactive and document-level ownership. */
40
+ readonly dispose: () => void;
41
+ }
42
+ //#endregion
43
+ //#region src/scroll-lock.d.ts
44
+ /** Lock a reactive document viewport without suppressing browser zoom gestures. */
45
+ declare function createScrollLock(options: ScrollLockOptions): ScrollLockController;
46
+ /** Create, mount-activate, and scope-dispose a document scroll lock. */
47
+ declare function useScrollLock(options: ScrollLockOptions): ScrollLockController;
48
+ //#endregion
49
+ export { ScrollLockStrategy as a, ScrollLockOptions as i, useScrollLock as n, ScrollLockController as r, createScrollLock as t };
@@ -0,0 +1,313 @@
1
+ import { getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, shallowReadonly, shallowRef, toValue, watch } from "vue";
2
+ //#region src/scroll-lock-internal.ts
3
+ const optionDiagnostic = "VIZE_UI_SCROLL_LOCK_OPTION";
4
+ function readDocument(source) {
5
+ const value = toValue(source);
6
+ if (value === void 0 || value === null) return null;
7
+ const candidate = value;
8
+ if (candidate.nodeType !== 9 || candidate.documentElement?.nodeType !== 1) throw new TypeError(`${optionDiagnostic}: document must resolve to a Document or null`);
9
+ return value;
10
+ }
11
+ function readBoolean(source, name, fallback) {
12
+ const value = toValue(source);
13
+ if (value === void 0) return fallback;
14
+ if (typeof value !== "boolean") throw new TypeError(`${optionDiagnostic}: ${name} must resolve to a boolean`);
15
+ return value;
16
+ }
17
+ function readStrategy(source) {
18
+ const value = toValue(source) ?? "auto";
19
+ if (value !== "auto" && value !== "fixed" && value !== "overflow") throw new TypeError(`${optionDiagnostic}: strategy must resolve to "auto", "fixed", or "overflow"`);
20
+ return value;
21
+ }
22
+ function validateScrollLockOptions(options) {
23
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError(`${optionDiagnostic}: options must be an object`);
24
+ readDocument(options.document);
25
+ readBoolean(options.enabled, "enabled", true);
26
+ readBoolean(options.preserveScrollbarGap, "preserveScrollbarGap", true);
27
+ readBoolean(options.restoreScroll, "restoreScroll", true);
28
+ readStrategy(options.strategy);
29
+ }
30
+ //#endregion
31
+ //#region src/scroll-lock-dom.ts
32
+ const rootProperties = [
33
+ "--vize-scroll-lock-scrollbar-gap",
34
+ "overflow",
35
+ "overscroll-behavior",
36
+ "padding-inline-end",
37
+ "scrollbar-gutter"
38
+ ];
39
+ const bodyProperties = [
40
+ "left",
41
+ "position",
42
+ "top",
43
+ "width"
44
+ ];
45
+ function captureStyle(element, properties) {
46
+ return {
47
+ element,
48
+ properties: properties.map((name) => ({
49
+ name,
50
+ priority: element.style.getPropertyPriority(name),
51
+ value: element.style.getPropertyValue(name)
52
+ }))
53
+ };
54
+ }
55
+ function restoreStyle(snapshot) {
56
+ for (const { name, priority, value } of snapshot.properties) if (value) snapshot.element.style.setProperty(name, value, priority);
57
+ else snapshot.element.style.removeProperty(name);
58
+ }
59
+ function setOwnedStyle(element, name, value) {
60
+ element.style.setProperty(name, value, "important");
61
+ }
62
+ function captureDocumentLock(document) {
63
+ const root = document.documentElement;
64
+ const body = document.body;
65
+ if (!root || !body) return null;
66
+ const view = document.defaultView;
67
+ return {
68
+ attribute: root.getAttribute("data-vize-scroll-locked"),
69
+ body: captureStyle(body, bodyProperties),
70
+ root: captureStyle(root, rootProperties),
71
+ scrollX: view?.scrollX ?? 0,
72
+ scrollY: view?.scrollY ?? 0
73
+ };
74
+ }
75
+ function measureScrollbarGap(document) {
76
+ const view = document.defaultView;
77
+ const clientWidth = document.documentElement?.clientWidth ?? 0;
78
+ if (!view || clientWidth <= 0 || !Number.isFinite(view.innerWidth)) return 0;
79
+ return Math.max(0, view.innerWidth - clientWidth);
80
+ }
81
+ function resolveScrollLockStrategy(document, strategy) {
82
+ if (strategy !== "auto") return strategy;
83
+ const navigator = document.defaultView?.navigator;
84
+ const platform = navigator?.platform ?? "";
85
+ const userAgent = navigator?.userAgent ?? "";
86
+ return /^(iPad|iPhone|iPod)$/.test(platform) || /\b(iPad|iPhone|iPod)\b/.test(userAgent) || platform === "MacIntel" && (navigator?.maxTouchPoints ?? 0) > 1 ? "fixed" : "overflow";
87
+ }
88
+ function applyDocumentLock(snapshot, strategy, gap, preserveGap) {
89
+ const root = snapshot.root.element;
90
+ root.setAttribute("data-vize-scroll-locked", "");
91
+ setOwnedStyle(root, "--vize-scroll-lock-scrollbar-gap", `${gap}px`);
92
+ setOwnedStyle(root, "overflow", "hidden");
93
+ setOwnedStyle(root, "overscroll-behavior", "none");
94
+ if (preserveGap) {
95
+ if (root.ownerDocument.defaultView?.CSS?.supports?.("scrollbar-gutter", "stable")) setOwnedStyle(root, "scrollbar-gutter", "stable");
96
+ else if (gap > 0) {
97
+ const computed = root.ownerDocument.defaultView?.getComputedStyle(root).paddingInlineEnd;
98
+ const padding = Number.parseFloat(computed ?? "0");
99
+ setOwnedStyle(root, "padding-inline-end", `${(Number.isFinite(padding) ? padding : 0) + gap}px`);
100
+ }
101
+ }
102
+ if (strategy === "fixed") {
103
+ const body = snapshot.body.element;
104
+ setOwnedStyle(body, "position", "fixed");
105
+ setOwnedStyle(body, "top", `${-snapshot.scrollY}px`);
106
+ setOwnedStyle(body, "left", `${-snapshot.scrollX}px`);
107
+ setOwnedStyle(body, "width", "100%");
108
+ }
109
+ }
110
+ function restoreDocumentLock(snapshot) {
111
+ restoreStyle(snapshot.body);
112
+ restoreStyle(snapshot.root);
113
+ if (snapshot.attribute === null) snapshot.root.element.removeAttribute("data-vize-scroll-locked");
114
+ else snapshot.root.element.setAttribute("data-vize-scroll-locked", snapshot.attribute);
115
+ }
116
+ function restoreDocumentScroll(snapshot) {
117
+ const view = snapshot.root.element.ownerDocument.defaultView;
118
+ if (!view || typeof view.scrollTo !== "function") return;
119
+ try {
120
+ view.scrollTo({
121
+ behavior: "instant",
122
+ left: snapshot.scrollX,
123
+ top: snapshot.scrollY
124
+ });
125
+ } catch {}
126
+ }
127
+ //#endregion
128
+ //#region src/scroll-lock-stack.ts
129
+ const states = /* @__PURE__ */ new WeakMap();
130
+ function stateFor(document) {
131
+ let state = states.get(document);
132
+ if (!state) {
133
+ state = {
134
+ document,
135
+ restoreOnRelease: true,
136
+ snapshot: null,
137
+ tokens: []
138
+ };
139
+ states.set(document, state);
140
+ }
141
+ return state;
142
+ }
143
+ function restoreAppliedState(state, restoreScroll) {
144
+ const snapshot = state.snapshot;
145
+ if (!snapshot) return;
146
+ restoreDocumentLock(snapshot);
147
+ if (restoreScroll) restoreDocumentScroll(snapshot);
148
+ }
149
+ function effectiveStrategy(document, tokens) {
150
+ return tokens.map((token) => resolveScrollLockStrategy(document, token.readStrategy())).includes("fixed") ? "fixed" : "overflow";
151
+ }
152
+ function recomputeScrollLock(state) {
153
+ const enabled = state.tokens.filter((token) => token.readEnabled());
154
+ if (enabled.length === 0) {
155
+ restoreAppliedState(state, state.restoreOnRelease);
156
+ state.snapshot = null;
157
+ for (const token of state.tokens) token.setState(false, 0, null);
158
+ return;
159
+ }
160
+ const previous = state.snapshot;
161
+ if (previous) restoreAppliedState(state, true);
162
+ const next = captureDocumentLock(state.document);
163
+ if (!next) {
164
+ state.snapshot = null;
165
+ for (const token of state.tokens) token.setState(false, 0, null);
166
+ return;
167
+ }
168
+ state.snapshot = previous ? {
169
+ ...next,
170
+ scrollX: previous.scrollX,
171
+ scrollY: previous.scrollY
172
+ } : next;
173
+ state.restoreOnRelease = enabled[0]?.readRestoreScroll() ?? true;
174
+ const strategy = effectiveStrategy(state.document, enabled);
175
+ const gap = measureScrollbarGap(state.document);
176
+ const preserveGap = enabled.some((token) => token.readPreserveGap());
177
+ applyDocumentLock(state.snapshot, strategy, gap, preserveGap);
178
+ for (const token of state.tokens) {
179
+ const locked = enabled.includes(token);
180
+ token.setState(locked, locked ? gap : 0, locked ? strategy : null);
181
+ }
182
+ }
183
+ function attachScrollLock(token, document) {
184
+ if (token.document === document) {
185
+ recomputeScrollLock(stateFor(document));
186
+ return;
187
+ }
188
+ detachScrollLock(token);
189
+ token.document = document;
190
+ const state = stateFor(document);
191
+ state.tokens.push(token);
192
+ recomputeScrollLock(state);
193
+ }
194
+ function detachScrollLock(token) {
195
+ const document = token.document;
196
+ if (!document) {
197
+ token.setState(false, 0, null);
198
+ return;
199
+ }
200
+ const state = stateFor(document);
201
+ const index = state.tokens.indexOf(token);
202
+ if (index >= 0) state.tokens.splice(index, 1);
203
+ token.document = null;
204
+ token.setState(false, 0, null);
205
+ if (state.tokens.length === 0) {
206
+ restoreAppliedState(state, state.restoreOnRelease);
207
+ state.snapshot = null;
208
+ states.delete(document);
209
+ } else recomputeScrollLock(state);
210
+ }
211
+ function refreshScrollLock(token) {
212
+ if (token.document) recomputeScrollLock(stateFor(token.document));
213
+ }
214
+ //#endregion
215
+ //#region src/scroll-lock.ts
216
+ const disposedDiagnostic = "VIZE_UI_SCROLL_LOCK_DISPOSED";
217
+ const setupDiagnostic = "VIZE_UI_SCROLL_LOCK_SETUP";
218
+ /** Lock a reactive document viewport without suppressing browser zoom gestures. */
219
+ function createScrollLock(options) {
220
+ validateScrollLockOptions(options);
221
+ const activeState = shallowRef(false);
222
+ const lockedState = shallowRef(false);
223
+ const gapState = shallowRef(0);
224
+ const strategyState = shallowRef(null);
225
+ const token = {
226
+ document: null,
227
+ readEnabled: () => readBoolean(options.enabled, "enabled", true),
228
+ readPreserveGap: () => readBoolean(options.preserveScrollbarGap, "preserveScrollbarGap", true),
229
+ readRestoreScroll: () => readBoolean(options.restoreScroll, "restoreScroll", true),
230
+ readStrategy: () => readStrategy(options.strategy),
231
+ setState: (locked, gap, strategy) => {
232
+ lockedState.value = locked;
233
+ gapState.value = gap;
234
+ strategyState.value = strategy;
235
+ }
236
+ };
237
+ let disposed = false;
238
+ const assertAlive = () => {
239
+ if (disposed) throw new Error(`${disposedDiagnostic}: the controller has been disposed`);
240
+ };
241
+ const refresh = () => {
242
+ assertAlive();
243
+ if (!activeState.value) return;
244
+ const document = readDocument(options.document);
245
+ readBoolean(options.enabled, "enabled", true);
246
+ readBoolean(options.preserveScrollbarGap, "preserveScrollbarGap", true);
247
+ readBoolean(options.restoreScroll, "restoreScroll", true);
248
+ readStrategy(options.strategy);
249
+ if (document && document !== token.document) attachScrollLock(token, document);
250
+ else if (!document) detachScrollLock(token);
251
+ else refreshScrollLock(token);
252
+ };
253
+ const activate = () => {
254
+ assertAlive();
255
+ if (activeState.value) return;
256
+ activeState.value = true;
257
+ try {
258
+ refresh();
259
+ } catch (error) {
260
+ activeState.value = false;
261
+ detachScrollLock(token);
262
+ throw error;
263
+ }
264
+ };
265
+ const deactivate = () => {
266
+ assertAlive();
267
+ if (!activeState.value) return;
268
+ try {
269
+ detachScrollLock(token);
270
+ } finally {
271
+ activeState.value = false;
272
+ }
273
+ };
274
+ const stopWatch = watch(() => [
275
+ toValue(options.document),
276
+ toValue(options.enabled),
277
+ toValue(options.preserveScrollbarGap),
278
+ toValue(options.restoreScroll),
279
+ toValue(options.strategy)
280
+ ], () => {
281
+ if (activeState.value) refresh();
282
+ }, { flush: "sync" });
283
+ return Object.freeze({
284
+ isActive: shallowReadonly(activeState),
285
+ isLocked: shallowReadonly(lockedState),
286
+ scrollbarGap: shallowReadonly(gapState),
287
+ resolvedStrategy: shallowReadonly(strategyState),
288
+ activate,
289
+ deactivate,
290
+ refresh,
291
+ dispose: () => {
292
+ if (disposed) return;
293
+ try {
294
+ detachScrollLock(token);
295
+ } finally {
296
+ activeState.value = false;
297
+ disposed = true;
298
+ stopWatch();
299
+ }
300
+ }
301
+ });
302
+ }
303
+ /** Create, mount-activate, and scope-dispose a document scroll lock. */
304
+ function useScrollLock(options) {
305
+ if (!getCurrentScope()) throw new Error(`${setupDiagnostic}: use inside component setup or an active effect scope`);
306
+ const controller = createScrollLock(options);
307
+ if (getCurrentInstance()) onMounted(controller.activate);
308
+ else controller.activate();
309
+ onScopeDispose(controller.dispose);
310
+ return controller;
311
+ }
312
+ //#endregion
313
+ export { useScrollLock as n, createScrollLock as t };
@@ -0,0 +1,2 @@
1
+ import { a as ScrollLockStrategy, i as ScrollLockOptions, n as useScrollLock, r as ScrollLockController, t as createScrollLock } from "./scroll-lock-BgVtX4wT.mjs";
2
+ export { type ScrollLockController, type ScrollLockOptions, type ScrollLockStrategy, createScrollLock, useScrollLock };
@@ -0,0 +1,2 @@
1
+ import { n as useScrollLock, t as createScrollLock } from "./scroll-lock-Ckbmm0-J.mjs";
2
+ export { createScrollLock, useScrollLock };
@@ -0,0 +1,106 @@
1
+ import { l as CollectionKey, p as CollectionRegistry, s as CollectionItem } from "./collection-B_dFZOHO.mjs";
2
+ import { MaybeRefOrGetter } from "vue";
3
+
4
+ //#region src/spatial-navigation-types.d.ts
5
+ /** Physical direction requested by spatial navigation. */
6
+ type SpatialNavigationDirection = "down" | "left" | "right" | "up";
7
+ /** Candidate ranking behavior aligned with CSS Spatial Navigation Level 1. */
8
+ type SpatialNavigationAlgorithm = "grid" | "normal";
9
+ /** Arrow-key behavior when no candidate exists in the requested direction. */
10
+ type SpatialNavigationBoundaryBehavior = "contain" | "exit";
11
+ /** DOM focus policy after logical state changes. */
12
+ type SpatialNavigationFocusBehavior = "focus" | "logical";
13
+ /** Serializable, axis-aligned CSS pixel rectangle. */
14
+ interface SpatialNavigationRect {
15
+ readonly bottom: number;
16
+ readonly height: number;
17
+ readonly left: number;
18
+ readonly right: number;
19
+ readonly top: number;
20
+ readonly width: number;
21
+ }
22
+ /** Immutable successful navigation snapshot. */
23
+ interface SpatialNavigationChange<Key extends CollectionKey> {
24
+ readonly direction: SpatialNavigationDirection;
25
+ readonly key: Key;
26
+ readonly previousKey: Key | null;
27
+ readonly originalEvent: Event | null;
28
+ readonly algorithm: SpatialNavigationAlgorithm;
29
+ readonly score: number;
30
+ }
31
+ /** Immutable boundary snapshot emitted when no directional candidate exists. */
32
+ interface SpatialNavigationBoundary<Key extends CollectionKey> {
33
+ readonly direction: SpatialNavigationDirection;
34
+ readonly key: Key | null;
35
+ readonly originalEvent: Event | null;
36
+ }
37
+ /** Spatial navigation configuration for one caller-owned collection. */
38
+ interface SpatialNavigationOptions<Key extends CollectionKey, Value> {
39
+ /** Ordered logical items and active-key ownership. */
40
+ readonly registry: CollectionRegistry<Key, Value>;
41
+ /**
42
+ * Candidate scoring algorithm.
43
+ *
44
+ * @default "normal"
45
+ */
46
+ readonly algorithm?: MaybeRefOrGetter<SpatialNavigationAlgorithm | undefined>;
47
+ /**
48
+ * Whether a boundary arrow remains owned by the composite or exits to native behavior.
49
+ *
50
+ * @default "contain"
51
+ */
52
+ readonly boundaryBehavior?: MaybeRefOrGetter<SpatialNavigationBoundaryBehavior | undefined>;
53
+ /** Suppress keyboard and imperative navigation without discarding active state. */
54
+ readonly isDisabled?: MaybeRefOrGetter<boolean | undefined>;
55
+ /**
56
+ * Wrap to the opposite spatial edge when no forward candidate exists.
57
+ *
58
+ * @default false
59
+ */
60
+ readonly loop?: MaybeRefOrGetter<boolean | undefined>;
61
+ /**
62
+ * Whether successful navigation moves DOM focus or only logical active state.
63
+ *
64
+ * @default "focus"
65
+ */
66
+ readonly focusBehavior?: MaybeRefOrGetter<SpatialNavigationFocusBehavior | undefined>;
67
+ /**
68
+ * Avoid browser scrolling while moving DOM focus. Reveal behavior still runs.
69
+ *
70
+ * @default false
71
+ */
72
+ readonly preventScroll?: MaybeRefOrGetter<boolean | undefined>;
73
+ /**
74
+ * Resolve transformed viewport geometry for DOM or virtual items.
75
+ * The default reads `element.getBoundingClientRect()` and skips unmounted candidates.
76
+ */
77
+ readonly getRect?: (item: CollectionItem<Key, Value>) => SpatialNavigationRect | DOMRectReadOnly | null | undefined;
78
+ /** Custom visibility policy for virtualized or scroll-managed collections. */
79
+ readonly scrollIntoView?: (item: CollectionItem<Key, Value>, originalEvent: Event | null) => void;
80
+ /** Called after logical state, DOM focus, and reveal behavior commit. */
81
+ readonly onNavigate?: (change: SpatialNavigationChange<Key>) => void;
82
+ /** Called when a valid origin has no candidate in the requested direction. */
83
+ readonly onBoundary?: (boundary: SpatialNavigationBoundary<Key>) => void;
84
+ }
85
+ /** Stable event adapter for a spatial navigation container. */
86
+ interface SpatialNavigationProps {
87
+ readonly onKeydown: (event: KeyboardEvent) => void;
88
+ }
89
+ /** Geometry-driven navigation controller. */
90
+ interface SpatialNavigationController<Key extends CollectionKey> {
91
+ readonly spatialNavigationProps: Readonly<SpatialNavigationProps>;
92
+ /** Resolve the best candidate without mutating logical or DOM state. */
93
+ readonly findTarget: (direction: SpatialNavigationDirection, fromKey?: Key) => Key | null;
94
+ /** Navigate, returning the committed key or `null` at a boundary. */
95
+ readonly navigate: (direction: SpatialNavigationDirection, originalEvent?: Event | null) => Key | null;
96
+ /** Release scope ownership. The caller-owned registry is not disposed. */
97
+ readonly dispose: () => void;
98
+ }
99
+ //#endregion
100
+ //#region src/spatial-navigation.d.ts
101
+ /** Create a geometry-driven, SSR-safe arrow navigation controller. */
102
+ declare function createSpatialNavigation<Key extends CollectionKey, Value>(options: SpatialNavigationOptions<Key, Value>): SpatialNavigationController<Key>;
103
+ /** Create a spatial controller disposed with the current Vue effect scope. */
104
+ declare function useSpatialNavigation<Key extends CollectionKey, Value>(options: SpatialNavigationOptions<Key, Value>): SpatialNavigationController<Key>;
105
+ //#endregion
106
+ export { SpatialNavigationBoundaryBehavior as a, SpatialNavigationDirection as c, SpatialNavigationProps as d, SpatialNavigationRect as f, SpatialNavigationBoundary as i, SpatialNavigationFocusBehavior as l, useSpatialNavigation as n, SpatialNavigationChange as o, SpatialNavigationAlgorithm as r, SpatialNavigationController as s, createSpatialNavigation as t, SpatialNavigationOptions as u };