@vizejs/ui 0.347.7 → 0.351.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 (96) hide show
  1. package/dist/{button-BMIqJ_M5.d.mts → button-CVX8UBXj.d.mts} +6 -7
  2. package/dist/{button-CaLxP2l2.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-sbhaWekB.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.d.mts +2 -2
  12. package/dist/collection.mjs +1 -1
  13. package/dist/composite-navigation-QINW9GLy.d.mts +115 -0
  14. package/dist/composite-navigation-Skx3LZsv.mjs +354 -0
  15. package/dist/composite-navigation.d.mts +2 -0
  16. package/dist/composite-navigation.mjs +2 -0
  17. package/dist/controllable-state.d.mts +1 -1
  18. package/dist/dismissable-layer-4icKahVs.d.mts +119 -0
  19. package/dist/dismissable-layer-CwG1gtdz.mjs +488 -0
  20. package/dist/dismissable-layer.d.mts +2 -0
  21. package/dist/dismissable-layer.mjs +2 -0
  22. package/dist/focus-CAWi_I-0.mjs +318 -0
  23. package/dist/focus-K6dOifoZ.d.mts +112 -0
  24. package/dist/focus-guards-Bt0C-0qS.d.mts +81 -0
  25. package/dist/focus-guards-DhMPQAT8.mjs +299 -0
  26. package/dist/focus-guards.d.mts +2 -0
  27. package/dist/focus-guards.mjs +2 -0
  28. package/dist/focus-scope-CavhKWx0.d.mts +100 -0
  29. package/dist/focus-scope-D9U1aj67.mjs +340 -0
  30. package/dist/focus-scope-dom-DBwNEWxG.mjs +264 -0
  31. package/dist/focus-scope.d.mts +2 -0
  32. package/dist/focus-scope.mjs +2 -0
  33. package/dist/focus.d.mts +2 -0
  34. package/dist/focus.mjs +2 -0
  35. package/dist/hover-BXwwbSaO.d.mts +80 -0
  36. package/dist/hover.d.mts +2 -0
  37. package/dist/hover.mjs +197 -0
  38. package/dist/{id-BSgJwErt.d.mts → id-5OAUyVPd.d.mts} +2 -3
  39. package/dist/{id-CPBdeoL3.mjs → id-mziSyAse.mjs} +2 -2
  40. package/dist/id.d.mts +2 -2
  41. package/dist/id.mjs +1 -1
  42. package/dist/index.d.mts +22 -11
  43. package/dist/index.mjs +21 -10
  44. package/dist/inert-outside-CyqtoKQ4.mjs +346 -0
  45. package/dist/inert-outside-tuHRmaqJ.d.mts +43 -0
  46. package/dist/inert-outside.d.mts +2 -0
  47. package/dist/inert-outside.mjs +2 -0
  48. package/dist/interaction-modality.d.mts +2 -2
  49. package/dist/interaction-modality.mjs +1 -1
  50. package/dist/long-press-Dsul69gk.mjs +340 -0
  51. package/dist/{long-press-CRjjjJK2.d.mts → long-press-cll6z2K9.d.mts} +8 -18
  52. package/dist/long-press.d.mts +2 -2
  53. package/dist/long-press.mjs +1 -245
  54. package/dist/media-pdf.d.mts +1 -1
  55. package/dist/media-pdf.mjs +1 -1
  56. package/dist/media.d.mts +1 -1
  57. package/dist/media.mjs +1 -1
  58. package/dist/move-BOmXDYbh.d.mts +103 -0
  59. package/dist/move-BVvMHzxr.mjs +386 -0
  60. package/dist/move.d.mts +2 -0
  61. package/dist/move.mjs +2 -0
  62. package/dist/{press-Bp57IOe2.mjs → press-N_mE3Mgx.mjs} +3 -149
  63. package/dist/press-event-Cd2OPpmw.mjs +149 -0
  64. package/dist/press.d.mts +1 -1
  65. package/dist/press.mjs +1 -1
  66. package/dist/{primitive-BE28SwD7.mjs → primitive-BX31dogp.mjs} +2 -2
  67. package/dist/{primitive-Bog8qvd8.d.mts → primitive-C8jW7DLd.d.mts} +3 -4
  68. package/dist/primitive.d.mts +1 -1
  69. package/dist/primitive.mjs +1 -1
  70. package/dist/scroll-lock-BgVtX4wT.d.mts +49 -0
  71. package/dist/scroll-lock-Ckbmm0-J.mjs +313 -0
  72. package/dist/scroll-lock.d.mts +2 -0
  73. package/dist/scroll-lock.mjs +2 -0
  74. package/dist/spatial-navigation-CHj9mDZH.d.mts +106 -0
  75. package/dist/spatial-navigation-D6-UDavU.mjs +301 -0
  76. package/dist/spatial-navigation.d.mts +2 -0
  77. package/dist/spatial-navigation.mjs +2 -0
  78. package/dist/typeahead-B7KDxE_u.mjs +175 -0
  79. package/dist/typeahead-BbgUB2Bj.d.mts +71 -0
  80. package/dist/typeahead.d.mts +2 -0
  81. package/dist/typeahead.mjs +2 -0
  82. package/dist/visually-hidden-BOqfqBFt.d.mts +17 -0
  83. package/dist/{visually-hidden-CTSV3ctZ.mjs → visually-hidden-BwDOx5yf.mjs} +2 -2
  84. package/dist/visually-hidden.d.mts +1 -1
  85. package/dist/visually-hidden.mjs +1 -1
  86. package/package.json +67 -6
  87. package/dist/visually-hidden-CekDwEwR.d.mts +0 -19
  88. /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
  89. /package/dist/{collection-aHZ6Pf0e.d.mts → collection-B_dFZOHO.d.mts} +0 -0
  90. /package/dist/{collection-CoOROaho.mjs → collection-eHN150dT.mjs} +0 -0
  91. /package/dist/{controllable-state-B9v6FClp.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
  92. /package/dist/{interaction-modality-CO-eQzNy.mjs → interaction-modality-DOZK0BpZ.mjs} +0 -0
  93. /package/dist/{interaction-modality-tee79ZBZ.d.mts → interaction-modality-jgHKjPFB.d.mts} +0 -0
  94. /package/dist/{pdf-source-BbZKF_dS.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
  95. /package/dist/{pdf-source-C9zNQd9l.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
  96. /package/dist/{press-types-B8Ssxqg4.d.mts → press-types-CNqStzJf.d.mts} +0 -0
@@ -0,0 +1,149 @@
1
+ import { toValue } from "vue";
2
+ //#region src/press-event.ts
3
+ const invalidOptionDiagnostic = "VIZE_UI_PRESS_OPTION";
4
+ const pointerTypes = new Set([
5
+ "keyboard",
6
+ "mouse",
7
+ "pen",
8
+ "pointer",
9
+ "touch",
10
+ "virtual"
11
+ ]);
12
+ const keyboardBehaviors = new Set([
13
+ "button",
14
+ "link",
15
+ "none"
16
+ ]);
17
+ /** Resolve and validate a reactive boolean option for JavaScript consumers. */
18
+ function readBooleanOption(value, name) {
19
+ const resolved = toValue(value);
20
+ if (resolved === void 0) return false;
21
+ if (typeof resolved !== "boolean") throw new TypeError(`${invalidOptionDiagnostic}: ${name} must resolve to a boolean`);
22
+ return resolved;
23
+ }
24
+ /** Resolve the closed keyboard behavior union without accepting mistyped JS. */
25
+ function readKeyboardBehavior(value) {
26
+ const resolved = toValue(value) ?? "button";
27
+ if (!keyboardBehaviors.has(resolved)) throw new TypeError(`${invalidOptionDiagnostic}: keyboardBehavior must resolve to button, link, or none`);
28
+ return resolved;
29
+ }
30
+ /** Resolve a cross-realm event currentTarget without instanceof assumptions. */
31
+ function eventElement(event) {
32
+ const value = event.currentTarget;
33
+ return value && value.nodeType === 1 ? value : null;
34
+ }
35
+ /** Map Pointer Events' extensible device string to the stable public union. */
36
+ function pointerTypeOf(event) {
37
+ if (event.pointerId === -1 && event.pointerType === "") return "virtual";
38
+ if (event.pointerType === "mouse" || event.pointerType === "pen") return event.pointerType;
39
+ if (event.pointerType === "touch") return "touch";
40
+ return "pointer";
41
+ }
42
+ /** Only a primary contact and its primary button can activate a control. */
43
+ function isPrimaryPointer(event) {
44
+ return event.isPrimary !== false && event.button === 0;
45
+ }
46
+ function eventPoint(event, touchIdentifier = null) {
47
+ if (!event) return null;
48
+ if ("clientX" in event && "clientY" in event) return {
49
+ x: Number(event.clientX),
50
+ y: Number(event.clientY)
51
+ };
52
+ if ("changedTouches" in event) {
53
+ const touches = Array.from(event.changedTouches);
54
+ const touch = (touchIdentifier === null ? touches[0] : touches.find(({ identifier }) => identifier === touchIdentifier)) ?? null;
55
+ if (touch) return {
56
+ x: touch.clientX,
57
+ y: touch.clientY
58
+ };
59
+ }
60
+ return null;
61
+ }
62
+ function modifier(event, key) {
63
+ return event && key in event ? Boolean(event[key]) : false;
64
+ }
65
+ /** Build a frozen snapshot so later browser mutation cannot change callbacks' data. */
66
+ function createPressEvent(type, target, pointerType, originalEvent, isCanceled = false, touchIdentifier = null) {
67
+ if (!pointerTypes.has(pointerType)) throw new TypeError(`${invalidOptionDiagnostic}: invalid press pointer type`);
68
+ const point = eventPoint(originalEvent, touchIdentifier);
69
+ return Object.freeze({
70
+ type,
71
+ pointerType,
72
+ target,
73
+ originalEvent,
74
+ x: point?.x ?? null,
75
+ y: point?.y ?? null,
76
+ altKey: modifier(originalEvent, "altKey"),
77
+ ctrlKey: modifier(originalEvent, "ctrlKey"),
78
+ metaKey: modifier(originalEvent, "metaKey"),
79
+ shiftKey: modifier(originalEvent, "shiftKey"),
80
+ isCanceled
81
+ });
82
+ }
83
+ /** Native elements retain their own activation timing and default actions. */
84
+ function keyboardActivation(target, key, behavior) {
85
+ if (behavior === "none") return null;
86
+ const tag = target.localName;
87
+ if (tag === "a" || tag === "area") {
88
+ if (target.hasAttribute("href")) return key === "Enter" ? "native" : null;
89
+ }
90
+ if (tag === "button") return key === "Enter" || key === " " ? "native" : null;
91
+ if (tag === "summary") return key === "Enter" || key === " " ? "native" : null;
92
+ if (tag === "input") {
93
+ const type = (target.getAttribute("type") ?? "text").toLowerCase();
94
+ if (type === "checkbox" || type === "radio") return key === " " ? "native" : null;
95
+ return new Set([
96
+ "button",
97
+ "file",
98
+ "image",
99
+ "reset",
100
+ "submit"
101
+ ]).has(type) && (key === "Enter" || key === " ") ? "native" : null;
102
+ }
103
+ if (behavior === "link") return key === "Enter" ? "custom" : null;
104
+ return key === "Enter" || key === " " ? "custom" : null;
105
+ }
106
+ /** Determine pointer containment without assuming events originate in one realm. */
107
+ function isEventInside(event, target, touchIdentifier = null) {
108
+ const point = eventPoint(event, touchIdentifier);
109
+ if (point) {
110
+ const hit = target.ownerDocument.elementFromPoint?.(point.x, point.y);
111
+ if (hit) return hit === target || target.contains(hit);
112
+ }
113
+ return event.composedPath().includes(target);
114
+ }
115
+ /** Apply a transient selection guard and return an exact, idempotent restore. */
116
+ function disableTextSelection(target) {
117
+ if (!("style" in target)) return () => void 0;
118
+ const style = target.style;
119
+ if (!style || typeof style.setProperty !== "function") return () => void 0;
120
+ const properties = ["user-select", "-webkit-user-select"];
121
+ const previous = properties.map((property) => ({
122
+ property,
123
+ value: style.getPropertyValue(property),
124
+ priority: style.getPropertyPriority(property)
125
+ }));
126
+ for (const property of properties) style.setProperty(property, "none");
127
+ let restored = false;
128
+ return () => {
129
+ if (restored) return;
130
+ restored = true;
131
+ for (const { property, value, priority } of previous) if (value) style.setProperty(property, value, priority);
132
+ else style.removeProperty(property);
133
+ };
134
+ }
135
+ /** Validate callback slots eagerly so setup failures never install listeners. */
136
+ function validatePressOptions(options) {
137
+ for (const name of [
138
+ "onPress",
139
+ "onPressChange",
140
+ "onPressEnd",
141
+ "onPressStart",
142
+ "onPressUp"
143
+ ]) {
144
+ const callback = options[name];
145
+ if (callback !== void 0 && typeof callback !== "function") throw new TypeError(`${invalidOptionDiagnostic}: ${name} must be a function`);
146
+ }
147
+ }
148
+ //#endregion
149
+ export { isPrimaryPointer as a, readBooleanOption as c, isEventInside as i, readKeyboardBehavior as l, disableTextSelection as n, keyboardActivation as o, eventElement as r, pointerTypeOf as s, createPressEvent as t, validatePressOptions as u };
package/dist/press.d.mts CHANGED
@@ -1,4 +1,4 @@
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-B8Ssxqg4.mjs";
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
2
 
3
3
  //#region src/press.d.ts
4
4
  /**
package/dist/press.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as usePress, t as createPress } from "./press-Bp57IOe2.mjs";
1
+ import { n as usePress, t as createPress } from "./press-N_mE3Mgx.mjs";
2
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-Bog8qvd8.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-BE28SwD7.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 };