@bifrostui/react 2.0.0-alpha.18 → 2.0.0-alpha.19
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/DatePicker/DatePicker.d.ts +1 -1
- package/dist/Modal/Modal.miniapp.d.ts +1 -1
- package/dist/Tabs/TabIndicator.d.ts +0 -2
- package/dist/Tabs/TabIndicator.js +73 -38
- package/dist/Tabs/Tabs.css +1 -1
- package/dist/Tabs/Tabs.js +1 -2
- package/dist/Tabs/index.css +1 -1
- package/dist/Tabs/miniapp/TabIndicator.js +6 -21
- package/es/Modal/Modal.miniapp.d.ts +1 -1
- package/es/Tabs/TabIndicator.d.ts +0 -2
- package/es/Tabs/TabIndicator.js +74 -39
- package/es/Tabs/Tabs.css +1 -1
- package/es/Tabs/Tabs.js +1 -2
- package/es/Tabs/index.css +1 -1
- package/es/Tabs/miniapp/TabIndicator.js +6 -21
- package/package.json +5 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DatePickerProps } from './DatePicker.types';
|
|
3
|
-
declare const DatePicker: React.ForwardRefExoticComponent<Omit<DatePickerProps<"div", Omit<import("../Picker").PickerProps<"div", import("..").DrawerProps>, "
|
|
3
|
+
declare const DatePicker: React.ForwardRefExoticComponent<Omit<DatePickerProps<"div", Omit<import("../Picker").PickerProps<"div", import("..").DrawerProps>, "value" | "defaultValue" | "onChange" | "onClose" | "onConfirm">>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
4
4
|
export default DatePicker;
|
|
@@ -12,5 +12,5 @@ declare const Modal: React.ForwardRefExoticComponent<Omit<ViewProps & {
|
|
|
12
12
|
keepMounted?: boolean;
|
|
13
13
|
} & import("@bifrostui/types").ICommonProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
14
14
|
ref?: React.Ref<HTMLDivElement>;
|
|
15
|
-
}, keyof import("@bifrostui/types").ICommonProps | "
|
|
15
|
+
}, "open" | "container" | keyof import("@bifrostui/types").ICommonProps | "disablePortal" | "hideBackdrop" | "BackdropProps" | "onClose" | "disableScrollLock" | "keepMounted">, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
16
16
|
export default Modal;
|
|
@@ -6,8 +6,6 @@ export interface TabIndicatorProps {
|
|
|
6
6
|
registeredTabs: React.MutableRefObject<Record<string, React.RefObject<HTMLElement>>>;
|
|
7
7
|
/** tabs 容器的引用 */
|
|
8
8
|
tabsContainerRef: React.RefObject<HTMLDivElement>;
|
|
9
|
-
/** 注册版本号,每次 tab 注册/取消注册时递增 */
|
|
10
|
-
registrationVersion: number;
|
|
11
9
|
}
|
|
12
10
|
declare const TabIndicator: React.FC<TabIndicatorProps>;
|
|
13
11
|
export default TabIndicator;
|
|
@@ -36,14 +36,18 @@ var import_utils = require("@bifrostui/utils");
|
|
|
36
36
|
var import_scroll = __toESM(require("./utils/scroll"));
|
|
37
37
|
const rootClass = "bui-tabs";
|
|
38
38
|
const duration = 300;
|
|
39
|
+
const DEFAULT_INDICATOR_WIDTH = 24;
|
|
39
40
|
const TabIndicator = ({
|
|
40
41
|
currentValue,
|
|
41
42
|
registeredTabs,
|
|
42
|
-
tabsContainerRef
|
|
43
|
-
registrationVersion
|
|
43
|
+
tabsContainerRef
|
|
44
44
|
}) => {
|
|
45
45
|
const indicatorRef = (0, import_react.useRef)(null);
|
|
46
|
-
const
|
|
46
|
+
const hasRenderedOnce = (0, import_react.useRef)(false);
|
|
47
|
+
const indicatorWidthCache = (0, import_react.useRef)(null);
|
|
48
|
+
const [indicatorStyle, setIndicatorStyle] = (0, import_react.useState)(
|
|
49
|
+
null
|
|
50
|
+
);
|
|
47
51
|
const getActiveTabElement = (0, import_utils.useEventCallback)(
|
|
48
52
|
(activeValue) => {
|
|
49
53
|
const tabRef = registeredTabs.current[activeValue];
|
|
@@ -51,7 +55,7 @@ const TabIndicator = ({
|
|
|
51
55
|
}
|
|
52
56
|
);
|
|
53
57
|
const scrollIntoView = (0, import_utils.useEventCallback)(
|
|
54
|
-
(activeTab,
|
|
58
|
+
(activeTab, animate = true) => {
|
|
55
59
|
const tabsEl = tabsContainerRef.current;
|
|
56
60
|
if (!tabsEl || !activeTab) {
|
|
57
61
|
return;
|
|
@@ -59,65 +63,96 @@ const TabIndicator = ({
|
|
|
59
63
|
(0, import_scroll.default)(
|
|
60
64
|
tabsEl,
|
|
61
65
|
activeTab.offsetLeft - (tabsEl.offsetWidth - activeTab.offsetWidth) / 2,
|
|
62
|
-
|
|
66
|
+
animate ? duration : 0
|
|
63
67
|
);
|
|
64
68
|
}
|
|
65
69
|
);
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
const getIndicatorWidth = (0, import_utils.useEventCallback)(() => {
|
|
71
|
+
if (indicatorWidthCache.current !== null) {
|
|
72
|
+
return indicatorWidthCache.current;
|
|
73
|
+
}
|
|
70
74
|
const indicator = indicatorRef.current;
|
|
71
75
|
if (!indicator)
|
|
76
|
+
return DEFAULT_INDICATOR_WIDTH;
|
|
77
|
+
const cssValue = getComputedStyle(indicator).getPropertyValue(
|
|
78
|
+
"--bui-tabs-indicator-width"
|
|
79
|
+
);
|
|
80
|
+
const parsed = Number.parseFloat(cssValue);
|
|
81
|
+
const width = Number.isNaN(parsed) ? DEFAULT_INDICATOR_WIDTH : parsed;
|
|
82
|
+
indicatorWidthCache.current = width;
|
|
83
|
+
return width;
|
|
84
|
+
});
|
|
85
|
+
const getTabsMeta = (0, import_utils.useEventCallback)(() => {
|
|
86
|
+
const tabsNode = tabsContainerRef.current;
|
|
87
|
+
let tabsMeta = null;
|
|
88
|
+
if (tabsNode) {
|
|
89
|
+
const rect = tabsNode.getBoundingClientRect();
|
|
90
|
+
tabsMeta = {
|
|
91
|
+
clientWidth: tabsNode.clientWidth,
|
|
92
|
+
scrollLeft: tabsNode.scrollLeft,
|
|
93
|
+
scrollWidth: tabsNode.scrollWidth,
|
|
94
|
+
left: rect.left
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
let tabMeta = null;
|
|
98
|
+
const activeTab = getActiveTabElement(currentValue);
|
|
99
|
+
if (activeTab) {
|
|
100
|
+
tabMeta = activeTab.getBoundingClientRect();
|
|
101
|
+
}
|
|
102
|
+
return { tabsMeta, tabMeta };
|
|
103
|
+
});
|
|
104
|
+
const updateIndicatorState = (0, import_utils.useEventCallback)(() => {
|
|
105
|
+
const { tabsMeta, tabMeta } = getTabsMeta();
|
|
106
|
+
if (!tabMeta || !tabsMeta) {
|
|
107
|
+
setIndicatorStyle(null);
|
|
72
108
|
return;
|
|
109
|
+
}
|
|
110
|
+
const tabLeft = tabMeta.left - tabsMeta.left + tabsMeta.scrollLeft;
|
|
111
|
+
const tabWidth = tabMeta.width;
|
|
112
|
+
const indicatorWidth = getIndicatorWidth();
|
|
113
|
+
const leftPosition = tabLeft + (tabWidth - indicatorWidth) / 2;
|
|
114
|
+
const newIndicatorStyle = {
|
|
115
|
+
left: leftPosition
|
|
116
|
+
};
|
|
117
|
+
if (indicatorStyle === null) {
|
|
118
|
+
setIndicatorStyle(newIndicatorStyle);
|
|
119
|
+
} else {
|
|
120
|
+
const dLeft = Math.abs(indicatorStyle.left - newIndicatorStyle.left);
|
|
121
|
+
if (dLeft >= 1) {
|
|
122
|
+
setIndicatorStyle(newIndicatorStyle);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
73
125
|
const activeTab = getActiveTabElement(currentValue);
|
|
74
126
|
if (activeTab) {
|
|
75
|
-
const
|
|
76
|
-
const activeTabWidth = activeTab.offsetWidth;
|
|
77
|
-
const containerWidth = tabsEl.offsetWidth;
|
|
78
|
-
const containerScrollWidth = tabsEl.scrollWidth;
|
|
79
|
-
const activeLineWidth = indicator.offsetWidth;
|
|
80
|
-
const x = activeTabLeft + (activeTabWidth - activeLineWidth) / 2;
|
|
81
|
-
indicator.style.transform = `translate(${x}px, 0px)`;
|
|
82
|
-
indicator.style.visibility = "visible";
|
|
83
|
-
const maxScrollDistance = containerScrollWidth - containerWidth;
|
|
127
|
+
const maxScrollDistance = tabsMeta.scrollWidth - tabsMeta.clientWidth;
|
|
84
128
|
if (maxScrollDistance > 0 && !import_utils.isMini) {
|
|
85
|
-
scrollIntoView(activeTab,
|
|
129
|
+
scrollIntoView(activeTab, hasRenderedOnce.current);
|
|
86
130
|
}
|
|
87
|
-
|
|
88
|
-
isFirstRender.current = false;
|
|
89
|
-
requestAnimationFrame(() => {
|
|
90
|
-
if (indicator) {
|
|
91
|
-
indicator.style.transition = "transform 0.3s ease-in-out";
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
indicator.style.visibility = "hidden";
|
|
131
|
+
hasRenderedOnce.current = true;
|
|
97
132
|
}
|
|
98
133
|
});
|
|
99
134
|
(0, import_react.useEffect)(() => {
|
|
100
|
-
|
|
101
|
-
}
|
|
135
|
+
updateIndicatorState();
|
|
136
|
+
});
|
|
102
137
|
(0, import_react.useEffect)(() => {
|
|
103
138
|
const handleResize = (0, import_utils.debounce)(() => {
|
|
104
|
-
|
|
139
|
+
indicatorWidthCache.current = null;
|
|
140
|
+
updateIndicatorState();
|
|
105
141
|
}, 100);
|
|
106
142
|
window.addEventListener("resize", handleResize);
|
|
107
143
|
return () => {
|
|
108
144
|
window.removeEventListener("resize", handleResize);
|
|
109
145
|
};
|
|
110
|
-
}, [
|
|
146
|
+
}, [updateIndicatorState]);
|
|
147
|
+
if (!indicatorStyle) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
111
150
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
112
151
|
"div",
|
|
113
152
|
{
|
|
114
153
|
ref: indicatorRef,
|
|
115
154
|
className: (0, import_clsx.default)(`${rootClass}-indicator`),
|
|
116
|
-
style:
|
|
117
|
-
transition: "none",
|
|
118
|
-
transform: "translate(0px, 0px)",
|
|
119
|
-
visibility: "hidden"
|
|
120
|
-
},
|
|
155
|
+
style: indicatorStyle,
|
|
121
156
|
"aria-hidden": "true"
|
|
122
157
|
}
|
|
123
158
|
);
|
package/dist/Tabs/Tabs.css
CHANGED
|
@@ -49,7 +49,6 @@ xhs-page {
|
|
|
49
49
|
position: absolute;
|
|
50
50
|
top: unset;
|
|
51
51
|
bottom: var(--bui-tabs-indicator-bottom, 0);
|
|
52
|
-
left: 0;
|
|
53
52
|
width: var(--bui-tabs-indicator-width);
|
|
54
53
|
height: var(--bui-tabs-indicator-height);
|
|
55
54
|
color: var(--bui-color-primary);
|
|
@@ -58,6 +57,7 @@ xhs-page {
|
|
|
58
57
|
box-shadow: var(--bui-tabs-indicator-box-shadow);
|
|
59
58
|
z-index: 1;
|
|
60
59
|
pointer-events: none;
|
|
60
|
+
transition: left 0.3s ease-in-out;
|
|
61
61
|
}
|
|
62
62
|
.bui-tabs-content {
|
|
63
63
|
padding: var(--bui-spacing-lg);
|
package/dist/Tabs/Tabs.js
CHANGED
|
@@ -175,8 +175,7 @@ const Tabs = /* @__PURE__ */ import_react.default.forwardRef((props, ref) => {
|
|
|
175
175
|
{
|
|
176
176
|
currentValue,
|
|
177
177
|
registeredTabs,
|
|
178
|
-
tabsContainerRef: tabsRef
|
|
179
|
-
registrationVersion
|
|
178
|
+
tabsContainerRef: tabsRef
|
|
180
179
|
}
|
|
181
180
|
),
|
|
182
181
|
/* @__PURE__ */ import_react.default.createElement(import_TabsContext.TabsContextProvider, { value: contextValue }, renderedTabs)
|
package/dist/Tabs/index.css
CHANGED
|
@@ -49,7 +49,6 @@ xhs-page {
|
|
|
49
49
|
position: absolute;
|
|
50
50
|
top: unset;
|
|
51
51
|
bottom: var(--bui-tabs-indicator-bottom, 0);
|
|
52
|
-
left: 0;
|
|
53
52
|
width: var(--bui-tabs-indicator-width);
|
|
54
53
|
height: var(--bui-tabs-indicator-height);
|
|
55
54
|
color: var(--bui-color-primary);
|
|
@@ -58,6 +57,7 @@ xhs-page {
|
|
|
58
57
|
box-shadow: var(--bui-tabs-indicator-box-shadow);
|
|
59
58
|
z-index: 1;
|
|
60
59
|
pointer-events: none;
|
|
60
|
+
transition: left 0.3s ease-in-out;
|
|
61
61
|
}
|
|
62
62
|
.bui-tabs-content {
|
|
63
63
|
padding: var(--bui-spacing-lg);
|
|
@@ -74,7 +74,6 @@ const TabIndicator = ({
|
|
|
74
74
|
const isInitializedRef = (0, import_react.useRef)(false);
|
|
75
75
|
const initRetryCountRef = (0, import_react.useRef)(0);
|
|
76
76
|
const maxInitRetries = 5;
|
|
77
|
-
const isFirstRender = (0, import_react.useRef)(true);
|
|
78
77
|
const isInitializingRef = (0, import_react.useRef)(false);
|
|
79
78
|
const initVersionRef = (0, import_react.useRef)(0);
|
|
80
79
|
const isMountedRef = (0, import_react.useRef)(true);
|
|
@@ -83,7 +82,7 @@ const TabIndicator = ({
|
|
|
83
82
|
if (!indicator)
|
|
84
83
|
return;
|
|
85
84
|
if (!isValidTabValue(currentValue) || !registeredTabValues.includes(currentValue)) {
|
|
86
|
-
indicator.style.
|
|
85
|
+
indicator.style.opacity = "0";
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
88
|
const cachedPosition = positionCacheRef.current.get(currentValue);
|
|
@@ -99,21 +98,7 @@ const TabIndicator = ({
|
|
|
99
98
|
const indicatorWidth = indicatorWidthRef.current;
|
|
100
99
|
const x = activeTabLeft + (activeTabWidth - indicatorWidth) / 2;
|
|
101
100
|
indicator.style.transform = `translate(${x}px, 0px)`;
|
|
102
|
-
|
|
103
|
-
import_taro.default.nextTick(() => {
|
|
104
|
-
if (!isMountedRef.current || !indicatorRef.current)
|
|
105
|
-
return;
|
|
106
|
-
indicatorRef.current.style.visibility = "visible";
|
|
107
|
-
import_taro.default.nextTick(() => {
|
|
108
|
-
if (!isMountedRef.current || !indicatorRef.current)
|
|
109
|
-
return;
|
|
110
|
-
indicatorRef.current.style.transition = "transform 0.3s ease-in-out";
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
isFirstRender.current = false;
|
|
114
|
-
} else {
|
|
115
|
-
indicator.style.visibility = "visible";
|
|
116
|
-
}
|
|
101
|
+
indicator.style.opacity = "1";
|
|
117
102
|
});
|
|
118
103
|
const initializePositions = (0, import_utils.useEventCallback)(() => __async(void 0, null, function* () {
|
|
119
104
|
if (!isMountedRef.current)
|
|
@@ -227,7 +212,7 @@ const TabIndicator = ({
|
|
|
227
212
|
(0, import_react.useEffect)(() => {
|
|
228
213
|
if (registeredTabValues.length === 0) {
|
|
229
214
|
if (indicatorRef.current) {
|
|
230
|
-
indicatorRef.current.style.
|
|
215
|
+
indicatorRef.current.style.opacity = "0";
|
|
231
216
|
}
|
|
232
217
|
return void 0;
|
|
233
218
|
}
|
|
@@ -256,7 +241,7 @@ const TabIndicator = ({
|
|
|
256
241
|
(0, import_react.useEffect)(() => {
|
|
257
242
|
if (!isValidTabValue(currentValue)) {
|
|
258
243
|
if (indicatorRef.current) {
|
|
259
|
-
indicatorRef.current.style.
|
|
244
|
+
indicatorRef.current.style.opacity = "0";
|
|
260
245
|
}
|
|
261
246
|
return;
|
|
262
247
|
}
|
|
@@ -305,9 +290,9 @@ const TabIndicator = ({
|
|
|
305
290
|
id: `${wrapperId}-indicator`,
|
|
306
291
|
className: (0, import_clsx.default)(import_classes.tabIndicatorClass),
|
|
307
292
|
style: {
|
|
308
|
-
transition: "
|
|
293
|
+
transition: "transform 0.3s ease-in-out, opacity 0.3s ease-in-out",
|
|
309
294
|
transform: "translate(0px, 0px)",
|
|
310
|
-
|
|
295
|
+
opacity: 0
|
|
311
296
|
}
|
|
312
297
|
}
|
|
313
298
|
);
|
|
@@ -12,5 +12,5 @@ declare const Modal: React.ForwardRefExoticComponent<Omit<ViewProps & {
|
|
|
12
12
|
keepMounted?: boolean;
|
|
13
13
|
} & import("@bifrostui/types").ICommonProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
14
14
|
ref?: React.Ref<HTMLDivElement>;
|
|
15
|
-
},
|
|
15
|
+
}, keyof import("@bifrostui/types").ICommonProps | "keepMounted" | "container" | "disablePortal" | "open" | "hideBackdrop" | "BackdropProps" | "onClose" | "disableScrollLock">, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
16
16
|
export default Modal;
|
|
@@ -6,8 +6,6 @@ export interface TabIndicatorProps {
|
|
|
6
6
|
registeredTabs: React.MutableRefObject<Record<string, React.RefObject<HTMLElement>>>;
|
|
7
7
|
/** tabs 容器的引用 */
|
|
8
8
|
tabsContainerRef: React.RefObject<HTMLDivElement>;
|
|
9
|
-
/** 注册版本号,每次 tab 注册/取消注册时递增 */
|
|
10
|
-
registrationVersion: number;
|
|
11
9
|
}
|
|
12
10
|
declare const TabIndicator: React.FC<TabIndicatorProps>;
|
|
13
11
|
export default TabIndicator;
|
package/es/Tabs/TabIndicator.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from "react";
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { debounce, isMini, useEventCallback } from "@bifrostui/utils";
|
|
4
4
|
import scrollLeftTo from "./utils/scroll";
|
|
5
5
|
const rootClass = "bui-tabs";
|
|
6
6
|
const duration = 300;
|
|
7
|
+
const DEFAULT_INDICATOR_WIDTH = 24;
|
|
7
8
|
const TabIndicator = ({
|
|
8
9
|
currentValue,
|
|
9
10
|
registeredTabs,
|
|
10
|
-
tabsContainerRef
|
|
11
|
-
registrationVersion
|
|
11
|
+
tabsContainerRef
|
|
12
12
|
}) => {
|
|
13
13
|
const indicatorRef = useRef(null);
|
|
14
|
-
const
|
|
14
|
+
const hasRenderedOnce = useRef(false);
|
|
15
|
+
const indicatorWidthCache = useRef(null);
|
|
16
|
+
const [indicatorStyle, setIndicatorStyle] = useState(
|
|
17
|
+
null
|
|
18
|
+
);
|
|
15
19
|
const getActiveTabElement = useEventCallback(
|
|
16
20
|
(activeValue) => {
|
|
17
21
|
const tabRef = registeredTabs.current[activeValue];
|
|
@@ -19,7 +23,7 @@ const TabIndicator = ({
|
|
|
19
23
|
}
|
|
20
24
|
);
|
|
21
25
|
const scrollIntoView = useEventCallback(
|
|
22
|
-
(activeTab,
|
|
26
|
+
(activeTab, animate = true) => {
|
|
23
27
|
const tabsEl = tabsContainerRef.current;
|
|
24
28
|
if (!tabsEl || !activeTab) {
|
|
25
29
|
return;
|
|
@@ -27,65 +31,96 @@ const TabIndicator = ({
|
|
|
27
31
|
scrollLeftTo(
|
|
28
32
|
tabsEl,
|
|
29
33
|
activeTab.offsetLeft - (tabsEl.offsetWidth - activeTab.offsetWidth) / 2,
|
|
30
|
-
|
|
34
|
+
animate ? duration : 0
|
|
31
35
|
);
|
|
32
36
|
}
|
|
33
37
|
);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
const getIndicatorWidth = useEventCallback(() => {
|
|
39
|
+
if (indicatorWidthCache.current !== null) {
|
|
40
|
+
return indicatorWidthCache.current;
|
|
41
|
+
}
|
|
38
42
|
const indicator = indicatorRef.current;
|
|
39
43
|
if (!indicator)
|
|
44
|
+
return DEFAULT_INDICATOR_WIDTH;
|
|
45
|
+
const cssValue = getComputedStyle(indicator).getPropertyValue(
|
|
46
|
+
"--bui-tabs-indicator-width"
|
|
47
|
+
);
|
|
48
|
+
const parsed = Number.parseFloat(cssValue);
|
|
49
|
+
const width = Number.isNaN(parsed) ? DEFAULT_INDICATOR_WIDTH : parsed;
|
|
50
|
+
indicatorWidthCache.current = width;
|
|
51
|
+
return width;
|
|
52
|
+
});
|
|
53
|
+
const getTabsMeta = useEventCallback(() => {
|
|
54
|
+
const tabsNode = tabsContainerRef.current;
|
|
55
|
+
let tabsMeta = null;
|
|
56
|
+
if (tabsNode) {
|
|
57
|
+
const rect = tabsNode.getBoundingClientRect();
|
|
58
|
+
tabsMeta = {
|
|
59
|
+
clientWidth: tabsNode.clientWidth,
|
|
60
|
+
scrollLeft: tabsNode.scrollLeft,
|
|
61
|
+
scrollWidth: tabsNode.scrollWidth,
|
|
62
|
+
left: rect.left
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
let tabMeta = null;
|
|
66
|
+
const activeTab = getActiveTabElement(currentValue);
|
|
67
|
+
if (activeTab) {
|
|
68
|
+
tabMeta = activeTab.getBoundingClientRect();
|
|
69
|
+
}
|
|
70
|
+
return { tabsMeta, tabMeta };
|
|
71
|
+
});
|
|
72
|
+
const updateIndicatorState = useEventCallback(() => {
|
|
73
|
+
const { tabsMeta, tabMeta } = getTabsMeta();
|
|
74
|
+
if (!tabMeta || !tabsMeta) {
|
|
75
|
+
setIndicatorStyle(null);
|
|
40
76
|
return;
|
|
77
|
+
}
|
|
78
|
+
const tabLeft = tabMeta.left - tabsMeta.left + tabsMeta.scrollLeft;
|
|
79
|
+
const tabWidth = tabMeta.width;
|
|
80
|
+
const indicatorWidth = getIndicatorWidth();
|
|
81
|
+
const leftPosition = tabLeft + (tabWidth - indicatorWidth) / 2;
|
|
82
|
+
const newIndicatorStyle = {
|
|
83
|
+
left: leftPosition
|
|
84
|
+
};
|
|
85
|
+
if (indicatorStyle === null) {
|
|
86
|
+
setIndicatorStyle(newIndicatorStyle);
|
|
87
|
+
} else {
|
|
88
|
+
const dLeft = Math.abs(indicatorStyle.left - newIndicatorStyle.left);
|
|
89
|
+
if (dLeft >= 1) {
|
|
90
|
+
setIndicatorStyle(newIndicatorStyle);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
41
93
|
const activeTab = getActiveTabElement(currentValue);
|
|
42
94
|
if (activeTab) {
|
|
43
|
-
const
|
|
44
|
-
const activeTabWidth = activeTab.offsetWidth;
|
|
45
|
-
const containerWidth = tabsEl.offsetWidth;
|
|
46
|
-
const containerScrollWidth = tabsEl.scrollWidth;
|
|
47
|
-
const activeLineWidth = indicator.offsetWidth;
|
|
48
|
-
const x = activeTabLeft + (activeTabWidth - activeLineWidth) / 2;
|
|
49
|
-
indicator.style.transform = `translate(${x}px, 0px)`;
|
|
50
|
-
indicator.style.visibility = "visible";
|
|
51
|
-
const maxScrollDistance = containerScrollWidth - containerWidth;
|
|
95
|
+
const maxScrollDistance = tabsMeta.scrollWidth - tabsMeta.clientWidth;
|
|
52
96
|
if (maxScrollDistance > 0 && !isMini) {
|
|
53
|
-
scrollIntoView(activeTab,
|
|
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
|
-
});
|
|
97
|
+
scrollIntoView(activeTab, hasRenderedOnce.current);
|
|
62
98
|
}
|
|
63
|
-
|
|
64
|
-
indicator.style.visibility = "hidden";
|
|
99
|
+
hasRenderedOnce.current = true;
|
|
65
100
|
}
|
|
66
101
|
});
|
|
67
102
|
useEffect(() => {
|
|
68
|
-
|
|
69
|
-
}
|
|
103
|
+
updateIndicatorState();
|
|
104
|
+
});
|
|
70
105
|
useEffect(() => {
|
|
71
106
|
const handleResize = debounce(() => {
|
|
72
|
-
|
|
107
|
+
indicatorWidthCache.current = null;
|
|
108
|
+
updateIndicatorState();
|
|
73
109
|
}, 100);
|
|
74
110
|
window.addEventListener("resize", handleResize);
|
|
75
111
|
return () => {
|
|
76
112
|
window.removeEventListener("resize", handleResize);
|
|
77
113
|
};
|
|
78
|
-
}, [
|
|
114
|
+
}, [updateIndicatorState]);
|
|
115
|
+
if (!indicatorStyle) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
79
118
|
return /* @__PURE__ */ React.createElement(
|
|
80
119
|
"div",
|
|
81
120
|
{
|
|
82
121
|
ref: indicatorRef,
|
|
83
122
|
className: clsx(`${rootClass}-indicator`),
|
|
84
|
-
style:
|
|
85
|
-
transition: "none",
|
|
86
|
-
transform: "translate(0px, 0px)",
|
|
87
|
-
visibility: "hidden"
|
|
88
|
-
},
|
|
123
|
+
style: indicatorStyle,
|
|
89
124
|
"aria-hidden": "true"
|
|
90
125
|
}
|
|
91
126
|
);
|
package/es/Tabs/Tabs.css
CHANGED
|
@@ -49,7 +49,6 @@ xhs-page {
|
|
|
49
49
|
position: absolute;
|
|
50
50
|
top: unset;
|
|
51
51
|
bottom: var(--bui-tabs-indicator-bottom, 0);
|
|
52
|
-
left: 0;
|
|
53
52
|
width: var(--bui-tabs-indicator-width);
|
|
54
53
|
height: var(--bui-tabs-indicator-height);
|
|
55
54
|
color: var(--bui-color-primary);
|
|
@@ -58,6 +57,7 @@ xhs-page {
|
|
|
58
57
|
box-shadow: var(--bui-tabs-indicator-box-shadow);
|
|
59
58
|
z-index: 1;
|
|
60
59
|
pointer-events: none;
|
|
60
|
+
transition: left 0.3s ease-in-out;
|
|
61
61
|
}
|
|
62
62
|
.bui-tabs-content {
|
|
63
63
|
padding: var(--bui-spacing-lg);
|
package/es/Tabs/Tabs.js
CHANGED
|
@@ -145,8 +145,7 @@ const Tabs = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
145
145
|
{
|
|
146
146
|
currentValue,
|
|
147
147
|
registeredTabs,
|
|
148
|
-
tabsContainerRef: tabsRef
|
|
149
|
-
registrationVersion
|
|
148
|
+
tabsContainerRef: tabsRef
|
|
150
149
|
}
|
|
151
150
|
),
|
|
152
151
|
/* @__PURE__ */ React.createElement(TabsContextProvider, { value: contextValue }, renderedTabs)
|
package/es/Tabs/index.css
CHANGED
|
@@ -49,7 +49,6 @@ xhs-page {
|
|
|
49
49
|
position: absolute;
|
|
50
50
|
top: unset;
|
|
51
51
|
bottom: var(--bui-tabs-indicator-bottom, 0);
|
|
52
|
-
left: 0;
|
|
53
52
|
width: var(--bui-tabs-indicator-width);
|
|
54
53
|
height: var(--bui-tabs-indicator-height);
|
|
55
54
|
color: var(--bui-color-primary);
|
|
@@ -58,6 +57,7 @@ xhs-page {
|
|
|
58
57
|
box-shadow: var(--bui-tabs-indicator-box-shadow);
|
|
59
58
|
z-index: 1;
|
|
60
59
|
pointer-events: none;
|
|
60
|
+
transition: left 0.3s ease-in-out;
|
|
61
61
|
}
|
|
62
62
|
.bui-tabs-content {
|
|
63
63
|
padding: var(--bui-spacing-lg);
|
|
@@ -42,7 +42,6 @@ const TabIndicator = ({
|
|
|
42
42
|
const isInitializedRef = useRef(false);
|
|
43
43
|
const initRetryCountRef = useRef(0);
|
|
44
44
|
const maxInitRetries = 5;
|
|
45
|
-
const isFirstRender = useRef(true);
|
|
46
45
|
const isInitializingRef = useRef(false);
|
|
47
46
|
const initVersionRef = useRef(0);
|
|
48
47
|
const isMountedRef = useRef(true);
|
|
@@ -51,7 +50,7 @@ const TabIndicator = ({
|
|
|
51
50
|
if (!indicator)
|
|
52
51
|
return;
|
|
53
52
|
if (!isValidTabValue(currentValue) || !registeredTabValues.includes(currentValue)) {
|
|
54
|
-
indicator.style.
|
|
53
|
+
indicator.style.opacity = "0";
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
56
|
const cachedPosition = positionCacheRef.current.get(currentValue);
|
|
@@ -67,21 +66,7 @@ const TabIndicator = ({
|
|
|
67
66
|
const indicatorWidth = indicatorWidthRef.current;
|
|
68
67
|
const x = activeTabLeft + (activeTabWidth - indicatorWidth) / 2;
|
|
69
68
|
indicator.style.transform = `translate(${x}px, 0px)`;
|
|
70
|
-
|
|
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
|
-
}
|
|
69
|
+
indicator.style.opacity = "1";
|
|
85
70
|
});
|
|
86
71
|
const initializePositions = useEventCallback(() => __async(void 0, null, function* () {
|
|
87
72
|
if (!isMountedRef.current)
|
|
@@ -195,7 +180,7 @@ const TabIndicator = ({
|
|
|
195
180
|
useEffect(() => {
|
|
196
181
|
if (registeredTabValues.length === 0) {
|
|
197
182
|
if (indicatorRef.current) {
|
|
198
|
-
indicatorRef.current.style.
|
|
183
|
+
indicatorRef.current.style.opacity = "0";
|
|
199
184
|
}
|
|
200
185
|
return void 0;
|
|
201
186
|
}
|
|
@@ -224,7 +209,7 @@ const TabIndicator = ({
|
|
|
224
209
|
useEffect(() => {
|
|
225
210
|
if (!isValidTabValue(currentValue)) {
|
|
226
211
|
if (indicatorRef.current) {
|
|
227
|
-
indicatorRef.current.style.
|
|
212
|
+
indicatorRef.current.style.opacity = "0";
|
|
228
213
|
}
|
|
229
214
|
return;
|
|
230
215
|
}
|
|
@@ -273,9 +258,9 @@ const TabIndicator = ({
|
|
|
273
258
|
id: `${wrapperId}-indicator`,
|
|
274
259
|
className: clsx(tabIndicatorClass),
|
|
275
260
|
style: {
|
|
276
|
-
transition: "
|
|
261
|
+
transition: "transform 0.3s ease-in-out, opacity 0.3s ease-in-out",
|
|
277
262
|
transform: "translate(0px, 0px)",
|
|
278
|
-
|
|
263
|
+
opacity: 0
|
|
279
264
|
}
|
|
280
265
|
}
|
|
281
266
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bifrostui/react",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.19",
|
|
4
4
|
"description": "React components for building mobile application",
|
|
5
5
|
"homepage": "http://bui.taopiaopiao.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"clsx": "^2.1.1",
|
|
44
44
|
"dayjs": "^1.11.7",
|
|
45
45
|
"swiper": "^8.1.5",
|
|
46
|
-
"@bifrostui/icons": "2.0.0-alpha.
|
|
47
|
-
"@bifrostui/
|
|
48
|
-
"@bifrostui/
|
|
49
|
-
"@bifrostui/
|
|
46
|
+
"@bifrostui/icons": "2.0.0-alpha.19",
|
|
47
|
+
"@bifrostui/styles": "2.0.0-alpha.19",
|
|
48
|
+
"@bifrostui/types": "2.0.0-alpha.19",
|
|
49
|
+
"@bifrostui/utils": "2.0.0-alpha.19"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@tarojs/components": "^3.0.0",
|