@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.
- package/dist/{button-BMIqJ_M5.d.mts → button-CVX8UBXj.d.mts} +6 -7
- package/dist/{button-CaLxP2l2.mjs → button-DT8AKlds.mjs} +2 -2
- package/dist/button.d.mts +1 -1
- package/dist/button.mjs +1 -1
- package/dist/catalog.d.mts +541 -0
- package/dist/catalog.mjs +784 -0
- package/dist/{checkbox-B4y9GUen.mjs → checkbox-BgIvwjyC.mjs} +2 -2
- package/dist/{checkbox-sbhaWekB.d.mts → checkbox-DP3_ko7D.d.mts} +7 -8
- package/dist/checkbox.d.mts +1 -1
- package/dist/checkbox.mjs +1 -1
- package/dist/collection.d.mts +2 -2
- package/dist/collection.mjs +1 -1
- package/dist/composite-navigation-QINW9GLy.d.mts +115 -0
- package/dist/composite-navigation-Skx3LZsv.mjs +354 -0
- package/dist/composite-navigation.d.mts +2 -0
- package/dist/composite-navigation.mjs +2 -0
- package/dist/controllable-state.d.mts +1 -1
- package/dist/dismissable-layer-4icKahVs.d.mts +119 -0
- package/dist/dismissable-layer-CwG1gtdz.mjs +488 -0
- package/dist/dismissable-layer.d.mts +2 -0
- package/dist/dismissable-layer.mjs +2 -0
- package/dist/focus-CAWi_I-0.mjs +318 -0
- package/dist/focus-K6dOifoZ.d.mts +112 -0
- package/dist/focus-guards-Bt0C-0qS.d.mts +81 -0
- package/dist/focus-guards-DhMPQAT8.mjs +299 -0
- package/dist/focus-guards.d.mts +2 -0
- package/dist/focus-guards.mjs +2 -0
- package/dist/focus-scope-CavhKWx0.d.mts +100 -0
- package/dist/focus-scope-D9U1aj67.mjs +340 -0
- package/dist/focus-scope-dom-DBwNEWxG.mjs +264 -0
- package/dist/focus-scope.d.mts +2 -0
- package/dist/focus-scope.mjs +2 -0
- package/dist/focus.d.mts +2 -0
- package/dist/focus.mjs +2 -0
- package/dist/hover-BXwwbSaO.d.mts +80 -0
- package/dist/hover.d.mts +2 -0
- package/dist/hover.mjs +197 -0
- package/dist/{id-BSgJwErt.d.mts → id-5OAUyVPd.d.mts} +2 -3
- package/dist/{id-CPBdeoL3.mjs → id-mziSyAse.mjs} +2 -2
- package/dist/id.d.mts +2 -2
- package/dist/id.mjs +1 -1
- package/dist/index.d.mts +22 -11
- package/dist/index.mjs +21 -10
- package/dist/inert-outside-CyqtoKQ4.mjs +346 -0
- package/dist/inert-outside-tuHRmaqJ.d.mts +43 -0
- package/dist/inert-outside.d.mts +2 -0
- package/dist/inert-outside.mjs +2 -0
- package/dist/interaction-modality.d.mts +2 -2
- package/dist/interaction-modality.mjs +1 -1
- package/dist/long-press-Dsul69gk.mjs +340 -0
- package/dist/{long-press-CRjjjJK2.d.mts → long-press-cll6z2K9.d.mts} +8 -18
- package/dist/long-press.d.mts +2 -2
- package/dist/long-press.mjs +1 -245
- package/dist/media-pdf.d.mts +1 -1
- package/dist/media-pdf.mjs +1 -1
- package/dist/media.d.mts +1 -1
- package/dist/media.mjs +1 -1
- package/dist/move-BOmXDYbh.d.mts +103 -0
- package/dist/move-BVvMHzxr.mjs +386 -0
- package/dist/move.d.mts +2 -0
- package/dist/move.mjs +2 -0
- package/dist/{press-Bp57IOe2.mjs → press-N_mE3Mgx.mjs} +3 -149
- package/dist/press-event-Cd2OPpmw.mjs +149 -0
- package/dist/press.d.mts +1 -1
- package/dist/press.mjs +1 -1
- package/dist/{primitive-BE28SwD7.mjs → primitive-BX31dogp.mjs} +2 -2
- package/dist/{primitive-Bog8qvd8.d.mts → primitive-C8jW7DLd.d.mts} +3 -4
- package/dist/primitive.d.mts +1 -1
- package/dist/primitive.mjs +1 -1
- package/dist/scroll-lock-BgVtX4wT.d.mts +49 -0
- package/dist/scroll-lock-Ckbmm0-J.mjs +313 -0
- package/dist/scroll-lock.d.mts +2 -0
- package/dist/scroll-lock.mjs +2 -0
- package/dist/spatial-navigation-CHj9mDZH.d.mts +106 -0
- package/dist/spatial-navigation-D6-UDavU.mjs +301 -0
- package/dist/spatial-navigation.d.mts +2 -0
- package/dist/spatial-navigation.mjs +2 -0
- package/dist/typeahead-B7KDxE_u.mjs +175 -0
- package/dist/typeahead-BbgUB2Bj.d.mts +71 -0
- package/dist/typeahead.d.mts +2 -0
- package/dist/typeahead.mjs +2 -0
- package/dist/visually-hidden-BOqfqBFt.d.mts +17 -0
- package/dist/{visually-hidden-CTSV3ctZ.mjs → visually-hidden-BwDOx5yf.mjs} +2 -2
- package/dist/visually-hidden.d.mts +1 -1
- package/dist/visually-hidden.mjs +1 -1
- package/package.json +67 -6
- package/dist/visually-hidden-CekDwEwR.d.mts +0 -19
- /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
- /package/dist/{collection-aHZ6Pf0e.d.mts → collection-B_dFZOHO.d.mts} +0 -0
- /package/dist/{collection-CoOROaho.mjs → collection-eHN150dT.mjs} +0 -0
- /package/dist/{controllable-state-B9v6FClp.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
- /package/dist/{interaction-modality-CO-eQzNy.mjs → interaction-modality-DOZK0BpZ.mjs} +0 -0
- /package/dist/{interaction-modality-tee79ZBZ.d.mts → interaction-modality-jgHKjPFB.d.mts} +0 -0
- /package/dist/{pdf-source-BbZKF_dS.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
- /package/dist/{pdf-source-C9zNQd9l.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
- /package/dist/{press-types-B8Ssxqg4.d.mts → press-types-CNqStzJf.d.mts} +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { MaybeRefOrGetter, ShallowRef } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/move-types.d.ts
|
|
4
|
+
/** Input families normalized by the move interaction. */
|
|
5
|
+
type MovePointerType = "keyboard" | "mouse" | "pen" | "pointer" | "touch";
|
|
6
|
+
/** Lifecycle phases emitted by a move controller. */
|
|
7
|
+
type MoveEventType = "move" | "moveend" | "movestart";
|
|
8
|
+
interface MoveEventBase<Type extends MoveEventType> {
|
|
9
|
+
/** Move lifecycle phase represented by this immutable snapshot. */
|
|
10
|
+
readonly type: Type;
|
|
11
|
+
/** Input family that owns this movement. */
|
|
12
|
+
readonly pointerType: MovePointerType;
|
|
13
|
+
/** Element whose bound props own the interaction. */
|
|
14
|
+
readonly target: Element;
|
|
15
|
+
/** Native event responsible for this phase, or `null` for manual cancellation. */
|
|
16
|
+
readonly originalEvent: Event | null;
|
|
17
|
+
/** Page coordinates when supplied by pointing hardware. */
|
|
18
|
+
readonly x: number | null;
|
|
19
|
+
readonly y: number | null;
|
|
20
|
+
/** Modifier-key snapshots captured from the native event. */
|
|
21
|
+
readonly altKey: boolean;
|
|
22
|
+
readonly ctrlKey: boolean;
|
|
23
|
+
readonly metaKey: boolean;
|
|
24
|
+
readonly shiftKey: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Snapshot emitted immediately before the first non-zero movement. */
|
|
27
|
+
interface MoveStartEvent extends MoveEventBase<"movestart"> {
|
|
28
|
+
readonly deltaX: 0;
|
|
29
|
+
readonly deltaY: 0;
|
|
30
|
+
readonly isCanceled: false;
|
|
31
|
+
}
|
|
32
|
+
/** Snapshot of one non-zero movement since the preceding native event. */
|
|
33
|
+
interface MoveUpdateEvent extends MoveEventBase<"move"> {
|
|
34
|
+
readonly deltaX: number;
|
|
35
|
+
readonly deltaY: number;
|
|
36
|
+
readonly isCanceled: false;
|
|
37
|
+
}
|
|
38
|
+
/** Snapshot emitted after a movement completes or is canceled. */
|
|
39
|
+
interface MoveEndEvent extends MoveEventBase<"moveend"> {
|
|
40
|
+
readonly deltaX: 0;
|
|
41
|
+
readonly deltaY: 0;
|
|
42
|
+
readonly isCanceled: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** Discriminated lifecycle event union for exhaustive consumer handling. */
|
|
45
|
+
type MoveEvent = MoveEndEvent | MoveStartEvent | MoveUpdateEvent;
|
|
46
|
+
/** Options shared by {@link createMove} and {@link useMove}. */
|
|
47
|
+
interface MoveOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Suppress new movement and cancel an active pointer movement on its next event.
|
|
50
|
+
*
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
readonly isDisabled?: MaybeRefOrGetter<boolean | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Distance contributed by each physical arrow-key press, including repeat events.
|
|
56
|
+
* The resolved value must be finite and greater than zero.
|
|
57
|
+
*
|
|
58
|
+
* @default 1
|
|
59
|
+
*/
|
|
60
|
+
readonly keyboardStep?: MaybeRefOrGetter<number | undefined>;
|
|
61
|
+
/** Called exactly once before the first non-zero delta in an interaction. */
|
|
62
|
+
readonly onMoveStart?: (event: MoveStartEvent) => void;
|
|
63
|
+
/** Called for every non-zero pointer or keyboard delta. */
|
|
64
|
+
readonly onMove?: (event: MoveUpdateEvent) => void;
|
|
65
|
+
/** Called after an interaction that emitted at least one move finishes. */
|
|
66
|
+
readonly onMoveEnd?: (event: MoveEndEvent) => void;
|
|
67
|
+
}
|
|
68
|
+
/** Native handlers to spread onto exactly one move host. */
|
|
69
|
+
interface MoveProps {
|
|
70
|
+
readonly onDragstart: (event: DragEvent) => void;
|
|
71
|
+
readonly onKeydown: (event: KeyboardEvent) => void;
|
|
72
|
+
readonly onMousedown: (event: MouseEvent) => void;
|
|
73
|
+
readonly onPointercancel: (event: PointerEvent) => void;
|
|
74
|
+
readonly onPointerdown: (event: PointerEvent) => void;
|
|
75
|
+
readonly onTouchcancel: (event: TouchEvent) => void;
|
|
76
|
+
readonly onTouchend: (event: TouchEvent) => void;
|
|
77
|
+
readonly onTouchmove: (event: TouchEvent) => void;
|
|
78
|
+
readonly onTouchstart: (event: TouchEvent) => void;
|
|
79
|
+
}
|
|
80
|
+
/** Stateful move normalizer with explicit listener and selection ownership. */
|
|
81
|
+
interface MoveController {
|
|
82
|
+
/** Whether a pointer or ephemeral keyboard movement is currently being emitted. */
|
|
83
|
+
readonly isMoving: Readonly<ShallowRef<boolean>>;
|
|
84
|
+
/** Stable native handlers to spread or merge onto one host. */
|
|
85
|
+
readonly moveProps: Readonly<MoveProps>;
|
|
86
|
+
/**
|
|
87
|
+
* Cancel the current pointer attempt, including one that has not moved yet.
|
|
88
|
+
*
|
|
89
|
+
* @returns `true` when an owned pointer or keyboard transaction was settled.
|
|
90
|
+
* @throws An error carrying `VIZE_UI_MOVE_DISPOSED` after disposal.
|
|
91
|
+
*/
|
|
92
|
+
readonly cancel: () => boolean;
|
|
93
|
+
/** Release listeners, selection guards, and reactive state without callbacks. */
|
|
94
|
+
readonly dispose: () => void;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/move.d.ts
|
|
98
|
+
/** Create an SSR-safe mouse, pen, touch, and keyboard move normalizer. */
|
|
99
|
+
declare function createMove(options?: MoveOptions): MoveController;
|
|
100
|
+
/** Create a move normalizer disposed with the current Vue effect scope. */
|
|
101
|
+
declare function useMove(options?: MoveOptions): MoveController;
|
|
102
|
+
//#endregion
|
|
103
|
+
export { MoveEvent as a, MovePointerType as c, MoveUpdateEvent as d, MoveEndEvent as i, MoveProps as l, useMove as n, MoveEventType as o, MoveController as r, MoveOptions as s, createMove as t, MoveStartEvent as u };
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { a as isPrimaryPointer, n as disableTextSelection, r as eventElement } from "./press-event-Cd2OPpmw.mjs";
|
|
2
|
+
import { getCurrentScope, onScopeDispose, shallowReadonly, shallowRef, toValue } from "vue";
|
|
3
|
+
//#region src/move-internal.ts
|
|
4
|
+
const invalidOptionDiagnostic = "VIZE_UI_MOVE_OPTION";
|
|
5
|
+
function readBoolean(value) {
|
|
6
|
+
const resolved = toValue(value);
|
|
7
|
+
if (resolved === void 0) return false;
|
|
8
|
+
if (typeof resolved !== "boolean") throw new TypeError(`${invalidOptionDiagnostic}: isDisabled must resolve to a boolean`);
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
function readKeyboardStep(value) {
|
|
12
|
+
const resolved = toValue(value) ?? 1;
|
|
13
|
+
if (typeof resolved !== "number" || !Number.isFinite(resolved) || resolved <= 0) throw new TypeError(`${invalidOptionDiagnostic}: keyboardStep must resolve to a finite number > 0`);
|
|
14
|
+
return resolved;
|
|
15
|
+
}
|
|
16
|
+
function modifier(event, key) {
|
|
17
|
+
return event && key in event ? Boolean(event[key]) : false;
|
|
18
|
+
}
|
|
19
|
+
function positionOf(event, touchId = null) {
|
|
20
|
+
if ("pageX" in event && "pageY" in event) {
|
|
21
|
+
const x = Number(event.pageX);
|
|
22
|
+
const y = Number(event.pageY);
|
|
23
|
+
if (Number.isFinite(x) && Number.isFinite(y)) return {
|
|
24
|
+
x,
|
|
25
|
+
y
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if ("clientX" in event && "clientY" in event) {
|
|
29
|
+
const x = Number(event.clientX);
|
|
30
|
+
const y = Number(event.clientY);
|
|
31
|
+
if (Number.isFinite(x) && Number.isFinite(y)) return {
|
|
32
|
+
x,
|
|
33
|
+
y
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if ("changedTouches" in event) {
|
|
37
|
+
const touch = Array.from(event.changedTouches).find(({ identifier }) => touchId === null || identifier === touchId);
|
|
38
|
+
if (touch) return {
|
|
39
|
+
x: touch.pageX,
|
|
40
|
+
y: touch.pageY
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
function pointerTypeOf(event) {
|
|
46
|
+
if (event.pointerType === "mouse" || event.pointerType === "pen") return event.pointerType;
|
|
47
|
+
if (event.pointerType === "touch") return "touch";
|
|
48
|
+
return "pointer";
|
|
49
|
+
}
|
|
50
|
+
function createMoveEvent(type, target, pointerType, originalEvent, deltaX = 0, deltaY = 0, isCanceled = false, touchId = null) {
|
|
51
|
+
const position = originalEvent ? positionOf(originalEvent, touchId) : null;
|
|
52
|
+
return Object.freeze({
|
|
53
|
+
type,
|
|
54
|
+
pointerType,
|
|
55
|
+
target,
|
|
56
|
+
originalEvent,
|
|
57
|
+
x: position?.x ?? null,
|
|
58
|
+
y: position?.y ?? null,
|
|
59
|
+
deltaX,
|
|
60
|
+
deltaY,
|
|
61
|
+
altKey: modifier(originalEvent, "altKey"),
|
|
62
|
+
ctrlKey: modifier(originalEvent, "ctrlKey"),
|
|
63
|
+
metaKey: modifier(originalEvent, "metaKey"),
|
|
64
|
+
shiftKey: modifier(originalEvent, "shiftKey"),
|
|
65
|
+
isCanceled
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function surfaceErrors(errors, message) {
|
|
69
|
+
if (errors.length === 1) throw errors[0];
|
|
70
|
+
if (errors.length < 2) return;
|
|
71
|
+
const Aggregate = globalThis.AggregateError;
|
|
72
|
+
if (typeof Aggregate === "function") throw new Aggregate(errors, message);
|
|
73
|
+
const fallback = Object.assign(new Error(message), { errors: [...errors] });
|
|
74
|
+
fallback.name = "AggregateError";
|
|
75
|
+
throw fallback;
|
|
76
|
+
}
|
|
77
|
+
function capture(errors, callback) {
|
|
78
|
+
try {
|
|
79
|
+
callback();
|
|
80
|
+
} catch (error) {
|
|
81
|
+
errors.push(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function validateOptions(options) {
|
|
85
|
+
for (const name of [
|
|
86
|
+
"onMove",
|
|
87
|
+
"onMoveEnd",
|
|
88
|
+
"onMoveStart"
|
|
89
|
+
]) {
|
|
90
|
+
const callback = options[name];
|
|
91
|
+
if (callback !== void 0 && typeof callback !== "function") throw new TypeError(`${invalidOptionDiagnostic}: ${name} must be a function`);
|
|
92
|
+
}
|
|
93
|
+
if (typeof options.keyboardStep !== "function") readKeyboardStep(options.keyboardStep);
|
|
94
|
+
}
|
|
95
|
+
/** Install and exhaustively clean up the document listeners for one pointer family. */
|
|
96
|
+
function installMoveListeners(document, source, context) {
|
|
97
|
+
const removals = [];
|
|
98
|
+
const listen = (owner, type, callback, capture = true) => {
|
|
99
|
+
owner.addEventListener(type, callback, capture);
|
|
100
|
+
removals.push(() => owner.removeEventListener(type, callback, capture));
|
|
101
|
+
};
|
|
102
|
+
const matches = (family, id) => {
|
|
103
|
+
const current = context.getActive();
|
|
104
|
+
return current?.source === family && current.id === id ? current : null;
|
|
105
|
+
};
|
|
106
|
+
const pointerMove = (event) => {
|
|
107
|
+
const current = matches("pointer", event.pointerId);
|
|
108
|
+
const position = positionOf(event);
|
|
109
|
+
if (current && position) context.emitDelta(current, event, position);
|
|
110
|
+
};
|
|
111
|
+
const pointerEnd = (event, canceled) => {
|
|
112
|
+
const current = matches("pointer", event.pointerId);
|
|
113
|
+
if (!current) return;
|
|
114
|
+
const disabled = context.readDisabled(event);
|
|
115
|
+
context.finish(event, canceled || disabled || !current.target.isConnected);
|
|
116
|
+
};
|
|
117
|
+
const mouseMove = (event) => {
|
|
118
|
+
const current = matches("mouse", null);
|
|
119
|
+
const position = positionOf(event);
|
|
120
|
+
if (current && position) context.emitDelta(current, event, position);
|
|
121
|
+
};
|
|
122
|
+
const mouseUp = (event) => {
|
|
123
|
+
const current = matches("mouse", null);
|
|
124
|
+
if (event.button === 0 && current) context.finish(event, context.readDisabled(event) || !current.target.isConnected);
|
|
125
|
+
};
|
|
126
|
+
const touchMove = (event) => {
|
|
127
|
+
const candidate = context.getActive();
|
|
128
|
+
const current = candidate?.source === "touch" ? candidate : null;
|
|
129
|
+
const position = current ? positionOf(event, current.id) : null;
|
|
130
|
+
if (current && position) context.emitDelta(current, event, position);
|
|
131
|
+
};
|
|
132
|
+
const touchEnd = (event, canceled) => {
|
|
133
|
+
const candidate = context.getActive();
|
|
134
|
+
const current = candidate?.source === "touch" ? candidate : null;
|
|
135
|
+
if (!current || !positionOf(event, current.id)) return;
|
|
136
|
+
context.rememberTouch(event.timeStamp);
|
|
137
|
+
context.finish(event, canceled || context.readDisabled(event) || !current.target.isConnected);
|
|
138
|
+
};
|
|
139
|
+
try {
|
|
140
|
+
if (source === "pointer") {
|
|
141
|
+
listen(document, "pointermove", pointerMove);
|
|
142
|
+
listen(document, "pointerup", ((event) => pointerEnd(event, false)));
|
|
143
|
+
listen(document, "pointercancel", ((event) => pointerEnd(event, true)));
|
|
144
|
+
} else if (source === "mouse") {
|
|
145
|
+
listen(document, "mousemove", mouseMove);
|
|
146
|
+
listen(document, "mouseup", mouseUp);
|
|
147
|
+
} else {
|
|
148
|
+
listen(document, "touchmove", touchMove);
|
|
149
|
+
listen(document, "touchend", ((event) => touchEnd(event, false)));
|
|
150
|
+
listen(document, "touchcancel", ((event) => touchEnd(event, true)));
|
|
151
|
+
}
|
|
152
|
+
listen(document, "dragstart", (event) => context.finish(event, true));
|
|
153
|
+
listen(document, "visibilitychange", (() => {
|
|
154
|
+
if (document.visibilityState === "hidden") context.finish(null, true);
|
|
155
|
+
}));
|
|
156
|
+
if (document.defaultView) listen(document.defaultView, "blur", (event) => context.finish(event, true), false);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
const errors = [error];
|
|
159
|
+
for (const remove of removals.reverse()) capture(errors, remove);
|
|
160
|
+
surfaceErrors(errors, "Move listener setup failed");
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
let released = false;
|
|
164
|
+
return () => {
|
|
165
|
+
if (released) return;
|
|
166
|
+
released = true;
|
|
167
|
+
const errors = [];
|
|
168
|
+
for (const remove of removals) capture(errors, remove);
|
|
169
|
+
surfaceErrors(errors, "Move listener cleanup failed");
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/move.ts
|
|
174
|
+
const disposedDiagnostic = "VIZE_UI_MOVE_DISPOSED";
|
|
175
|
+
const setupDiagnostic = "VIZE_UI_MOVE_SETUP";
|
|
176
|
+
/** Create an SSR-safe mouse, pen, touch, and keyboard move normalizer. */
|
|
177
|
+
function createMove(options = {}) {
|
|
178
|
+
validateOptions(options);
|
|
179
|
+
const moving = shallowRef(false);
|
|
180
|
+
let active = null;
|
|
181
|
+
let keyboard = null;
|
|
182
|
+
let disposed = false;
|
|
183
|
+
let lastTouchTime = Number.NEGATIVE_INFINITY;
|
|
184
|
+
const finish = (originalEvent, isCanceled) => {
|
|
185
|
+
const current = active;
|
|
186
|
+
if (!current) return false;
|
|
187
|
+
active = null;
|
|
188
|
+
moving.value = false;
|
|
189
|
+
const errors = [];
|
|
190
|
+
capture(errors, current.releaseListeners);
|
|
191
|
+
capture(errors, current.restoreSelection);
|
|
192
|
+
if (current.didMove) capture(errors, () => options.onMoveEnd?.(createMoveEvent("moveend", current.target, current.pointerType, originalEvent, 0, 0, isCanceled, current.source === "touch" ? current.id : null)));
|
|
193
|
+
surfaceErrors(errors, "Move completion failed");
|
|
194
|
+
return true;
|
|
195
|
+
};
|
|
196
|
+
const readDisabledDuringActive = (event) => {
|
|
197
|
+
try {
|
|
198
|
+
return readBoolean(options.isDisabled);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
const errors = [error];
|
|
201
|
+
capture(errors, () => finish(event, true));
|
|
202
|
+
surfaceErrors(errors, "Move option validation failed during teardown");
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const finishKeyboard = (originalEvent, isCanceled) => {
|
|
207
|
+
const current = keyboard;
|
|
208
|
+
if (!current) return false;
|
|
209
|
+
keyboard = null;
|
|
210
|
+
moving.value = false;
|
|
211
|
+
options.onMoveEnd?.(createMoveEvent("moveend", current.target, "keyboard", originalEvent, 0, 0, isCanceled));
|
|
212
|
+
return true;
|
|
213
|
+
};
|
|
214
|
+
const emitDelta = (current, event, position) => {
|
|
215
|
+
if (active !== current) return;
|
|
216
|
+
current.lastEvent = event;
|
|
217
|
+
if (readDisabledDuringActive(event) || !current.target.isConnected) {
|
|
218
|
+
finish(event, true);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const deltaX = position.x - current.position.x;
|
|
222
|
+
const deltaY = position.y - current.position.y;
|
|
223
|
+
current.position = position;
|
|
224
|
+
if (deltaX === 0 && deltaY === 0) return;
|
|
225
|
+
event.preventDefault();
|
|
226
|
+
const errors = [];
|
|
227
|
+
if (!current.didMove) {
|
|
228
|
+
current.didMove = true;
|
|
229
|
+
moving.value = true;
|
|
230
|
+
capture(errors, () => options.onMoveStart?.(createMoveEvent("movestart", current.target, current.pointerType, event, 0, 0, false, current.source === "touch" ? current.id : null)));
|
|
231
|
+
}
|
|
232
|
+
if (active === current && !disposed) capture(errors, () => options.onMove?.(createMoveEvent("move", current.target, current.pointerType, event, deltaX, deltaY, false, current.source === "touch" ? current.id : null)));
|
|
233
|
+
surfaceErrors(errors, "Move callbacks failed");
|
|
234
|
+
};
|
|
235
|
+
const matches = (source, id) => {
|
|
236
|
+
const current = active;
|
|
237
|
+
return current?.source === source && current.id === id ? current : null;
|
|
238
|
+
};
|
|
239
|
+
const start = (event, source, pointerType, id, position) => {
|
|
240
|
+
if (disposed || active || readBoolean(options.isDisabled)) return;
|
|
241
|
+
const target = eventElement(event);
|
|
242
|
+
if (!target) return;
|
|
243
|
+
event.preventDefault();
|
|
244
|
+
event.stopPropagation();
|
|
245
|
+
let releaseListeners = () => void 0;
|
|
246
|
+
let restoreSelection = () => void 0;
|
|
247
|
+
try {
|
|
248
|
+
releaseListeners = installMoveListeners(target.ownerDocument, source, {
|
|
249
|
+
emitDelta,
|
|
250
|
+
finish,
|
|
251
|
+
getActive: () => active,
|
|
252
|
+
readDisabled: readDisabledDuringActive,
|
|
253
|
+
rememberTouch: (timeStamp) => {
|
|
254
|
+
lastTouchTime = timeStamp;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
restoreSelection = disableTextSelection(target);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
const errors = [error];
|
|
260
|
+
capture(errors, releaseListeners);
|
|
261
|
+
capture(errors, restoreSelection);
|
|
262
|
+
surfaceErrors(errors, "Move start cleanup failed");
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
active = {
|
|
266
|
+
id,
|
|
267
|
+
pointerType,
|
|
268
|
+
releaseListeners,
|
|
269
|
+
restoreSelection,
|
|
270
|
+
source,
|
|
271
|
+
target,
|
|
272
|
+
didMove: false,
|
|
273
|
+
lastEvent: event,
|
|
274
|
+
position
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
const keyboardMove = (event, deltaX, deltaY) => {
|
|
278
|
+
if (disposed || active || keyboard || readBoolean(options.isDisabled)) return;
|
|
279
|
+
const target = eventElement(event);
|
|
280
|
+
if (!target || event.target !== target) return;
|
|
281
|
+
event.preventDefault();
|
|
282
|
+
event.stopPropagation();
|
|
283
|
+
const step = readKeyboardStep(options.keyboardStep);
|
|
284
|
+
const errors = [];
|
|
285
|
+
const current = { target };
|
|
286
|
+
keyboard = current;
|
|
287
|
+
moving.value = true;
|
|
288
|
+
capture(errors, () => options.onMoveStart?.(createMoveEvent("movestart", target, "keyboard", event)));
|
|
289
|
+
if (keyboard === current && !disposed) capture(errors, () => options.onMove?.(createMoveEvent("move", target, "keyboard", event, deltaX * step, deltaY * step)));
|
|
290
|
+
if (keyboard === current && !disposed) capture(errors, () => finishKeyboard(event, false));
|
|
291
|
+
surfaceErrors(errors, "Keyboard move callbacks failed");
|
|
292
|
+
};
|
|
293
|
+
const moveProps = Object.freeze({
|
|
294
|
+
onDragstart(event) {
|
|
295
|
+
if (active?.target === eventElement(event)) finish(event, true);
|
|
296
|
+
},
|
|
297
|
+
onKeydown(event) {
|
|
298
|
+
if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;
|
|
299
|
+
switch (event.key) {
|
|
300
|
+
case "Left":
|
|
301
|
+
case "ArrowLeft":
|
|
302
|
+
keyboardMove(event, -1, 0);
|
|
303
|
+
break;
|
|
304
|
+
case "Right":
|
|
305
|
+
case "ArrowRight":
|
|
306
|
+
keyboardMove(event, 1, 0);
|
|
307
|
+
break;
|
|
308
|
+
case "Up":
|
|
309
|
+
case "ArrowUp":
|
|
310
|
+
keyboardMove(event, 0, -1);
|
|
311
|
+
break;
|
|
312
|
+
case "Down":
|
|
313
|
+
case "ArrowDown":
|
|
314
|
+
keyboardMove(event, 0, 1);
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
onMousedown(event) {
|
|
319
|
+
if (event.button !== 0 || active || event.view && "PointerEvent" in event.view) return;
|
|
320
|
+
const elapsed = event.timeStamp - lastTouchTime;
|
|
321
|
+
if (elapsed >= 0 && elapsed < 800) return;
|
|
322
|
+
const position = positionOf(event);
|
|
323
|
+
if (position) start(event, "mouse", "mouse", null, position);
|
|
324
|
+
},
|
|
325
|
+
onPointercancel(event) {
|
|
326
|
+
if (matches("pointer", event.pointerId)) finish(event, true);
|
|
327
|
+
},
|
|
328
|
+
onPointerdown(event) {
|
|
329
|
+
if (!isPrimaryPointer(event)) return;
|
|
330
|
+
const position = positionOf(event);
|
|
331
|
+
if (position) start(event, "pointer", pointerTypeOf(event), event.pointerId, position);
|
|
332
|
+
},
|
|
333
|
+
onTouchcancel(event) {
|
|
334
|
+
const current = active?.source === "touch" ? active : null;
|
|
335
|
+
if (current && positionOf(event, current.id)) finish(event, true);
|
|
336
|
+
},
|
|
337
|
+
onTouchend(event) {
|
|
338
|
+
const current = active?.source === "touch" ? active : null;
|
|
339
|
+
if (current && positionOf(event, current.id)) finish(event, false);
|
|
340
|
+
},
|
|
341
|
+
onTouchmove(event) {
|
|
342
|
+
const current = active?.source === "touch" ? active : null;
|
|
343
|
+
const position = current ? positionOf(event, current.id) : null;
|
|
344
|
+
if (current && position) emitDelta(current, event, position);
|
|
345
|
+
},
|
|
346
|
+
onTouchstart(event) {
|
|
347
|
+
lastTouchTime = event.timeStamp;
|
|
348
|
+
if (event.view && "PointerEvent" in event.view || active || event.changedTouches.length !== 1) return;
|
|
349
|
+
const touch = event.changedTouches.item(0);
|
|
350
|
+
if (touch) start(event, "touch", "touch", touch.identifier, {
|
|
351
|
+
x: touch.pageX,
|
|
352
|
+
y: touch.pageY
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
return Object.freeze({
|
|
357
|
+
isMoving: shallowReadonly(moving),
|
|
358
|
+
moveProps,
|
|
359
|
+
cancel: () => {
|
|
360
|
+
if (disposed) throw new Error(`${disposedDiagnostic}: the controller has been disposed`);
|
|
361
|
+
return finish(null, true) || finishKeyboard(null, true);
|
|
362
|
+
},
|
|
363
|
+
dispose: () => {
|
|
364
|
+
if (disposed) return;
|
|
365
|
+
disposed = true;
|
|
366
|
+
const current = active;
|
|
367
|
+
active = null;
|
|
368
|
+
keyboard = null;
|
|
369
|
+
moving.value = false;
|
|
370
|
+
if (!current) return;
|
|
371
|
+
const errors = [];
|
|
372
|
+
capture(errors, current.releaseListeners);
|
|
373
|
+
capture(errors, current.restoreSelection);
|
|
374
|
+
surfaceErrors(errors, "Move disposal failed");
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
/** Create a move normalizer disposed with the current Vue effect scope. */
|
|
379
|
+
function useMove(options = {}) {
|
|
380
|
+
if (!getCurrentScope()) throw new Error(`${setupDiagnostic}: use inside component setup or an active effect scope`);
|
|
381
|
+
const controller = createMove(options);
|
|
382
|
+
onScopeDispose(controller.dispose);
|
|
383
|
+
return controller;
|
|
384
|
+
}
|
|
385
|
+
//#endregion
|
|
386
|
+
export { useMove as n, createMove as t };
|
package/dist/move.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as MoveEvent, c as MovePointerType, d as MoveUpdateEvent, i as MoveEndEvent, l as MoveProps, n as useMove, o as MoveEventType, r as MoveController, s as MoveOptions, t as createMove, u as MoveStartEvent } from "./move-BOmXDYbh.mjs";
|
|
2
|
+
export { type MoveController, type MoveEndEvent, type MoveEvent, type MoveEventType, type MoveOptions, type MovePointerType, type MoveProps, type MoveStartEvent, type MoveUpdateEvent, createMove, useMove };
|
package/dist/move.mjs
ADDED
|
@@ -1,151 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
|
1
|
+
import { a as isPrimaryPointer, c as readBooleanOption, i as isEventInside, l as readKeyboardBehavior, n as disableTextSelection, o as keyboardActivation, r as eventElement, s as pointerTypeOf, t as createPressEvent, u as validatePressOptions } from "./press-event-Cd2OPpmw.mjs";
|
|
2
|
+
import { getCurrentScope, onScopeDispose, shallowReadonly, shallowRef } from "vue";
|
|
149
3
|
//#region src/press-handlers.ts
|
|
150
4
|
/** Adapt Pointer Events plus legacy mouse/touch and keyboard events to one lifecycle. */
|
|
151
5
|
function createPressHandlers(lifecycle) {
|
|
@@ -612,4 +466,4 @@ function usePress(options = {}) {
|
|
|
612
466
|
return controller;
|
|
613
467
|
}
|
|
614
468
|
//#endregion
|
|
615
|
-
export {
|
|
469
|
+
export { usePress as n, createPress as t };
|