@v-c/tabs 0.0.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.
- package/LICENSE +21 -0
- package/dist/TabContext.cjs +11 -0
- package/dist/TabContext.d.ts +8 -0
- package/dist/TabContext.js +9 -0
- package/dist/TabNavList/AddButton.cjs +4 -0
- package/dist/TabNavList/AddButton.js +3 -0
- package/dist/TabNavList/AddButton.vue_vue_type_script_setup_true_lang.cjs +36 -0
- package/dist/TabNavList/AddButton.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/TabNavList/ExtraContent.cjs +4 -0
- package/dist/TabNavList/ExtraContent.js +3 -0
- package/dist/TabNavList/ExtraContent.vue_vue_type_script_setup_true_lang.cjs +51 -0
- package/dist/TabNavList/ExtraContent.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/TabNavList/OperationNode.cjs +4 -0
- package/dist/TabNavList/OperationNode.js +3 -0
- package/dist/TabNavList/OperationNode.vue_vue_type_script_setup_true_lang.cjs +210 -0
- package/dist/TabNavList/OperationNode.vue_vue_type_script_setup_true_lang.js +205 -0
- package/dist/TabNavList/TabNode.cjs +4 -0
- package/dist/TabNavList/TabNode.js +3 -0
- package/dist/TabNavList/TabNode.vue_vue_type_script_setup_true_lang.cjs +129 -0
- package/dist/TabNavList/TabNode.vue_vue_type_script_setup_true_lang.js +127 -0
- package/dist/TabNavList/Wrapper.cjs +4 -0
- package/dist/TabNavList/Wrapper.js +3 -0
- package/dist/TabNavList/Wrapper.vue_vue_type_script_setup_true_lang.cjs +54 -0
- package/dist/TabNavList/Wrapper.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/TabNavList/index.cjs +4 -0
- package/dist/TabNavList/index.js +3 -0
- package/dist/TabNavList/index.vue_vue_type_script_setup_true_lang.cjs +516 -0
- package/dist/TabNavList/index.vue_vue_type_script_setup_true_lang.js +513 -0
- package/dist/TabPanelList/TabPane.cjs +4 -0
- package/dist/TabPanelList/TabPane.js +3 -0
- package/dist/TabPanelList/TabPane.vue_vue_type_script_setup_true_lang.cjs +85 -0
- package/dist/TabPanelList/TabPane.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/TabPanelList/index.cjs +4 -0
- package/dist/TabPanelList/index.js +3 -0
- package/dist/TabPanelList/index.vue_vue_type_script_setup_true_lang.cjs +105 -0
- package/dist/TabPanelList/index.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/Tabs.cjs +4 -0
- package/dist/Tabs.js +3 -0
- package/dist/Tabs.vue_vue_type_script_setup_true_lang.cjs +194 -0
- package/dist/Tabs.vue_vue_type_script_setup_true_lang.js +190 -0
- package/dist/_virtual/rolldown_runtime.cjs +21 -0
- package/dist/hooks/useAnimateConfig.cjs +28 -0
- package/dist/hooks/useAnimateConfig.d.ts +2 -0
- package/dist/hooks/useAnimateConfig.js +26 -0
- package/dist/hooks/useIndicator.cjs +68 -0
- package/dist/hooks/useIndicator.d.ts +11 -0
- package/dist/hooks/useIndicator.js +65 -0
- package/dist/hooks/useOffsets.cjs +39 -0
- package/dist/hooks/useOffsets.d.ts +18 -0
- package/dist/hooks/useOffsets.js +37 -0
- package/dist/hooks/useTouchMove.cjs +119 -0
- package/dist/hooks/useTouchMove.d.ts +2 -0
- package/dist/hooks/useTouchMove.js +117 -0
- package/dist/hooks/useVisibleRange.cjs +51 -0
- package/dist/hooks/useVisibleRange.d.ts +17 -0
- package/dist/hooks/useVisibleRange.js +49 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/interface.cjs +0 -0
- package/dist/interface.d.ts +195 -0
- package/dist/interface.js +0 -0
- package/dist/utils.cjs +33 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.js +27 -0
- package/package.json +44 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { warning } from "@v-c/util/dist/warning";
|
|
2
|
+
function useAnimateConfig(animated = {
|
|
3
|
+
inkBar: true,
|
|
4
|
+
tabPane: false
|
|
5
|
+
}) {
|
|
6
|
+
let mergedAnimated;
|
|
7
|
+
if (animated === false) mergedAnimated = {
|
|
8
|
+
inkBar: false,
|
|
9
|
+
tabPane: false
|
|
10
|
+
};
|
|
11
|
+
else if (animated === true) mergedAnimated = {
|
|
12
|
+
inkBar: true,
|
|
13
|
+
tabPane: false
|
|
14
|
+
};
|
|
15
|
+
else mergedAnimated = {
|
|
16
|
+
inkBar: true,
|
|
17
|
+
...typeof animated === "object" ? animated : {}
|
|
18
|
+
};
|
|
19
|
+
if (mergedAnimated.tabPaneMotion && mergedAnimated.tabPane === void 0) mergedAnimated.tabPane = true;
|
|
20
|
+
if (!mergedAnimated.tabPaneMotion && mergedAnimated.tabPane) {
|
|
21
|
+
if (process.env.NODE_ENV !== "production") warning(false, "`animated.tabPane` is true but `animated.tabPaneMotion` is not provided. Motion will not work.");
|
|
22
|
+
mergedAnimated.tabPane = false;
|
|
23
|
+
}
|
|
24
|
+
return mergedAnimated;
|
|
25
|
+
}
|
|
26
|
+
export { useAnimateConfig as default };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
let __v_c_util_dist_raf = require("@v-c/util/dist/raf");
|
|
5
|
+
__v_c_util_dist_raf = require_rolldown_runtime.__toESM(__v_c_util_dist_raf);
|
|
6
|
+
function useIndicator(options) {
|
|
7
|
+
const { activeTabOffset, horizontal, rtl, indicator } = options;
|
|
8
|
+
const inkStyle = (0, vue.ref)();
|
|
9
|
+
const inkBarRafRef = (0, vue.ref)();
|
|
10
|
+
const getLength = (origin) => {
|
|
11
|
+
const size = indicator?.value?.size;
|
|
12
|
+
if (typeof size === "function") return size(origin);
|
|
13
|
+
if (typeof size === "number") return size;
|
|
14
|
+
return origin;
|
|
15
|
+
};
|
|
16
|
+
function cleanInkBarRaf() {
|
|
17
|
+
if (!inkBarRafRef.value) return;
|
|
18
|
+
__v_c_util_dist_raf.default.cancel(inkBarRafRef.value);
|
|
19
|
+
}
|
|
20
|
+
(0, vue.watch)([
|
|
21
|
+
() => activeTabOffset.value,
|
|
22
|
+
() => horizontal.value,
|
|
23
|
+
() => rtl.value,
|
|
24
|
+
() => indicator?.value
|
|
25
|
+
], async (_n, _o) => {
|
|
26
|
+
await (0, vue.nextTick)();
|
|
27
|
+
const align = indicator?.value?.align || "center";
|
|
28
|
+
const newInkStyle = {};
|
|
29
|
+
if (activeTabOffset.value) if (horizontal.value) {
|
|
30
|
+
newInkStyle.width = `${getLength(activeTabOffset.value.width)}px`;
|
|
31
|
+
const key = rtl.value ? "right" : "left";
|
|
32
|
+
if (align === "start") newInkStyle[key] = `${activeTabOffset.value[key]}px`;
|
|
33
|
+
if (align === "center") {
|
|
34
|
+
newInkStyle[key] = `${activeTabOffset.value[key] + activeTabOffset.value.width / 2}px`;
|
|
35
|
+
newInkStyle.transform = rtl.value ? "translateX(50%)" : "translateX(-50%)";
|
|
36
|
+
}
|
|
37
|
+
if (align === "end") {
|
|
38
|
+
newInkStyle[key] = `${activeTabOffset.value[key] + activeTabOffset.value.width}px`;
|
|
39
|
+
newInkStyle.transform = "translateX(-100%)";
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
newInkStyle.height = `${getLength(activeTabOffset.value.height)}px`;
|
|
43
|
+
if (align === "start") newInkStyle.top = `${activeTabOffset.value.top}px`;
|
|
44
|
+
if (align === "center") {
|
|
45
|
+
newInkStyle.top = `${activeTabOffset.value.top + activeTabOffset.value.height / 2}px`;
|
|
46
|
+
newInkStyle.transform = "translateY(-50%)";
|
|
47
|
+
}
|
|
48
|
+
if (align === "end") {
|
|
49
|
+
newInkStyle.top = `${activeTabOffset.value.top + activeTabOffset.value.height}px`;
|
|
50
|
+
newInkStyle.transform = "translateY(-100%)";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
cleanInkBarRaf();
|
|
54
|
+
inkBarRafRef.value = (0, __v_c_util_dist_raf.default)(() => {
|
|
55
|
+
if (!(inkStyle.value && newInkStyle && Object.keys(newInkStyle).every((key) => {
|
|
56
|
+
const newValue = newInkStyle[key];
|
|
57
|
+
const oldValue = inkStyle.value?.[key];
|
|
58
|
+
return typeof newValue === "number" && typeof oldValue === "number" ? Math.round(newValue) === Math.round(oldValue) : newValue === oldValue;
|
|
59
|
+
}))) inkStyle.value = newInkStyle;
|
|
60
|
+
});
|
|
61
|
+
}, { immediate: true });
|
|
62
|
+
(0, vue.onUnmounted)(() => {
|
|
63
|
+
cleanInkBarRaf();
|
|
64
|
+
});
|
|
65
|
+
return inkStyle;
|
|
66
|
+
}
|
|
67
|
+
var useIndicator_default = useIndicator;
|
|
68
|
+
exports.default = useIndicator_default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ComputedRef, CSSProperties, Ref } from 'vue';
|
|
2
|
+
import { IndicatorConfig } from '../interface';
|
|
3
|
+
import { TabOffset } from './useOffsets';
|
|
4
|
+
interface UseIndicatorOptions {
|
|
5
|
+
activeTabOffset: ComputedRef<TabOffset> | Ref<TabOffset>;
|
|
6
|
+
horizontal: ComputedRef<boolean> | Ref<boolean>;
|
|
7
|
+
rtl: ComputedRef<boolean> | Ref<boolean>;
|
|
8
|
+
indicator?: ComputedRef<IndicatorConfig | undefined> | Ref<IndicatorConfig | undefined>;
|
|
9
|
+
}
|
|
10
|
+
declare function useIndicator(options: UseIndicatorOptions): Ref<CSSProperties | undefined, CSSProperties | undefined>;
|
|
11
|
+
export default useIndicator;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { nextTick, onUnmounted, ref, watch } from "vue";
|
|
2
|
+
import raf from "@v-c/util/dist/raf";
|
|
3
|
+
function useIndicator(options) {
|
|
4
|
+
const { activeTabOffset, horizontal, rtl, indicator } = options;
|
|
5
|
+
const inkStyle = ref();
|
|
6
|
+
const inkBarRafRef = ref();
|
|
7
|
+
const getLength = (origin) => {
|
|
8
|
+
const size = indicator?.value?.size;
|
|
9
|
+
if (typeof size === "function") return size(origin);
|
|
10
|
+
if (typeof size === "number") return size;
|
|
11
|
+
return origin;
|
|
12
|
+
};
|
|
13
|
+
function cleanInkBarRaf() {
|
|
14
|
+
if (!inkBarRafRef.value) return;
|
|
15
|
+
raf.cancel(inkBarRafRef.value);
|
|
16
|
+
}
|
|
17
|
+
watch([
|
|
18
|
+
() => activeTabOffset.value,
|
|
19
|
+
() => horizontal.value,
|
|
20
|
+
() => rtl.value,
|
|
21
|
+
() => indicator?.value
|
|
22
|
+
], async (_n, _o) => {
|
|
23
|
+
await nextTick();
|
|
24
|
+
const align = indicator?.value?.align || "center";
|
|
25
|
+
const newInkStyle = {};
|
|
26
|
+
if (activeTabOffset.value) if (horizontal.value) {
|
|
27
|
+
newInkStyle.width = `${getLength(activeTabOffset.value.width)}px`;
|
|
28
|
+
const key = rtl.value ? "right" : "left";
|
|
29
|
+
if (align === "start") newInkStyle[key] = `${activeTabOffset.value[key]}px`;
|
|
30
|
+
if (align === "center") {
|
|
31
|
+
newInkStyle[key] = `${activeTabOffset.value[key] + activeTabOffset.value.width / 2}px`;
|
|
32
|
+
newInkStyle.transform = rtl.value ? "translateX(50%)" : "translateX(-50%)";
|
|
33
|
+
}
|
|
34
|
+
if (align === "end") {
|
|
35
|
+
newInkStyle[key] = `${activeTabOffset.value[key] + activeTabOffset.value.width}px`;
|
|
36
|
+
newInkStyle.transform = "translateX(-100%)";
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
newInkStyle.height = `${getLength(activeTabOffset.value.height)}px`;
|
|
40
|
+
if (align === "start") newInkStyle.top = `${activeTabOffset.value.top}px`;
|
|
41
|
+
if (align === "center") {
|
|
42
|
+
newInkStyle.top = `${activeTabOffset.value.top + activeTabOffset.value.height / 2}px`;
|
|
43
|
+
newInkStyle.transform = "translateY(-50%)";
|
|
44
|
+
}
|
|
45
|
+
if (align === "end") {
|
|
46
|
+
newInkStyle.top = `${activeTabOffset.value.top + activeTabOffset.value.height}px`;
|
|
47
|
+
newInkStyle.transform = "translateY(-100%)";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
cleanInkBarRaf();
|
|
51
|
+
inkBarRafRef.value = raf(() => {
|
|
52
|
+
if (!(inkStyle.value && newInkStyle && Object.keys(newInkStyle).every((key) => {
|
|
53
|
+
const newValue = newInkStyle[key];
|
|
54
|
+
const oldValue = inkStyle.value?.[key];
|
|
55
|
+
return typeof newValue === "number" && typeof oldValue === "number" ? Math.round(newValue) === Math.round(oldValue) : newValue === oldValue;
|
|
56
|
+
}))) inkStyle.value = newInkStyle;
|
|
57
|
+
});
|
|
58
|
+
}, { immediate: true });
|
|
59
|
+
onUnmounted(() => {
|
|
60
|
+
cleanInkBarRaf();
|
|
61
|
+
});
|
|
62
|
+
return inkStyle;
|
|
63
|
+
}
|
|
64
|
+
var useIndicator_default = useIndicator;
|
|
65
|
+
export { useIndicator_default as default };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
var DEFAULT_SIZE = {
|
|
5
|
+
width: 0,
|
|
6
|
+
height: 0,
|
|
7
|
+
left: 0,
|
|
8
|
+
top: 0
|
|
9
|
+
};
|
|
10
|
+
function useOffsets(tabs, tabSizes, holderScrollWidth) {
|
|
11
|
+
const mapRef = (0, vue.shallowRef)(/* @__PURE__ */ new Map());
|
|
12
|
+
(0, vue.watch)([
|
|
13
|
+
() => tabs.value.map((tab) => tab.key).join("_"),
|
|
14
|
+
tabSizes,
|
|
15
|
+
holderScrollWidth
|
|
16
|
+
], () => {
|
|
17
|
+
const map = /* @__PURE__ */ new Map();
|
|
18
|
+
const firstKey = tabs.value[0]?.key;
|
|
19
|
+
const lastOffset = (firstKey ? tabSizes.value.get(firstKey) : void 0) || DEFAULT_SIZE;
|
|
20
|
+
const rightOffset = lastOffset.left + lastOffset.width;
|
|
21
|
+
for (let i = 0; i < tabs.value.length; i += 1) {
|
|
22
|
+
const { key } = tabs.value[i];
|
|
23
|
+
let data = tabSizes.value.get(key);
|
|
24
|
+
if (!data) {
|
|
25
|
+
const prevKey = tabs.value[i - 1]?.key;
|
|
26
|
+
data = (prevKey ? tabSizes.value.get(prevKey) : void 0) || DEFAULT_SIZE;
|
|
27
|
+
}
|
|
28
|
+
const entity = map.get(key) || {
|
|
29
|
+
...data,
|
|
30
|
+
right: 0
|
|
31
|
+
};
|
|
32
|
+
entity.right = rightOffset - entity.left - entity.width;
|
|
33
|
+
map.set(key, entity);
|
|
34
|
+
}
|
|
35
|
+
mapRef.value = map;
|
|
36
|
+
}, { immediate: true });
|
|
37
|
+
return mapRef;
|
|
38
|
+
}
|
|
39
|
+
exports.default = useOffsets;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
import { Tab } from '../interface';
|
|
3
|
+
export interface TabOffset {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
left: number;
|
|
7
|
+
top: number;
|
|
8
|
+
right: number;
|
|
9
|
+
}
|
|
10
|
+
export type TabOffsetMap = Map<string, TabOffset>;
|
|
11
|
+
export interface TabSize {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
left: number;
|
|
15
|
+
top: number;
|
|
16
|
+
}
|
|
17
|
+
export type TabSizeMap = Map<string, TabSize>;
|
|
18
|
+
export default function useOffsets(tabs: Ref<Tab[]>, tabSizes: Ref<TabSizeMap>, holderScrollWidth: Ref<number>): Ref<TabOffsetMap>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { shallowRef, watch } from "vue";
|
|
2
|
+
var DEFAULT_SIZE = {
|
|
3
|
+
width: 0,
|
|
4
|
+
height: 0,
|
|
5
|
+
left: 0,
|
|
6
|
+
top: 0
|
|
7
|
+
};
|
|
8
|
+
function useOffsets(tabs, tabSizes, holderScrollWidth) {
|
|
9
|
+
const mapRef = shallowRef(/* @__PURE__ */ new Map());
|
|
10
|
+
watch([
|
|
11
|
+
() => tabs.value.map((tab) => tab.key).join("_"),
|
|
12
|
+
tabSizes,
|
|
13
|
+
holderScrollWidth
|
|
14
|
+
], () => {
|
|
15
|
+
const map = /* @__PURE__ */ new Map();
|
|
16
|
+
const firstKey = tabs.value[0]?.key;
|
|
17
|
+
const lastOffset = (firstKey ? tabSizes.value.get(firstKey) : void 0) || DEFAULT_SIZE;
|
|
18
|
+
const rightOffset = lastOffset.left + lastOffset.width;
|
|
19
|
+
for (let i = 0; i < tabs.value.length; i += 1) {
|
|
20
|
+
const { key } = tabs.value[i];
|
|
21
|
+
let data = tabSizes.value.get(key);
|
|
22
|
+
if (!data) {
|
|
23
|
+
const prevKey = tabs.value[i - 1]?.key;
|
|
24
|
+
data = (prevKey ? tabSizes.value.get(prevKey) : void 0) || DEFAULT_SIZE;
|
|
25
|
+
}
|
|
26
|
+
const entity = map.get(key) || {
|
|
27
|
+
...data,
|
|
28
|
+
right: 0
|
|
29
|
+
};
|
|
30
|
+
entity.right = rightOffset - entity.left - entity.width;
|
|
31
|
+
map.set(key, entity);
|
|
32
|
+
}
|
|
33
|
+
mapRef.value = map;
|
|
34
|
+
}, { immediate: true });
|
|
35
|
+
return mapRef;
|
|
36
|
+
}
|
|
37
|
+
export { useOffsets as default };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
var MIN_SWIPE_DISTANCE = .1;
|
|
5
|
+
var STOP_SWIPE_DISTANCE = .01;
|
|
6
|
+
var REFRESH_INTERVAL = 20;
|
|
7
|
+
var SPEED_OFF_MULTIPLE = .995 ** REFRESH_INTERVAL;
|
|
8
|
+
function useTouchMove(elRef, onOffset) {
|
|
9
|
+
const touchPosition = (0, vue.ref)(null);
|
|
10
|
+
const lastTimestamp = (0, vue.ref)(0);
|
|
11
|
+
const lastTimeDiff = (0, vue.ref)(0);
|
|
12
|
+
const lastOffset = (0, vue.ref)(null);
|
|
13
|
+
const motionRef = (0, vue.ref)();
|
|
14
|
+
const lastWheelDirectionRef = (0, vue.ref)();
|
|
15
|
+
function onTouchStart(e) {
|
|
16
|
+
const { screenX, screenY } = e.touches[0];
|
|
17
|
+
touchPosition.value = {
|
|
18
|
+
x: screenX,
|
|
19
|
+
y: screenY
|
|
20
|
+
};
|
|
21
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
22
|
+
}
|
|
23
|
+
function onTouchMove(e) {
|
|
24
|
+
if (!touchPosition.value) return;
|
|
25
|
+
const { screenX, screenY } = e.touches[0];
|
|
26
|
+
const prev = touchPosition.value;
|
|
27
|
+
touchPosition.value = {
|
|
28
|
+
x: screenX,
|
|
29
|
+
y: screenY
|
|
30
|
+
};
|
|
31
|
+
const offsetX = screenX - prev.x;
|
|
32
|
+
const offsetY = screenY - prev.y;
|
|
33
|
+
onOffset(offsetX, offsetY);
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
lastTimeDiff.value = now - lastTimestamp.value;
|
|
36
|
+
lastTimestamp.value = now;
|
|
37
|
+
lastOffset.value = {
|
|
38
|
+
x: offsetX,
|
|
39
|
+
y: offsetY
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function onTouchEnd() {
|
|
43
|
+
if (!touchPosition.value) return;
|
|
44
|
+
touchPosition.value = null;
|
|
45
|
+
const lo = lastOffset.value;
|
|
46
|
+
lastOffset.value = null;
|
|
47
|
+
if (lo) {
|
|
48
|
+
const distanceX = lo.x / (lastTimeDiff.value || 1);
|
|
49
|
+
const distanceY = lo.y / (lastTimeDiff.value || 1);
|
|
50
|
+
const absX = Math.abs(distanceX);
|
|
51
|
+
const absY = Math.abs(distanceY);
|
|
52
|
+
if (Math.max(absX, absY) < MIN_SWIPE_DISTANCE) return;
|
|
53
|
+
let currentX = distanceX;
|
|
54
|
+
let currentY = distanceY;
|
|
55
|
+
motionRef.value = window.setInterval(() => {
|
|
56
|
+
if (Math.abs(currentX) < STOP_SWIPE_DISTANCE && Math.abs(currentY) < STOP_SWIPE_DISTANCE) {
|
|
57
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
currentX *= SPEED_OFF_MULTIPLE;
|
|
61
|
+
currentY *= SPEED_OFF_MULTIPLE;
|
|
62
|
+
onOffset(currentX * REFRESH_INTERVAL, currentY * REFRESH_INTERVAL);
|
|
63
|
+
}, REFRESH_INTERVAL);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function onWheel(e) {
|
|
67
|
+
const { deltaX, deltaY } = e;
|
|
68
|
+
let mixed = 0;
|
|
69
|
+
const absX = Math.abs(deltaX);
|
|
70
|
+
const absY = Math.abs(deltaY);
|
|
71
|
+
if (absX === absY) mixed = lastWheelDirectionRef.value === "x" ? deltaX : deltaY;
|
|
72
|
+
else if (absX > absY) {
|
|
73
|
+
mixed = deltaX;
|
|
74
|
+
lastWheelDirectionRef.value = "x";
|
|
75
|
+
} else {
|
|
76
|
+
mixed = deltaY;
|
|
77
|
+
lastWheelDirectionRef.value = "y";
|
|
78
|
+
}
|
|
79
|
+
if (onOffset(-mixed, -mixed)) e.preventDefault();
|
|
80
|
+
}
|
|
81
|
+
const touchEventsRef = (0, vue.ref)();
|
|
82
|
+
touchEventsRef.value = {
|
|
83
|
+
onTouchStart,
|
|
84
|
+
onTouchMove,
|
|
85
|
+
onTouchEnd,
|
|
86
|
+
onWheel
|
|
87
|
+
};
|
|
88
|
+
(0, vue.onMounted)(() => {
|
|
89
|
+
function onProxyTouchStart(e) {
|
|
90
|
+
touchEventsRef.value?.onTouchStart(e);
|
|
91
|
+
}
|
|
92
|
+
function onProxyTouchMove(e) {
|
|
93
|
+
touchEventsRef.value?.onTouchMove(e);
|
|
94
|
+
}
|
|
95
|
+
function onProxyTouchEnd(e) {
|
|
96
|
+
touchEventsRef.value?.onTouchEnd(e);
|
|
97
|
+
}
|
|
98
|
+
function onProxyWheel(e) {
|
|
99
|
+
touchEventsRef.value?.onWheel(e);
|
|
100
|
+
}
|
|
101
|
+
document.addEventListener("touchmove", onProxyTouchMove, { passive: false });
|
|
102
|
+
document.addEventListener("touchend", onProxyTouchEnd, { passive: true });
|
|
103
|
+
const el = elRef.value;
|
|
104
|
+
if (el) {
|
|
105
|
+
el.addEventListener("touchstart", onProxyTouchStart, { passive: true });
|
|
106
|
+
el.addEventListener("wheel", onProxyWheel, { passive: false });
|
|
107
|
+
}
|
|
108
|
+
(0, vue.onUnmounted)(() => {
|
|
109
|
+
document.removeEventListener("touchmove", onProxyTouchMove);
|
|
110
|
+
document.removeEventListener("touchend", onProxyTouchEnd);
|
|
111
|
+
if (el) {
|
|
112
|
+
el.removeEventListener("touchstart", onProxyTouchStart);
|
|
113
|
+
el.removeEventListener("wheel", onProxyWheel);
|
|
114
|
+
}
|
|
115
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
exports.default = useTouchMove;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
2
|
+
var MIN_SWIPE_DISTANCE = .1;
|
|
3
|
+
var STOP_SWIPE_DISTANCE = .01;
|
|
4
|
+
var REFRESH_INTERVAL = 20;
|
|
5
|
+
var SPEED_OFF_MULTIPLE = .995 ** REFRESH_INTERVAL;
|
|
6
|
+
function useTouchMove(elRef, onOffset) {
|
|
7
|
+
const touchPosition = ref(null);
|
|
8
|
+
const lastTimestamp = ref(0);
|
|
9
|
+
const lastTimeDiff = ref(0);
|
|
10
|
+
const lastOffset = ref(null);
|
|
11
|
+
const motionRef = ref();
|
|
12
|
+
const lastWheelDirectionRef = ref();
|
|
13
|
+
function onTouchStart(e) {
|
|
14
|
+
const { screenX, screenY } = e.touches[0];
|
|
15
|
+
touchPosition.value = {
|
|
16
|
+
x: screenX,
|
|
17
|
+
y: screenY
|
|
18
|
+
};
|
|
19
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
20
|
+
}
|
|
21
|
+
function onTouchMove(e) {
|
|
22
|
+
if (!touchPosition.value) return;
|
|
23
|
+
const { screenX, screenY } = e.touches[0];
|
|
24
|
+
const prev = touchPosition.value;
|
|
25
|
+
touchPosition.value = {
|
|
26
|
+
x: screenX,
|
|
27
|
+
y: screenY
|
|
28
|
+
};
|
|
29
|
+
const offsetX = screenX - prev.x;
|
|
30
|
+
const offsetY = screenY - prev.y;
|
|
31
|
+
onOffset(offsetX, offsetY);
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
lastTimeDiff.value = now - lastTimestamp.value;
|
|
34
|
+
lastTimestamp.value = now;
|
|
35
|
+
lastOffset.value = {
|
|
36
|
+
x: offsetX,
|
|
37
|
+
y: offsetY
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function onTouchEnd() {
|
|
41
|
+
if (!touchPosition.value) return;
|
|
42
|
+
touchPosition.value = null;
|
|
43
|
+
const lo = lastOffset.value;
|
|
44
|
+
lastOffset.value = null;
|
|
45
|
+
if (lo) {
|
|
46
|
+
const distanceX = lo.x / (lastTimeDiff.value || 1);
|
|
47
|
+
const distanceY = lo.y / (lastTimeDiff.value || 1);
|
|
48
|
+
const absX = Math.abs(distanceX);
|
|
49
|
+
const absY = Math.abs(distanceY);
|
|
50
|
+
if (Math.max(absX, absY) < MIN_SWIPE_DISTANCE) return;
|
|
51
|
+
let currentX = distanceX;
|
|
52
|
+
let currentY = distanceY;
|
|
53
|
+
motionRef.value = window.setInterval(() => {
|
|
54
|
+
if (Math.abs(currentX) < STOP_SWIPE_DISTANCE && Math.abs(currentY) < STOP_SWIPE_DISTANCE) {
|
|
55
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
currentX *= SPEED_OFF_MULTIPLE;
|
|
59
|
+
currentY *= SPEED_OFF_MULTIPLE;
|
|
60
|
+
onOffset(currentX * REFRESH_INTERVAL, currentY * REFRESH_INTERVAL);
|
|
61
|
+
}, REFRESH_INTERVAL);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function onWheel(e) {
|
|
65
|
+
const { deltaX, deltaY } = e;
|
|
66
|
+
let mixed = 0;
|
|
67
|
+
const absX = Math.abs(deltaX);
|
|
68
|
+
const absY = Math.abs(deltaY);
|
|
69
|
+
if (absX === absY) mixed = lastWheelDirectionRef.value === "x" ? deltaX : deltaY;
|
|
70
|
+
else if (absX > absY) {
|
|
71
|
+
mixed = deltaX;
|
|
72
|
+
lastWheelDirectionRef.value = "x";
|
|
73
|
+
} else {
|
|
74
|
+
mixed = deltaY;
|
|
75
|
+
lastWheelDirectionRef.value = "y";
|
|
76
|
+
}
|
|
77
|
+
if (onOffset(-mixed, -mixed)) e.preventDefault();
|
|
78
|
+
}
|
|
79
|
+
const touchEventsRef = ref();
|
|
80
|
+
touchEventsRef.value = {
|
|
81
|
+
onTouchStart,
|
|
82
|
+
onTouchMove,
|
|
83
|
+
onTouchEnd,
|
|
84
|
+
onWheel
|
|
85
|
+
};
|
|
86
|
+
onMounted(() => {
|
|
87
|
+
function onProxyTouchStart(e) {
|
|
88
|
+
touchEventsRef.value?.onTouchStart(e);
|
|
89
|
+
}
|
|
90
|
+
function onProxyTouchMove(e) {
|
|
91
|
+
touchEventsRef.value?.onTouchMove(e);
|
|
92
|
+
}
|
|
93
|
+
function onProxyTouchEnd(e) {
|
|
94
|
+
touchEventsRef.value?.onTouchEnd(e);
|
|
95
|
+
}
|
|
96
|
+
function onProxyWheel(e) {
|
|
97
|
+
touchEventsRef.value?.onWheel(e);
|
|
98
|
+
}
|
|
99
|
+
document.addEventListener("touchmove", onProxyTouchMove, { passive: false });
|
|
100
|
+
document.addEventListener("touchend", onProxyTouchEnd, { passive: true });
|
|
101
|
+
const el = elRef.value;
|
|
102
|
+
if (el) {
|
|
103
|
+
el.addEventListener("touchstart", onProxyTouchStart, { passive: true });
|
|
104
|
+
el.addEventListener("wheel", onProxyWheel, { passive: false });
|
|
105
|
+
}
|
|
106
|
+
onUnmounted(() => {
|
|
107
|
+
document.removeEventListener("touchmove", onProxyTouchMove);
|
|
108
|
+
document.removeEventListener("touchend", onProxyTouchEnd);
|
|
109
|
+
if (el) {
|
|
110
|
+
el.removeEventListener("touchstart", onProxyTouchStart);
|
|
111
|
+
el.removeEventListener("wheel", onProxyWheel);
|
|
112
|
+
}
|
|
113
|
+
if (motionRef.value != null) window.clearInterval(motionRef.value);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export { useTouchMove as default };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
var DEFAULT_SIZE = {
|
|
5
|
+
width: 0,
|
|
6
|
+
height: 0,
|
|
7
|
+
left: 0,
|
|
8
|
+
top: 0,
|
|
9
|
+
right: 0
|
|
10
|
+
};
|
|
11
|
+
function useVisibleRange(tabOffsets, visibleTabContentValue, transform, tabContentSizeValue, addNodeSizeValue, operationNodeSizeValue, { tabs, tabPosition, rtl }) {
|
|
12
|
+
const isHorizontal = (0, vue.computed)(() => tabPosition.value === "top" || tabPosition.value === "bottom");
|
|
13
|
+
const charUnit = (0, vue.computed)(() => isHorizontal.value ? "width" : "height");
|
|
14
|
+
const position = (0, vue.computed)(() => isHorizontal.value ? rtl.value ? "right" : "left" : "top");
|
|
15
|
+
const transformSize = (0, vue.computed)(() => isHorizontal.value ? Math.abs(transform.value) : -transform.value);
|
|
16
|
+
const rangeRef = (0, vue.shallowRef)([0, 0]);
|
|
17
|
+
(0, vue.watch)([
|
|
18
|
+
tabOffsets,
|
|
19
|
+
visibleTabContentValue,
|
|
20
|
+
tabContentSizeValue,
|
|
21
|
+
addNodeSizeValue,
|
|
22
|
+
operationNodeSizeValue,
|
|
23
|
+
transformSize,
|
|
24
|
+
tabPosition,
|
|
25
|
+
rtl,
|
|
26
|
+
() => tabs.value.map((tab) => tab.key).join("_")
|
|
27
|
+
], () => {
|
|
28
|
+
const list = tabs.value;
|
|
29
|
+
if (!list.length) {
|
|
30
|
+
rangeRef.value = [0, 0];
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const len = list.length;
|
|
34
|
+
let endIndex = len;
|
|
35
|
+
for (let i = 0; i < len; i += 1) {
|
|
36
|
+
const offset = tabOffsets.value.get(list[i].key) || DEFAULT_SIZE;
|
|
37
|
+
if (Math.floor(offset[position.value] + offset[charUnit.value]) > Math.floor(transformSize.value + visibleTabContentValue.value)) {
|
|
38
|
+
endIndex = i - 1;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let startIndex = 0;
|
|
43
|
+
for (let i = len - 1; i >= 0; i -= 1) if ((tabOffsets.value.get(list[i].key) || DEFAULT_SIZE)[position.value] < transformSize.value) {
|
|
44
|
+
startIndex = i + 1;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
rangeRef.value = startIndex > endIndex ? [0, -1] : [startIndex, endIndex];
|
|
48
|
+
}, { immediate: true });
|
|
49
|
+
return rangeRef;
|
|
50
|
+
}
|
|
51
|
+
exports.default = useVisibleRange;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
import { Tab, TabNavListProps } from '../interface';
|
|
3
|
+
export interface TabOffsetInfo {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
left: number;
|
|
7
|
+
top: number;
|
|
8
|
+
right: number;
|
|
9
|
+
}
|
|
10
|
+
export type TabOffsetMap = Map<string, TabOffsetInfo>;
|
|
11
|
+
export type ContainerSizeInfo = [width: number, height: number, left: number, top: number];
|
|
12
|
+
export default function useVisibleRange(tabOffsets: Ref<TabOffsetMap>, visibleTabContentValue: Ref<number>, transform: Ref<number>, tabContentSizeValue: Ref<number>, addNodeSizeValue: Ref<number>, operationNodeSizeValue: Ref<number>, { tabs, tabPosition, rtl, }: {
|
|
13
|
+
tabs: Ref<Tab[]>;
|
|
14
|
+
} & {
|
|
15
|
+
tabPosition: Ref<TabNavListProps['tabPosition']>;
|
|
16
|
+
rtl: Ref<boolean>;
|
|
17
|
+
}): Ref<[visibleStart: number, visibleEnd: number]>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { computed, shallowRef, watch } from "vue";
|
|
2
|
+
var DEFAULT_SIZE = {
|
|
3
|
+
width: 0,
|
|
4
|
+
height: 0,
|
|
5
|
+
left: 0,
|
|
6
|
+
top: 0,
|
|
7
|
+
right: 0
|
|
8
|
+
};
|
|
9
|
+
function useVisibleRange(tabOffsets, visibleTabContentValue, transform, tabContentSizeValue, addNodeSizeValue, operationNodeSizeValue, { tabs, tabPosition, rtl }) {
|
|
10
|
+
const isHorizontal = computed(() => tabPosition.value === "top" || tabPosition.value === "bottom");
|
|
11
|
+
const charUnit = computed(() => isHorizontal.value ? "width" : "height");
|
|
12
|
+
const position = computed(() => isHorizontal.value ? rtl.value ? "right" : "left" : "top");
|
|
13
|
+
const transformSize = computed(() => isHorizontal.value ? Math.abs(transform.value) : -transform.value);
|
|
14
|
+
const rangeRef = shallowRef([0, 0]);
|
|
15
|
+
watch([
|
|
16
|
+
tabOffsets,
|
|
17
|
+
visibleTabContentValue,
|
|
18
|
+
tabContentSizeValue,
|
|
19
|
+
addNodeSizeValue,
|
|
20
|
+
operationNodeSizeValue,
|
|
21
|
+
transformSize,
|
|
22
|
+
tabPosition,
|
|
23
|
+
rtl,
|
|
24
|
+
() => tabs.value.map((tab) => tab.key).join("_")
|
|
25
|
+
], () => {
|
|
26
|
+
const list = tabs.value;
|
|
27
|
+
if (!list.length) {
|
|
28
|
+
rangeRef.value = [0, 0];
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const len = list.length;
|
|
32
|
+
let endIndex = len;
|
|
33
|
+
for (let i = 0; i < len; i += 1) {
|
|
34
|
+
const offset = tabOffsets.value.get(list[i].key) || DEFAULT_SIZE;
|
|
35
|
+
if (Math.floor(offset[position.value] + offset[charUnit.value]) > Math.floor(transformSize.value + visibleTabContentValue.value)) {
|
|
36
|
+
endIndex = i - 1;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let startIndex = 0;
|
|
41
|
+
for (let i = len - 1; i >= 0; i -= 1) if ((tabOffsets.value.get(list[i].key) || DEFAULT_SIZE)[position.value] < transformSize.value) {
|
|
42
|
+
startIndex = i + 1;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
rangeRef.value = startIndex > endIndex ? [0, -1] : [startIndex, endIndex];
|
|
46
|
+
}, { immediate: true });
|
|
47
|
+
return rangeRef;
|
|
48
|
+
}
|
|
49
|
+
export { useVisibleRange as default };
|
package/dist/index.cjs
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
File without changes
|