@bifrostui/react 2.0.0-alpha.15 → 2.0.0-alpha.18
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/Modal/Modal.miniapp.d.ts +1 -1
- package/dist/Tabs/Tab.css +0 -1
- package/dist/Tabs/TabIndicator.js +23 -12
- package/dist/Tabs/TabMask.d.ts +2 -4
- package/dist/Tabs/TabMask.js +12 -53
- package/dist/Tabs/Tabs.css +0 -1
- package/dist/Tabs/Tabs.js +19 -4
- package/dist/Tabs/index.css +0 -2
- package/dist/Tabs/miniapp/Tab.d.ts +1 -1
- package/dist/Tabs/miniapp/Tab.js +5 -2
- package/dist/Tabs/miniapp/TabIndicator.js +124 -14
- package/dist/Tabs/miniapp/Tabs.d.ts +1 -1
- package/dist/Tabs/miniapp/Tabs.js +14 -38
- package/es/DatePicker/DatePicker.d.ts +1 -1
- package/es/Modal/Modal.miniapp.d.ts +1 -1
- package/es/Tabs/Tab.css +0 -1
- package/es/Tabs/TabIndicator.js +23 -12
- package/es/Tabs/TabMask.d.ts +2 -4
- package/es/Tabs/TabMask.js +13 -54
- package/es/Tabs/Tabs.css +0 -1
- package/es/Tabs/Tabs.js +20 -5
- package/es/Tabs/index.css +0 -2
- package/es/Tabs/miniapp/Tab.d.ts +1 -1
- package/es/Tabs/miniapp/Tab.js +7 -4
- package/es/Tabs/miniapp/TabIndicator.js +125 -15
- package/es/Tabs/miniapp/Tabs.d.ts +1 -1
- package/es/Tabs/miniapp/Tabs.js +14 -38
- package/package.json +5 -5
- package/dist/Tabs/miniapp/TabMask.d.ts +0 -13
- package/dist/Tabs/miniapp/TabMask.js +0 -66
- package/es/Tabs/miniapp/TabMask.d.ts +0 -13
- package/es/Tabs/miniapp/TabMask.js +0 -37
package/es/Tabs/Tab.css
CHANGED
package/es/Tabs/TabIndicator.js
CHANGED
|
@@ -11,23 +11,26 @@ const TabIndicator = ({
|
|
|
11
11
|
registrationVersion
|
|
12
12
|
}) => {
|
|
13
13
|
const indicatorRef = useRef(null);
|
|
14
|
+
const isFirstRender = useRef(true);
|
|
14
15
|
const getActiveTabElement = useEventCallback(
|
|
15
16
|
(activeValue) => {
|
|
16
17
|
const tabRef = registeredTabs.current[activeValue];
|
|
17
18
|
return tabRef == null ? void 0 : tabRef.current;
|
|
18
19
|
}
|
|
19
20
|
);
|
|
20
|
-
const scrollIntoView = useEventCallback(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const scrollIntoView = useEventCallback(
|
|
22
|
+
(activeTab, animate2 = true) => {
|
|
23
|
+
const tabsEl = tabsContainerRef.current;
|
|
24
|
+
if (!tabsEl || !activeTab) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
scrollLeftTo(
|
|
28
|
+
tabsEl,
|
|
29
|
+
activeTab.offsetLeft - (tabsEl.offsetWidth - activeTab.offsetWidth) / 2,
|
|
30
|
+
animate2 ? duration : 0
|
|
31
|
+
);
|
|
24
32
|
}
|
|
25
|
-
|
|
26
|
-
tabsEl,
|
|
27
|
-
activeTab.offsetLeft - (tabsEl.offsetWidth - activeTab.offsetWidth) / 2,
|
|
28
|
-
duration
|
|
29
|
-
);
|
|
30
|
-
});
|
|
33
|
+
);
|
|
31
34
|
const animate = useEventCallback(() => {
|
|
32
35
|
const tabsEl = tabsContainerRef.current;
|
|
33
36
|
if (!tabsEl)
|
|
@@ -47,7 +50,15 @@ const TabIndicator = ({
|
|
|
47
50
|
indicator.style.visibility = "visible";
|
|
48
51
|
const maxScrollDistance = containerScrollWidth - containerWidth;
|
|
49
52
|
if (maxScrollDistance > 0 && !isMini) {
|
|
50
|
-
scrollIntoView(activeTab);
|
|
53
|
+
scrollIntoView(activeTab, !isFirstRender.current);
|
|
54
|
+
}
|
|
55
|
+
if (isFirstRender.current) {
|
|
56
|
+
isFirstRender.current = false;
|
|
57
|
+
requestAnimationFrame(() => {
|
|
58
|
+
if (indicator) {
|
|
59
|
+
indicator.style.transition = "transform 0.3s ease-in-out";
|
|
60
|
+
}
|
|
61
|
+
});
|
|
51
62
|
}
|
|
52
63
|
} else {
|
|
53
64
|
indicator.style.visibility = "hidden";
|
|
@@ -71,7 +82,7 @@ const TabIndicator = ({
|
|
|
71
82
|
ref: indicatorRef,
|
|
72
83
|
className: clsx(`${rootClass}-indicator`),
|
|
73
84
|
style: {
|
|
74
|
-
transition: "
|
|
85
|
+
transition: "none",
|
|
75
86
|
transform: "translate(0px, 0px)",
|
|
76
87
|
visibility: "hidden"
|
|
77
88
|
},
|
package/es/Tabs/TabMask.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export interface TabMaskProps {
|
|
3
|
-
/** Tabs 容器的引用,用于监听滚动 */
|
|
4
|
-
tabsContainerRef: React.RefObject<HTMLDivElement>;
|
|
5
3
|
/** 位置:左侧或右侧 */
|
|
6
4
|
position: 'left' | 'right';
|
|
7
5
|
}
|
|
8
|
-
declare const
|
|
9
|
-
export default
|
|
6
|
+
declare const _default: React.NamedExoticComponent<TabMaskProps>;
|
|
7
|
+
export default _default;
|
package/es/Tabs/TabMask.js
CHANGED
|
@@ -1,59 +1,18 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const tabsEl = tabsContainerRef.current;
|
|
11
|
-
const mask = maskRef.current;
|
|
12
|
-
if (!tabsEl || !mask)
|
|
13
|
-
return;
|
|
14
|
-
const { scrollLeft, scrollWidth, offsetWidth } = tabsEl;
|
|
15
|
-
let shouldShow = false;
|
|
16
|
-
if (position === "left") {
|
|
17
|
-
shouldShow = scrollLeft > 0;
|
|
18
|
-
} else {
|
|
19
|
-
const rightRange = Math.abs(
|
|
20
|
-
scrollWidth - (scrollLeft + offsetWidth)
|
|
21
|
-
);
|
|
22
|
-
shouldShow = rightRange > 1;
|
|
23
|
-
}
|
|
24
|
-
mask.style.opacity = shouldShow ? "1" : "0";
|
|
25
|
-
},
|
|
26
|
-
100,
|
|
27
|
-
{
|
|
28
|
-
trailing: true,
|
|
29
|
-
leading: true
|
|
30
|
-
}
|
|
3
|
+
import { tabMaskClass, tabMaskLeftClass, tabMaskRightClass } from "./classes";
|
|
4
|
+
const TabMask = ({ position }) => /* @__PURE__ */ React.createElement(
|
|
5
|
+
"div",
|
|
6
|
+
{
|
|
7
|
+
className: clsx(
|
|
8
|
+
tabMaskClass,
|
|
9
|
+
position === "left" ? tabMaskLeftClass : tabMaskRightClass
|
|
31
10
|
),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return void 0;
|
|
38
|
-
updateMaskOpacity();
|
|
39
|
-
tabsEl.addEventListener("scroll", updateMaskOpacity);
|
|
40
|
-
return () => {
|
|
41
|
-
tabsEl.removeEventListener("scroll", updateMaskOpacity);
|
|
42
|
-
};
|
|
43
|
-
}, [tabsContainerRef, updateMaskOpacity]);
|
|
44
|
-
return /* @__PURE__ */ React.createElement(
|
|
45
|
-
"div",
|
|
46
|
-
{
|
|
47
|
-
ref: maskRef,
|
|
48
|
-
className: clsx(`${rootClass}-mask`, `${rootClass}-mask-${position}`),
|
|
49
|
-
style: {
|
|
50
|
-
opacity: 0
|
|
51
|
-
},
|
|
52
|
-
"aria-hidden": "true"
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
};
|
|
56
|
-
var TabMask_default = TabMask;
|
|
11
|
+
"aria-hidden": "true"
|
|
12
|
+
}
|
|
13
|
+
);
|
|
14
|
+
TabMask.displayName = "BuiTabsMask";
|
|
15
|
+
var TabMask_default = /* @__PURE__ */ React.memo(TabMask);
|
|
57
16
|
export {
|
|
58
17
|
TabMask_default as default
|
|
59
18
|
};
|
package/es/Tabs/Tabs.css
CHANGED
|
@@ -16,7 +16,6 @@ xhs-page {
|
|
|
16
16
|
--bui-tab-height: 100%;
|
|
17
17
|
--bui-tab-padding: var(--bui-spacing-lg) var(--bui-spacing-lg) 10px;
|
|
18
18
|
--bui-tab-active-color: var(--bui-color-fg-default);
|
|
19
|
-
--bui-tab-active-font-family: var(--bui-font-family-accent, inherit);
|
|
20
19
|
}
|
|
21
20
|
.bui-tabs {
|
|
22
21
|
position: relative;
|
package/es/Tabs/Tabs.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
var __objRest = (source, exclude) => {
|
|
18
21
|
var target = {};
|
|
19
22
|
for (var prop in source)
|
|
@@ -26,7 +29,7 @@ var __objRest = (source, exclude) => {
|
|
|
26
29
|
}
|
|
27
30
|
return target;
|
|
28
31
|
};
|
|
29
|
-
import React, { useMemo, useRef, useState } from "react";
|
|
32
|
+
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
30
33
|
import clsx from "clsx";
|
|
31
34
|
import { useValue, useEventCallback } from "@bifrostui/utils";
|
|
32
35
|
import Tab from "./Tab";
|
|
@@ -70,6 +73,7 @@ const Tabs = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
70
73
|
{}
|
|
71
74
|
);
|
|
72
75
|
const [registrationVersion, setRegistrationVersion] = useState(0);
|
|
76
|
+
const [isScrollable, setIsScrollable] = useState(false);
|
|
73
77
|
if (process.env.NODE_ENV !== "production") {
|
|
74
78
|
if (tabs.length > 0 && React.Children.count(children) > 0) {
|
|
75
79
|
console.warn(
|
|
@@ -114,10 +118,21 @@ const Tabs = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
114
118
|
}
|
|
115
119
|
return children;
|
|
116
120
|
}, [tabs, children]);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
const tabsEl = tabsRef.current;
|
|
123
|
+
if (!tabsEl)
|
|
124
|
+
return;
|
|
125
|
+
const checkScrollable = () => {
|
|
126
|
+
setIsScrollable(tabsEl.scrollWidth > tabsEl.offsetWidth);
|
|
127
|
+
};
|
|
128
|
+
checkScrollable();
|
|
129
|
+
const resizeObserver = new ResizeObserver(checkScrollable);
|
|
130
|
+
resizeObserver.observe(tabsEl);
|
|
131
|
+
return () => {
|
|
132
|
+
resizeObserver.disconnect();
|
|
133
|
+
};
|
|
134
|
+
}, [registrationVersion]);
|
|
135
|
+
return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({ className: clsx(tabsRootClass, className) }, others), { ref }), isScrollable && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TabMask, { position: "left" }), /* @__PURE__ */ React.createElement(TabMask, { position: "right" })), /* @__PURE__ */ React.createElement(
|
|
121
136
|
"div",
|
|
122
137
|
{
|
|
123
138
|
className: `${tabsRootClass}-tabs`,
|
package/es/Tabs/index.css
CHANGED
|
@@ -16,7 +16,6 @@ xhs-page {
|
|
|
16
16
|
--bui-tab-height: 100%;
|
|
17
17
|
--bui-tab-padding: var(--bui-spacing-lg) var(--bui-spacing-lg) 10px;
|
|
18
18
|
--bui-tab-active-color: var(--bui-color-fg-default);
|
|
19
|
-
--bui-tab-active-font-family: var(--bui-font-family-accent, inherit);
|
|
20
19
|
}
|
|
21
20
|
.bui-tabs {
|
|
22
21
|
position: relative;
|
|
@@ -107,7 +106,6 @@ xhs-page {
|
|
|
107
106
|
.bui-tab-active {
|
|
108
107
|
color: var(--bui-tab-active-color);
|
|
109
108
|
font-weight: var(--bui-font-weight-bold);
|
|
110
|
-
font-family: var(--bui-tab-active-font-family);
|
|
111
109
|
}
|
|
112
110
|
.bui-tab-disabled {
|
|
113
111
|
opacity: 0.5;
|
package/es/Tabs/miniapp/Tab.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TabProps } from '../Tab.types';
|
|
3
3
|
import '../Tab.less';
|
|
4
|
-
declare const _default: React.
|
|
4
|
+
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Omit<TabProps<"div", {}>, "ref"> & React.RefAttributes<HTMLDivElement>>>;
|
|
5
5
|
export default _default;
|
package/es/Tabs/miniapp/Tab.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import { useContextSelector } from "@bifrostui/utils";
|
|
3
|
+
import { useContextSelector, useForkRef } from "@bifrostui/utils";
|
|
4
4
|
import TabsContext from "./TabsContext";
|
|
5
5
|
import { tabRootClass, tabActiveClass, tabDisabledClass } from "../classes";
|
|
6
6
|
import "../Tab.css";
|
|
7
|
-
const Tab = (props) => {
|
|
7
|
+
const Tab = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
8
8
|
const {
|
|
9
9
|
className,
|
|
10
10
|
children,
|
|
@@ -13,6 +13,8 @@ const Tab = (props) => {
|
|
|
13
13
|
onClick,
|
|
14
14
|
style
|
|
15
15
|
} = props;
|
|
16
|
+
const innerRef = useRef(null);
|
|
17
|
+
const handleRef = useForkRef(ref, innerRef);
|
|
16
18
|
const isActive = useContextSelector(
|
|
17
19
|
TabsContext,
|
|
18
20
|
(ctx) => ctx.value === index
|
|
@@ -53,6 +55,7 @@ const Tab = (props) => {
|
|
|
53
55
|
"div",
|
|
54
56
|
{
|
|
55
57
|
id: tabId,
|
|
58
|
+
ref: handleRef,
|
|
56
59
|
className: rootCls,
|
|
57
60
|
style,
|
|
58
61
|
onClick: (e) => {
|
|
@@ -64,7 +67,7 @@ const Tab = (props) => {
|
|
|
64
67
|
},
|
|
65
68
|
children
|
|
66
69
|
);
|
|
67
|
-
};
|
|
70
|
+
});
|
|
68
71
|
Tab.displayName = "BuiTab";
|
|
69
72
|
var Tab_default = /* @__PURE__ */ React.memo(Tab, (prevProps, nextProps) => {
|
|
70
73
|
return prevProps.index === nextProps.index && prevProps.disabled === nextProps.disabled && prevProps.className === nextProps.className && prevProps.children === nextProps.children;
|
|
@@ -18,12 +18,15 @@ var __async = (__this, __arguments, generator) => {
|
|
|
18
18
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
19
19
|
});
|
|
20
20
|
};
|
|
21
|
-
import React, { useEffect, useRef
|
|
21
|
+
import React, { useEffect, useRef } from "react";
|
|
22
22
|
import clsx from "clsx";
|
|
23
23
|
import Taro from "@tarojs/taro";
|
|
24
24
|
import { useEventCallback } from "@bifrostui/utils";
|
|
25
25
|
import { tabIndicatorClass } from "../classes";
|
|
26
26
|
import { batchQueryTabs } from "./utils/queryBatch";
|
|
27
|
+
const isValidTabValue = (value) => {
|
|
28
|
+
return value !== void 0 && value !== null;
|
|
29
|
+
};
|
|
27
30
|
const TabIndicator = ({
|
|
28
31
|
currentValue,
|
|
29
32
|
registeredTabValues,
|
|
@@ -31,8 +34,7 @@ const TabIndicator = ({
|
|
|
31
34
|
scrollViewId,
|
|
32
35
|
registrationVersion
|
|
33
36
|
}) => {
|
|
34
|
-
const
|
|
35
|
-
const [visibility, setVisibility] = useState("hidden");
|
|
37
|
+
const indicatorRef = useRef(null);
|
|
36
38
|
const animationTimerRef = useRef(null);
|
|
37
39
|
const positionCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
38
40
|
const containerInfoRef = useRef(null);
|
|
@@ -40,14 +42,21 @@ const TabIndicator = ({
|
|
|
40
42
|
const isInitializedRef = useRef(false);
|
|
41
43
|
const initRetryCountRef = useRef(0);
|
|
42
44
|
const maxInitRetries = 5;
|
|
45
|
+
const isFirstRender = useRef(true);
|
|
46
|
+
const isInitializingRef = useRef(false);
|
|
47
|
+
const initVersionRef = useRef(0);
|
|
48
|
+
const isMountedRef = useRef(true);
|
|
43
49
|
const updateIndicatorPosition = useEventCallback(() => {
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
const indicator = indicatorRef.current;
|
|
51
|
+
if (!indicator)
|
|
52
|
+
return;
|
|
53
|
+
if (!isValidTabValue(currentValue) || !registeredTabValues.includes(currentValue)) {
|
|
54
|
+
indicator.style.visibility = "hidden";
|
|
46
55
|
return;
|
|
47
56
|
}
|
|
48
57
|
const cachedPosition = positionCacheRef.current.get(currentValue);
|
|
49
58
|
const containerInfo = containerInfoRef.current;
|
|
50
|
-
if (!cachedPosition || !containerInfo) {
|
|
59
|
+
if (!cachedPosition || !containerInfo || !isInitializedRef.current) {
|
|
51
60
|
if (!isInitializedRef.current) {
|
|
52
61
|
initializePositions();
|
|
53
62
|
}
|
|
@@ -57,16 +66,41 @@ const TabIndicator = ({
|
|
|
57
66
|
const activeTabWidth = cachedPosition.width;
|
|
58
67
|
const indicatorWidth = indicatorWidthRef.current;
|
|
59
68
|
const x = activeTabLeft + (activeTabWidth - indicatorWidth) / 2;
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
indicator.style.transform = `translate(${x}px, 0px)`;
|
|
70
|
+
if (isFirstRender.current) {
|
|
71
|
+
Taro.nextTick(() => {
|
|
72
|
+
if (!isMountedRef.current || !indicatorRef.current)
|
|
73
|
+
return;
|
|
74
|
+
indicatorRef.current.style.visibility = "visible";
|
|
75
|
+
Taro.nextTick(() => {
|
|
76
|
+
if (!isMountedRef.current || !indicatorRef.current)
|
|
77
|
+
return;
|
|
78
|
+
indicatorRef.current.style.transition = "transform 0.3s ease-in-out";
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
isFirstRender.current = false;
|
|
82
|
+
} else {
|
|
83
|
+
indicator.style.visibility = "visible";
|
|
84
|
+
}
|
|
62
85
|
});
|
|
63
86
|
const initializePositions = useEventCallback(() => __async(void 0, null, function* () {
|
|
87
|
+
if (!isMountedRef.current)
|
|
88
|
+
return;
|
|
89
|
+
if (isInitializingRef.current)
|
|
90
|
+
return;
|
|
91
|
+
isInitializingRef.current = true;
|
|
92
|
+
initVersionRef.current += 1;
|
|
93
|
+
const currentVersion = initVersionRef.current;
|
|
64
94
|
try {
|
|
65
95
|
const result = yield batchQueryTabs({
|
|
66
96
|
scrollViewId,
|
|
67
97
|
wrapperId,
|
|
68
98
|
tabValues: registeredTabValues
|
|
69
99
|
});
|
|
100
|
+
if (!isMountedRef.current)
|
|
101
|
+
return;
|
|
102
|
+
if (currentVersion !== initVersionRef.current)
|
|
103
|
+
return;
|
|
70
104
|
const { scrollView, scrollFields, wrapper, indicator, tabs } = result;
|
|
71
105
|
if (!scrollView || !wrapper || !indicator || !scrollFields) {
|
|
72
106
|
if (initRetryCountRef.current < maxInitRetries) {
|
|
@@ -75,8 +109,30 @@ const TabIndicator = ({
|
|
|
75
109
|
clearTimeout(animationTimerRef.current);
|
|
76
110
|
}
|
|
77
111
|
animationTimerRef.current = setTimeout(() => {
|
|
112
|
+
if (!isMountedRef.current)
|
|
113
|
+
return;
|
|
114
|
+
isInitializingRef.current = false;
|
|
78
115
|
initializePositions();
|
|
79
116
|
}, 100);
|
|
117
|
+
} else {
|
|
118
|
+
isInitializingRef.current = false;
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!indicator.width || indicator.width <= 0) {
|
|
123
|
+
if (initRetryCountRef.current < maxInitRetries) {
|
|
124
|
+
initRetryCountRef.current += 1;
|
|
125
|
+
if (animationTimerRef.current) {
|
|
126
|
+
clearTimeout(animationTimerRef.current);
|
|
127
|
+
}
|
|
128
|
+
animationTimerRef.current = setTimeout(() => {
|
|
129
|
+
if (!isMountedRef.current)
|
|
130
|
+
return;
|
|
131
|
+
isInitializingRef.current = false;
|
|
132
|
+
initializePositions();
|
|
133
|
+
}, 100);
|
|
134
|
+
} else {
|
|
135
|
+
isInitializingRef.current = false;
|
|
80
136
|
}
|
|
81
137
|
return;
|
|
82
138
|
}
|
|
@@ -89,9 +145,8 @@ const TabIndicator = ({
|
|
|
89
145
|
registeredTabValues.forEach((value, index) => {
|
|
90
146
|
const tabRect = tabs[index];
|
|
91
147
|
if (tabRect && tabRect.width > 0) {
|
|
92
|
-
const relativeLeft = tabRect.left - wrapper.left;
|
|
93
148
|
newCache.set(value, {
|
|
94
|
-
left:
|
|
149
|
+
left: tabRect.left - wrapper.left,
|
|
95
150
|
width: tabRect.width
|
|
96
151
|
});
|
|
97
152
|
}
|
|
@@ -103,40 +158,74 @@ const TabIndicator = ({
|
|
|
103
158
|
clearTimeout(animationTimerRef.current);
|
|
104
159
|
}
|
|
105
160
|
animationTimerRef.current = setTimeout(() => {
|
|
161
|
+
if (!isMountedRef.current)
|
|
162
|
+
return;
|
|
163
|
+
isInitializingRef.current = false;
|
|
106
164
|
initializePositions();
|
|
107
165
|
}, 100);
|
|
166
|
+
} else {
|
|
167
|
+
isInitializingRef.current = false;
|
|
108
168
|
}
|
|
109
169
|
return;
|
|
110
170
|
}
|
|
171
|
+
if (currentVersion !== initVersionRef.current || !isMountedRef.current) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
111
174
|
initRetryCountRef.current = 0;
|
|
112
175
|
positionCacheRef.current = newCache;
|
|
113
176
|
isInitializedRef.current = true;
|
|
177
|
+
isInitializingRef.current = false;
|
|
114
178
|
updateIndicatorPosition();
|
|
115
179
|
} catch (error) {
|
|
116
180
|
console.error("[TabIndicator] \u6279\u91CF\u67E5\u8BE2\u5931\u8D25:", error);
|
|
181
|
+
isInitializingRef.current = false;
|
|
182
|
+
if (isMountedRef.current && initRetryCountRef.current < maxInitRetries) {
|
|
183
|
+
initRetryCountRef.current += 1;
|
|
184
|
+
if (animationTimerRef.current) {
|
|
185
|
+
clearTimeout(animationTimerRef.current);
|
|
186
|
+
}
|
|
187
|
+
animationTimerRef.current = setTimeout(() => {
|
|
188
|
+
if (!isMountedRef.current)
|
|
189
|
+
return;
|
|
190
|
+
initializePositions();
|
|
191
|
+
}, 100);
|
|
192
|
+
}
|
|
117
193
|
}
|
|
118
194
|
}));
|
|
119
195
|
useEffect(() => {
|
|
120
196
|
if (registeredTabValues.length === 0) {
|
|
197
|
+
if (indicatorRef.current) {
|
|
198
|
+
indicatorRef.current.style.visibility = "hidden";
|
|
199
|
+
}
|
|
121
200
|
return void 0;
|
|
122
201
|
}
|
|
202
|
+
initVersionRef.current += 1;
|
|
123
203
|
if (animationTimerRef.current) {
|
|
124
204
|
clearTimeout(animationTimerRef.current);
|
|
205
|
+
animationTimerRef.current = null;
|
|
125
206
|
}
|
|
126
207
|
isInitializedRef.current = false;
|
|
208
|
+
isInitializingRef.current = false;
|
|
127
209
|
initRetryCountRef.current = 0;
|
|
128
210
|
Taro.nextTick(() => {
|
|
211
|
+
if (!isMountedRef.current)
|
|
212
|
+
return;
|
|
129
213
|
initializePositions();
|
|
130
214
|
});
|
|
131
215
|
return () => {
|
|
132
216
|
if (animationTimerRef.current) {
|
|
133
217
|
clearTimeout(animationTimerRef.current);
|
|
218
|
+
animationTimerRef.current = null;
|
|
134
219
|
}
|
|
220
|
+
initVersionRef.current += 1;
|
|
221
|
+
isInitializingRef.current = false;
|
|
135
222
|
};
|
|
136
223
|
}, [registrationVersion, initializePositions]);
|
|
137
224
|
useEffect(() => {
|
|
138
|
-
if (!currentValue) {
|
|
139
|
-
|
|
225
|
+
if (!isValidTabValue(currentValue)) {
|
|
226
|
+
if (indicatorRef.current) {
|
|
227
|
+
indicatorRef.current.style.visibility = "hidden";
|
|
228
|
+
}
|
|
140
229
|
return;
|
|
141
230
|
}
|
|
142
231
|
updateIndicatorPosition();
|
|
@@ -144,10 +233,20 @@ const TabIndicator = ({
|
|
|
144
233
|
useEffect(() => {
|
|
145
234
|
var _a, _b;
|
|
146
235
|
const handleResize = () => {
|
|
236
|
+
if (!isMountedRef.current)
|
|
237
|
+
return;
|
|
238
|
+
initVersionRef.current += 1;
|
|
147
239
|
isInitializedRef.current = false;
|
|
240
|
+
isInitializingRef.current = false;
|
|
148
241
|
initRetryCountRef.current = 0;
|
|
149
242
|
positionCacheRef.current.clear();
|
|
243
|
+
if (animationTimerRef.current) {
|
|
244
|
+
clearTimeout(animationTimerRef.current);
|
|
245
|
+
animationTimerRef.current = null;
|
|
246
|
+
}
|
|
150
247
|
Taro.nextTick(() => {
|
|
248
|
+
if (!isMountedRef.current)
|
|
249
|
+
return;
|
|
151
250
|
initializePositions();
|
|
152
251
|
});
|
|
153
252
|
};
|
|
@@ -157,15 +256,26 @@ const TabIndicator = ({
|
|
|
157
256
|
(_b2 = (_a2 = Taro).offWindowResize) == null ? void 0 : _b2.call(_a2, handleResize);
|
|
158
257
|
};
|
|
159
258
|
}, [initializePositions]);
|
|
259
|
+
useEffect(() => {
|
|
260
|
+
isMountedRef.current = true;
|
|
261
|
+
return () => {
|
|
262
|
+
isMountedRef.current = false;
|
|
263
|
+
if (animationTimerRef.current) {
|
|
264
|
+
clearTimeout(animationTimerRef.current);
|
|
265
|
+
animationTimerRef.current = null;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}, []);
|
|
160
269
|
return /* @__PURE__ */ React.createElement(
|
|
161
270
|
"div",
|
|
162
271
|
{
|
|
272
|
+
ref: indicatorRef,
|
|
163
273
|
id: `${wrapperId}-indicator`,
|
|
164
274
|
className: clsx(tabIndicatorClass),
|
|
165
275
|
style: {
|
|
166
|
-
transition: "
|
|
167
|
-
transform,
|
|
168
|
-
visibility
|
|
276
|
+
transition: "none",
|
|
277
|
+
transform: "translate(0px, 0px)",
|
|
278
|
+
visibility: "hidden"
|
|
169
279
|
}
|
|
170
280
|
}
|
|
171
281
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TabsProps } from '../Tabs.types';
|
|
3
3
|
import '../Tabs.less';
|
|
4
|
-
declare const Tabs: React.
|
|
4
|
+
declare const Tabs: React.ForwardRefExoticComponent<Omit<TabsProps<"div", {}>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
5
5
|
export default Tabs;
|
package/es/Tabs/miniapp/Tabs.js
CHANGED
|
@@ -25,7 +25,7 @@ import { ScrollView } from "@tarojs/components";
|
|
|
25
25
|
import { useValue, useEventCallback } from "@bifrostui/utils";
|
|
26
26
|
import Tab from "./Tab";
|
|
27
27
|
import TabIndicator from "./TabIndicator";
|
|
28
|
-
import TabMask from "
|
|
28
|
+
import TabMask from "../TabMask";
|
|
29
29
|
import { TabsContextProvider } from "./TabsContext";
|
|
30
30
|
import {
|
|
31
31
|
tabsRootClass,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
batchQueryForScroll
|
|
38
38
|
} from "./utils/queryBatch";
|
|
39
39
|
import "../Tabs.css";
|
|
40
|
-
const Tabs = (props) => {
|
|
40
|
+
const Tabs = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
41
41
|
const {
|
|
42
42
|
children,
|
|
43
43
|
className,
|
|
@@ -72,8 +72,10 @@ const Tabs = (props) => {
|
|
|
72
72
|
const [scrollLeft, setScrollLeft] = useState(0);
|
|
73
73
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
74
74
|
const [scrollWidth, setScrollWidth] = useState(0);
|
|
75
|
-
const scrollLeftUpdateTimerRef = React.useRef(null);
|
|
76
75
|
const lastScrollLeftRef = React.useRef(0);
|
|
76
|
+
const isFirstScroll = React.useRef(true);
|
|
77
|
+
const [scrollWithAnimation, setScrollWithAnimation] = React.useState(false);
|
|
78
|
+
const isScrollable = scrollWidth > containerWidth;
|
|
77
79
|
if (process.env.NODE_ENV !== "production") {
|
|
78
80
|
if (tabs.length > 0 && React.Children.count(children) > 0) {
|
|
79
81
|
console.warn(
|
|
@@ -113,14 +115,6 @@ const Tabs = (props) => {
|
|
|
113
115
|
(e) => {
|
|
114
116
|
const { scrollLeft: newScrollLeft, scrollWidth: newScrollWidth } = e.detail;
|
|
115
117
|
lastScrollLeftRef.current = newScrollLeft;
|
|
116
|
-
if (scrollLeftUpdateTimerRef.current) {
|
|
117
|
-
clearTimeout(scrollLeftUpdateTimerRef.current);
|
|
118
|
-
}
|
|
119
|
-
scrollLeftUpdateTimerRef.current = setTimeout(() => {
|
|
120
|
-
if (Math.abs(lastScrollLeftRef.current - scrollLeft) > 1) {
|
|
121
|
-
setScrollLeft(lastScrollLeftRef.current);
|
|
122
|
-
}
|
|
123
|
-
}, 150);
|
|
124
118
|
if (newScrollWidth && newScrollWidth !== scrollWidth) {
|
|
125
119
|
setScrollWidth(newScrollWidth);
|
|
126
120
|
}
|
|
@@ -163,6 +157,12 @@ const Tabs = (props) => {
|
|
|
163
157
|
);
|
|
164
158
|
setScrollLeft(finalScrollLeft);
|
|
165
159
|
lastScrollLeftRef.current = finalScrollLeft;
|
|
160
|
+
if (isFirstScroll.current) {
|
|
161
|
+
Taro.nextTick(() => {
|
|
162
|
+
setScrollWithAnimation(true);
|
|
163
|
+
});
|
|
164
|
+
isFirstScroll.current = false;
|
|
165
|
+
}
|
|
166
166
|
}));
|
|
167
167
|
React.useEffect(() => {
|
|
168
168
|
if (!currentValue || registeredTabValues.length === 0) {
|
|
@@ -196,38 +196,14 @@ const Tabs = (props) => {
|
|
|
196
196
|
}
|
|
197
197
|
return children;
|
|
198
198
|
}, [tabs, children]);
|
|
199
|
-
React.
|
|
200
|
-
return () => {
|
|
201
|
-
if (scrollLeftUpdateTimerRef.current) {
|
|
202
|
-
clearTimeout(scrollLeftUpdateTimerRef.current);
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
}, []);
|
|
206
|
-
return /* @__PURE__ */ React.createElement("div", { className: clsx(tabsRootClass, className), style }, /* @__PURE__ */ React.createElement(
|
|
207
|
-
TabMask,
|
|
208
|
-
{
|
|
209
|
-
position: "left",
|
|
210
|
-
scrollLeft,
|
|
211
|
-
containerWidth,
|
|
212
|
-
scrollWidth
|
|
213
|
-
}
|
|
214
|
-
), /* @__PURE__ */ React.createElement(
|
|
215
|
-
TabMask,
|
|
216
|
-
{
|
|
217
|
-
position: "right",
|
|
218
|
-
scrollLeft,
|
|
219
|
-
containerWidth,
|
|
220
|
-
scrollWidth
|
|
221
|
-
}
|
|
222
|
-
), /* @__PURE__ */ React.createElement(
|
|
199
|
+
return /* @__PURE__ */ React.createElement("div", { className: clsx(tabsRootClass, className), style, ref }, isScrollable && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TabMask, { position: "left" }), /* @__PURE__ */ React.createElement(TabMask, { position: "right" })), /* @__PURE__ */ React.createElement(
|
|
223
200
|
ScrollView,
|
|
224
201
|
{
|
|
225
202
|
id: scrollViewId,
|
|
226
203
|
className: tabsScrollClass,
|
|
227
204
|
scrollX: true,
|
|
228
|
-
scrollWithAnimation
|
|
205
|
+
scrollWithAnimation,
|
|
229
206
|
scrollLeft,
|
|
230
|
-
scrollAnimationDuration: "200",
|
|
231
207
|
onScroll: handleScroll,
|
|
232
208
|
enhanced: true,
|
|
233
209
|
showScrollbar: false,
|
|
@@ -245,7 +221,7 @@ const Tabs = (props) => {
|
|
|
245
221
|
}
|
|
246
222
|
), /* @__PURE__ */ React.createElement(TabsContextProvider, { value: contextValue }, renderedTabs))
|
|
247
223
|
));
|
|
248
|
-
};
|
|
224
|
+
});
|
|
249
225
|
Tabs.displayName = "BuiTabs";
|
|
250
226
|
var Tabs_default = Tabs;
|
|
251
227
|
export {
|