Move components.ts into many SFC files
This commit is contained in:
104
packages/core/src/components/NativeGestureLink.vue
Executable file
104
packages/core/src/components/NativeGestureLink.vue
Executable file
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, ref, useAttrs, type PropType } from "vue";
|
||||
import type { RouteLocationRaw } from "vue-router";
|
||||
import type { NativePresentationName } from "../types";
|
||||
import { createPointerGesture, sourceRect } from "./gestures";
|
||||
import { useNativeRouter } from "./lifecycle";
|
||||
|
||||
defineOptions({ name: "NativeGestureLink", inheritAttrs: false });
|
||||
|
||||
const props = defineProps({
|
||||
to: {
|
||||
type: [String, Object] as PropType<RouteLocationRaw>,
|
||||
required: true,
|
||||
},
|
||||
presentation: {
|
||||
type: String as PropType<NativePresentationName>,
|
||||
default: "reveal",
|
||||
},
|
||||
replace: Boolean,
|
||||
direction: {
|
||||
type: String as PropType<"left" | "right" | "any">,
|
||||
default: "any",
|
||||
},
|
||||
as: { type: String, default: "div" },
|
||||
});
|
||||
const attrs = useAttrs();
|
||||
const passthroughAttrs = computed(() => {
|
||||
const result = { ...attrs };
|
||||
delete result.onPointerdown;
|
||||
delete result.onPointermove;
|
||||
delete result.onPointerup;
|
||||
delete result.onPointercancel;
|
||||
delete result.onClick;
|
||||
return result;
|
||||
});
|
||||
const runtime = useNativeRouter();
|
||||
const root = ref<HTMLElement | null>(null);
|
||||
let dragDistance = 0;
|
||||
let suppressClick = false;
|
||||
|
||||
const gesture = createPointerGesture(
|
||||
() => root.value,
|
||||
runtime,
|
||||
async (direction) =>
|
||||
runtime.beginInteractive("push", props.to, {
|
||||
presentation: props.presentation,
|
||||
replace: props.replace,
|
||||
direction,
|
||||
sourceRect: root.value ? sourceRect(root.value) : undefined,
|
||||
}),
|
||||
(dx) => {
|
||||
if (props.direction === "left" && dx >= 0) return null;
|
||||
if (props.direction === "right" && dx <= 0) return null;
|
||||
return dx < 0 ? "forward" : "back";
|
||||
},
|
||||
);
|
||||
|
||||
onBeforeUnmount(() => void runtime.cancelInteractive());
|
||||
|
||||
function pointerDown(event: PointerEvent) {
|
||||
// Component-owned gestures outrank their containing navigator.
|
||||
event.stopPropagation();
|
||||
dragDistance = 0;
|
||||
suppressClick = false;
|
||||
gesture.down(event);
|
||||
}
|
||||
|
||||
function pointerMove(event: PointerEvent) {
|
||||
if (event.buttons) {
|
||||
dragDistance += Math.abs(event.movementX);
|
||||
if (dragDistance > 8) suppressClick = true;
|
||||
}
|
||||
void gesture.move(event);
|
||||
}
|
||||
|
||||
function click(event: MouseEvent) {
|
||||
if (suppressClick) {
|
||||
suppressClick = false;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
void runtime.push(props.to, {
|
||||
presentation: props.presentation,
|
||||
replace: props.replace,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="as"
|
||||
ref="root"
|
||||
v-bind="passthroughAttrs"
|
||||
class="nvr-gesture-link"
|
||||
@pointerdown="pointerDown"
|
||||
@pointermove="pointerMove"
|
||||
@pointerup="gesture.up"
|
||||
@pointercancel="gesture.cancel"
|
||||
@click="click"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
Reference in New Issue
Block a user