xxf_react 0.3.5 → 0.3.7
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/foundation/LayoutSize.d.ts +5 -0
- package/dist/foundation/LayoutSize.d.ts.map +1 -0
- package/dist/foundation/LayoutSize.js +1 -0
- package/dist/layout/index.d.ts +6 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +5 -0
- package/dist/layout/resize/core/ResizeObserverHook.d.ts +41 -0
- package/dist/layout/resize/core/ResizeObserverHook.d.ts.map +1 -0
- package/dist/layout/resize/core/ResizeObserverHook.js +57 -0
- package/dist/layout/resize/core/SizedLayoutContext.d.ts +23 -0
- package/dist/layout/resize/core/SizedLayoutContext.d.ts.map +1 -0
- package/dist/layout/resize/core/SizedLayoutContext.js +23 -0
- package/dist/layout/resize/core/SizedLayoutProps.d.ts +19 -0
- package/dist/layout/resize/core/SizedLayoutProps.d.ts.map +1 -0
- package/dist/layout/resize/core/SizedLayoutProps.js +1 -0
- package/dist/layout/resize/impl/SizedContainer.d.ts +45 -0
- package/dist/layout/resize/impl/SizedContainer.d.ts.map +1 -0
- package/dist/layout/resize/impl/SizedContainer.js +65 -0
- package/dist/layout/resize/impl/SizedLayout.d.ts +45 -0
- package/dist/layout/resize/impl/SizedLayout.d.ts.map +1 -0
- package/dist/layout/resize/impl/SizedLayout.js +65 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/package.json +8 -2
- package/dist/utils/TestUtils.d.ts +0 -2
- package/dist/utils/TestUtils.d.ts.map +0 -1
- package/dist/utils/TestUtils.js +0 -3
- package/dist/utils/scroll-to-center.d.ts +0 -72
- package/dist/utils/scroll-to-center.d.ts.map +0 -1
- package/dist/utils/scroll-to-center.js +0 -145
- package/dist/utils/tailwind.d.ts +0 -14
- package/dist/utils/tailwind.d.ts.map +0 -1
- package/dist/utils/tailwind.js +0 -16
- /package/dist/utils/{reload.d.ts → Reload.d.ts} +0 -0
- /package/dist/utils/{reload.d.ts.map → Reload.d.ts.map} +0 -0
- /package/dist/utils/{reload.js → Reload.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutSize.d.ts","sourceRoot":"","sources":["../../src/foundation/LayoutSize.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './resize/core/SizedLayoutProps';
|
|
2
|
+
export * from './resize/core/SizedLayoutContext';
|
|
3
|
+
export * from './resize/core/ResizeObserverHook';
|
|
4
|
+
export * from './resize/impl/SizedContainer';
|
|
5
|
+
export * from './resize/impl/SizedLayout';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kCAAkC,CAAA;AAChD,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { LayoutSize } from "../../../foundation/LayoutSize";
|
|
3
|
+
interface UseResizeObserverOptions {
|
|
4
|
+
/** 防抖延迟,默认 0(不防抖) */
|
|
5
|
+
debounce?: number;
|
|
6
|
+
/** 初始尺寸 */
|
|
7
|
+
initialSize?: LayoutSize;
|
|
8
|
+
}
|
|
9
|
+
interface UseResizeObserverReturn<T extends HTMLElement> {
|
|
10
|
+
/** 绑定到容器元素的 ref */
|
|
11
|
+
containerRef: RefObject<T | null>;
|
|
12
|
+
/** 容器宽度 */
|
|
13
|
+
containerWidth: number;
|
|
14
|
+
/** 容器高度 */
|
|
15
|
+
containerHeight: number;
|
|
16
|
+
/** 是否已获取到尺寸 */
|
|
17
|
+
isContainerReady: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 基于 ResizeObserver 监听容器尺寸变化
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const { containerRef, containerWidth, containerHeight, isContainerReady } = useResizeObserver();
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div ref={containerRef}>
|
|
28
|
+
* {isContainerReady && <Chart width={containerWidth} height={containerHeight} />}
|
|
29
|
+
* </div>
|
|
30
|
+
* );
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* // 带防抖
|
|
36
|
+
* const { containerRef, containerHeight } = useResizeObserver({ debounce: 100 });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function useResizeObserver<T extends HTMLElement = HTMLDivElement>(options?: UseResizeObserverOptions): UseResizeObserverReturn<T>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=ResizeObserverHook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResizeObserverHook.d.ts","sourceRoot":"","sources":["../../../../src/layout/resize/core/ResizeObserverHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,SAAS,EAAC,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAC,UAAU,EAAC,MAAM,gCAAgC,CAAC;AAG1D,UAAU,wBAAwB;IAC9B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,WAAW,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED,UAAU,uBAAuB,CAAC,CAAC,SAAS,WAAW;IACnD,mBAAmB;IACnB,YAAY,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAClC,WAAW;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe;IACf,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc,EACpE,OAAO,GAAE,wBAA6B,GACvC,uBAAuB,CAAC,CAAC,CAAC,CAqC5B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 基于 ResizeObserver 监听容器尺寸变化
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const { containerRef, containerWidth, containerHeight, isContainerReady } = useResizeObserver();
|
|
8
|
+
*
|
|
9
|
+
* return (
|
|
10
|
+
* <div ref={containerRef}>
|
|
11
|
+
* {isContainerReady && <Chart width={containerWidth} height={containerHeight} />}
|
|
12
|
+
* </div>
|
|
13
|
+
* );
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // 带防抖
|
|
19
|
+
* const { containerRef, containerHeight } = useResizeObserver({ debounce: 100 });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function useResizeObserver(options = {}) {
|
|
23
|
+
const { debounce = 0, initialSize = { width: 0, height: 0 } } = options;
|
|
24
|
+
const containerRef = useRef(null);
|
|
25
|
+
const [size, setSize] = useState(initialSize);
|
|
26
|
+
const timeoutRef = useRef(null);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const element = containerRef.current;
|
|
29
|
+
if (!element)
|
|
30
|
+
return;
|
|
31
|
+
const updateSize = (entries) => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
const { width, height } = (_b = (_a = entries[0]) === null || _a === void 0 ? void 0 : _a.contentRect) !== null && _b !== void 0 ? _b : { width: 0, height: 0 };
|
|
34
|
+
if (debounce > 0) {
|
|
35
|
+
if (timeoutRef.current)
|
|
36
|
+
clearTimeout(timeoutRef.current);
|
|
37
|
+
timeoutRef.current = setTimeout(() => setSize({ width, height }), debounce);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
setSize({ width, height });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const observer = new ResizeObserver(updateSize);
|
|
44
|
+
observer.observe(element);
|
|
45
|
+
return () => {
|
|
46
|
+
observer.disconnect();
|
|
47
|
+
if (timeoutRef.current)
|
|
48
|
+
clearTimeout(timeoutRef.current);
|
|
49
|
+
};
|
|
50
|
+
}, [debounce]);
|
|
51
|
+
return {
|
|
52
|
+
containerRef,
|
|
53
|
+
containerWidth: size.width,
|
|
54
|
+
containerHeight: size.height,
|
|
55
|
+
isContainerReady: size.width > 0 && size.height > 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { LayoutSize } from "../../../foundation/LayoutSize";
|
|
2
|
+
/** Context 中的尺寸状态 */
|
|
3
|
+
export interface SizedLayoutContextValue extends LayoutSize {
|
|
4
|
+
/** 是否已获取到有效尺寸 */
|
|
5
|
+
isReady: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const SizedLayoutContext: import("react").Context<SizedLayoutContextValue | null>;
|
|
8
|
+
/**
|
|
9
|
+
* 获取父级容器(SizedLayout 或 SizedContainer)的尺寸
|
|
10
|
+
*
|
|
11
|
+
* @throws 如果不在 SizedLayout 或 SizedContainer 内部使用会抛出错误
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* function ChildComponent() {
|
|
16
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
17
|
+
* if (!isReady) return <Loading />;
|
|
18
|
+
* return <div style={{ width, height }}>...</div>;
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function useContextLayoutSize(): SizedLayoutContextValue;
|
|
23
|
+
//# sourceMappingURL=SizedLayoutContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SizedLayoutContext.d.ts","sourceRoot":"","sources":["../../../../src/layout/resize/core/SizedLayoutContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,gCAAgC,CAAC;AAG1D,qBAAqB;AACrB,MAAM,WAAW,uBAAwB,SAAQ,UAAU;IACvD,iBAAiB;IACjB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,yDAAsD,CAAC;AAEtF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,IAAI,uBAAuB,CAM9D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
export const SizedLayoutContext = createContext(null);
|
|
3
|
+
/**
|
|
4
|
+
* 获取父级容器(SizedLayout 或 SizedContainer)的尺寸
|
|
5
|
+
*
|
|
6
|
+
* @throws 如果不在 SizedLayout 或 SizedContainer 内部使用会抛出错误
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* function ChildComponent() {
|
|
11
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
12
|
+
* if (!isReady) return <Loading />;
|
|
13
|
+
* return <div style={{ width, height }}>...</div>;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function useContextLayoutSize() {
|
|
18
|
+
const context = useContext(SizedLayoutContext);
|
|
19
|
+
if (!context) {
|
|
20
|
+
throw new Error('useContextLayoutSize must be used within a SizedLayout or SizedContainer');
|
|
21
|
+
}
|
|
22
|
+
return context;
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CSSProperties, ElementType, ReactNode } from "react";
|
|
2
|
+
import { LayoutSize } from "../../../foundation/LayoutSize";
|
|
3
|
+
export interface SizedLayoutProps {
|
|
4
|
+
/** 子元素 */
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
/** 容器的 className */
|
|
7
|
+
className?: string;
|
|
8
|
+
/** 容器的 style */
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
/** 自定义容器元素类型,默认 div */
|
|
11
|
+
as?: ElementType;
|
|
12
|
+
/** 防抖延迟(毫秒) */
|
|
13
|
+
debounce?: number;
|
|
14
|
+
/** 尺寸未就绪时显示的占位内容 */
|
|
15
|
+
fallback?: ReactNode;
|
|
16
|
+
/** 尺寸变化时的回调 */
|
|
17
|
+
onResize?: (size: LayoutSize) => void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=SizedLayoutProps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SizedLayoutProps.d.ts","sourceRoot":"","sources":["../../../../src/layout/resize/core/SizedLayoutProps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,WAAW,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAC,UAAU,EAAC,MAAM,gCAAgC,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC7B,UAAU;IACV,QAAQ,EAAE,SAAS,CAAC;IACpB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,eAAe;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,eAAe;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SizedLayoutProps } from "../core/SizedLayoutProps";
|
|
3
|
+
/**
|
|
4
|
+
* 自动测量尺寸的容器组件(基于 react-resize-detector)
|
|
5
|
+
*
|
|
6
|
+
* 子组件通过 useContextLayoutSize() 获取容器尺寸,适用于需要根据父容器尺寸
|
|
7
|
+
* 进行布局的场景(如虚拟列表、图表、Canvas 等)。
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // 基础用法
|
|
12
|
+
* <SizedContainer className="h-full w-full">
|
|
13
|
+
* <ChartComponent />
|
|
14
|
+
* </SizedContainer>
|
|
15
|
+
*
|
|
16
|
+
* // ChartComponent 内部
|
|
17
|
+
* function ChartComponent() {
|
|
18
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
19
|
+
* if (!isReady) return <Skeleton />;
|
|
20
|
+
* return <Chart width={width} height={height} />;
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* // 带 fallback 的用法
|
|
27
|
+
* <SizedContainer fallback={<Loading />} className="h-full">
|
|
28
|
+
* <VirtualList />
|
|
29
|
+
* </SizedContainer>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // 自定义元素类型 + 尺寸变化回调
|
|
35
|
+
* <SizedContainer
|
|
36
|
+
* as="section"
|
|
37
|
+
* debounce={100}
|
|
38
|
+
* onResize={({ width, height }) => console.log(width, height)}
|
|
39
|
+
* >
|
|
40
|
+
* <Content />
|
|
41
|
+
* </SizedContainer>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function SizedContainer({ children, className, style, as: Component, debounce, fallback, onResize, }: SizedLayoutProps): React.JSX.Element;
|
|
45
|
+
//# sourceMappingURL=SizedContainer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SizedContainer.d.ts","sourceRoot":"","sources":["../../../../src/layout/resize/impl/SizedContainer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAK1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,cAAc,CAAC,EACI,QAAQ,EACR,SAAS,EACT,KAAK,EACL,EAAE,EAAE,SAAiB,EACrB,QAAQ,EACR,QAAQ,EACR,QAAQ,GACX,EAAE,gBAAgB,qBA2BjD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useResizeDetector } from 'react-resize-detector';
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SizedLayoutContext } from "../core/SizedLayoutContext";
|
|
5
|
+
/**
|
|
6
|
+
* 自动测量尺寸的容器组件(基于 react-resize-detector)
|
|
7
|
+
*
|
|
8
|
+
* 子组件通过 useContextLayoutSize() 获取容器尺寸,适用于需要根据父容器尺寸
|
|
9
|
+
* 进行布局的场景(如虚拟列表、图表、Canvas 等)。
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // 基础用法
|
|
14
|
+
* <SizedContainer className="h-full w-full">
|
|
15
|
+
* <ChartComponent />
|
|
16
|
+
* </SizedContainer>
|
|
17
|
+
*
|
|
18
|
+
* // ChartComponent 内部
|
|
19
|
+
* function ChartComponent() {
|
|
20
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
21
|
+
* if (!isReady) return <Skeleton />;
|
|
22
|
+
* return <Chart width={width} height={height} />;
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* // 带 fallback 的用法
|
|
29
|
+
* <SizedContainer fallback={<Loading />} className="h-full">
|
|
30
|
+
* <VirtualList />
|
|
31
|
+
* </SizedContainer>
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* // 自定义元素类型 + 尺寸变化回调
|
|
37
|
+
* <SizedContainer
|
|
38
|
+
* as="section"
|
|
39
|
+
* debounce={100}
|
|
40
|
+
* onResize={({ width, height }) => console.log(width, height)}
|
|
41
|
+
* >
|
|
42
|
+
* <Content />
|
|
43
|
+
* </SizedContainer>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function SizedContainer({ children, className, style, as: Component = 'div', debounce, fallback, onResize, }) {
|
|
47
|
+
const { width, height, ref } = useResizeDetector({
|
|
48
|
+
refreshMode: debounce ? 'debounce' : undefined,
|
|
49
|
+
refreshRate: debounce,
|
|
50
|
+
onResize: onResize
|
|
51
|
+
? ({ width: w, height: h }) => {
|
|
52
|
+
if (w !== null && h !== null) {
|
|
53
|
+
onResize({ width: w, height: h });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
: undefined,
|
|
57
|
+
});
|
|
58
|
+
const size = {
|
|
59
|
+
width: width !== null && width !== void 0 ? width : 0,
|
|
60
|
+
height: height !== null && height !== void 0 ? height : 0,
|
|
61
|
+
};
|
|
62
|
+
const isReady = size.width > 0 && size.height > 0;
|
|
63
|
+
return (React.createElement(Component, { ref: ref, className: className, style: style },
|
|
64
|
+
React.createElement(SizedLayoutContext.Provider, { value: { ...size, isReady } }, fallback && !isReady ? fallback : children)));
|
|
65
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SizedLayoutProps } from "../core/SizedLayoutProps";
|
|
3
|
+
/**
|
|
4
|
+
* 自动测量尺寸的布局容器
|
|
5
|
+
*
|
|
6
|
+
* 子组件通过 useContextLayoutSize() 获取容器尺寸,适用于需要根据父容器尺寸
|
|
7
|
+
* 进行布局的场景(如虚拟列表、图表、Canvas 等)。
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // 基础用法
|
|
12
|
+
* <SizedLayout className="h-full w-full">
|
|
13
|
+
* <ChartComponent />
|
|
14
|
+
* </SizedLayout>
|
|
15
|
+
*
|
|
16
|
+
* // ChartComponent 内部
|
|
17
|
+
* function ChartComponent() {
|
|
18
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
19
|
+
* if (!isReady) return <Skeleton />;
|
|
20
|
+
* return <Chart width={width} height={height} />;
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* // 带 fallback 的用法
|
|
27
|
+
* <SizedLayout fallback={<Loading />} className="h-full">
|
|
28
|
+
* <VirtualList />
|
|
29
|
+
* </SizedLayout>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // 自定义元素类型 + 尺寸变化回调
|
|
35
|
+
* <SizedLayout
|
|
36
|
+
* as="section"
|
|
37
|
+
* debounce={100}
|
|
38
|
+
* onResize={({ width, height }) => console.log(width, height)}
|
|
39
|
+
* >
|
|
40
|
+
* <Content />
|
|
41
|
+
* </SizedLayout>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function SizedLayout({ children, className, style, as: Component, debounce, fallback, onResize, }: SizedLayoutProps): React.JSX.Element;
|
|
45
|
+
//# sourceMappingURL=SizedLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SizedLayout.d.ts","sourceRoot":"","sources":["../../../../src/layout/resize/impl/SizedLayout.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,WAAW,CAAC,EACI,QAAQ,EACR,SAAS,EACT,KAAK,EACL,EAAE,EAAE,SAAiB,EACrB,QAAQ,EACR,QAAQ,EACR,QAAQ,GACX,EAAE,gBAAgB,qBA2B9C"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { useResizeObserver } from '../core/ResizeObserverHook';
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { SizedLayoutContext } from "../core/SizedLayoutContext";
|
|
6
|
+
/**
|
|
7
|
+
* 自动测量尺寸的布局容器
|
|
8
|
+
*
|
|
9
|
+
* 子组件通过 useContextLayoutSize() 获取容器尺寸,适用于需要根据父容器尺寸
|
|
10
|
+
* 进行布局的场景(如虚拟列表、图表、Canvas 等)。
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* // 基础用法
|
|
15
|
+
* <SizedLayout className="h-full w-full">
|
|
16
|
+
* <ChartComponent />
|
|
17
|
+
* </SizedLayout>
|
|
18
|
+
*
|
|
19
|
+
* // ChartComponent 内部
|
|
20
|
+
* function ChartComponent() {
|
|
21
|
+
* const { width, height, isReady } = useContextLayoutSize();
|
|
22
|
+
* if (!isReady) return <Skeleton />;
|
|
23
|
+
* return <Chart width={width} height={height} />;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* // 带 fallback 的用法
|
|
30
|
+
* <SizedLayout fallback={<Loading />} className="h-full">
|
|
31
|
+
* <VirtualList />
|
|
32
|
+
* </SizedLayout>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* // 自定义元素类型 + 尺寸变化回调
|
|
38
|
+
* <SizedLayout
|
|
39
|
+
* as="section"
|
|
40
|
+
* debounce={100}
|
|
41
|
+
* onResize={({ width, height }) => console.log(width, height)}
|
|
42
|
+
* >
|
|
43
|
+
* <Content />
|
|
44
|
+
* </SizedLayout>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function SizedLayout({ children, className, style, as: Component = 'div', debounce, fallback, onResize, }) {
|
|
48
|
+
const { containerRef, containerWidth, containerHeight, isContainerReady } = useResizeObserver({
|
|
49
|
+
debounce,
|
|
50
|
+
});
|
|
51
|
+
const size = {
|
|
52
|
+
width: containerWidth,
|
|
53
|
+
height: containerHeight,
|
|
54
|
+
};
|
|
55
|
+
// 处理 onResize 回调
|
|
56
|
+
const onResizeRef = useRef(onResize);
|
|
57
|
+
onResizeRef.current = onResize;
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (isContainerReady && onResizeRef.current) {
|
|
60
|
+
onResizeRef.current(size);
|
|
61
|
+
}
|
|
62
|
+
}, [containerWidth, containerHeight, isContainerReady]);
|
|
63
|
+
return (React.createElement(Component, { ref: containerRef, className: className, style: style },
|
|
64
|
+
React.createElement(SizedLayoutContext.Provider, { value: { ...size, isReady: isContainerReady } }, fallback && !isContainerReady ? fallback : children)));
|
|
65
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './ScrollToCenter';
|
|
2
2
|
export * from './Reload';
|
|
3
|
-
export * from '
|
|
3
|
+
export * from '../layout/resize/core/ResizeObserverHook';
|
|
4
|
+
export * from '../layout/resize/core/SizedLayoutContext';
|
|
5
|
+
export * from '../layout/resize/impl/SizedLayout';
|
|
6
|
+
export * from '../layout/resize/impl/SizedContainer';
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,cAAc,kBAAkB,CAAA;AAChC,cAAc,UAAU,CAAA;AACxB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,cAAc,kBAAkB,CAAA;AAChC,cAAc,UAAU,CAAA;AACxB,cAAc,0CAA0C,CAAA;AACxD,cAAc,0CAA0C,CAAA;AACxD,cAAc,mCAAmC,CAAA;AACjD,cAAc,sCAAsC,CAAA"}
|
package/dist/utils/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
export * from './ScrollToCenter';
|
|
3
3
|
export * from './Reload';
|
|
4
|
-
export * from '
|
|
4
|
+
export * from '../layout/resize/core/ResizeObserverHook';
|
|
5
|
+
export * from '../layout/resize/core/SizedLayoutContext';
|
|
6
|
+
export * from '../layout/resize/impl/SizedLayout';
|
|
7
|
+
export * from '../layout/resize/impl/SizedContainer';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xxf_react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,9 +45,15 @@
|
|
|
45
45
|
"./foundation": {
|
|
46
46
|
"types": "./dist/foundation/index.d.ts",
|
|
47
47
|
"import": "./dist/foundation/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./layout": {
|
|
50
|
+
"types": "./dist/layout/index.d.ts",
|
|
51
|
+
"import": "./dist/layout/index.js"
|
|
48
52
|
}
|
|
49
53
|
},
|
|
50
|
-
"files": [
|
|
54
|
+
"files": [
|
|
55
|
+
"dist"
|
|
56
|
+
],
|
|
51
57
|
"scripts": {
|
|
52
58
|
"build": "tsc"
|
|
53
59
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TestUtils.d.ts","sourceRoot":"","sources":["../../src/utils/TestUtils.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,SAEnB"}
|
package/dist/utils/TestUtils.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/** 滚动对齐方式 */
|
|
2
|
-
type ScrollAlign = 'center' | 'start' | 'end' | 'nearest';
|
|
3
|
-
/** 滚动配置选项 */
|
|
4
|
-
interface ScrollOptions {
|
|
5
|
-
/** 滚动行为:'smooth' 平滑滚动 | 'instant' 瞬间滚动 | 'auto' 自动,默认 'smooth' */
|
|
6
|
-
behavior?: ScrollBehavior;
|
|
7
|
-
/** 对齐方式:'center' 居中 | 'start' 起始 | 'end' 末尾 | 'nearest' 最近可见,默认 'center' */
|
|
8
|
-
align?: ScrollAlign;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* 将元素滚动到容器指定位置
|
|
12
|
-
* @param element - 要滚动到的目标元素,为 null 时不执行滚动
|
|
13
|
-
* @param container - 可滚动的容器元素,为 null 时不执行滚动
|
|
14
|
-
* @param options - 滚动配置选项
|
|
15
|
-
* @param options.behavior - 滚动行为,默认 'smooth'
|
|
16
|
-
* @param options.align - 对齐方式,默认 'center'
|
|
17
|
-
*/
|
|
18
|
-
export declare const scrollToElement: (element: HTMLElement | null, container: HTMLElement | null, options?: ScrollOptions) => void;
|
|
19
|
-
/**
|
|
20
|
-
* scrollToElement 的别名,保持向后兼容
|
|
21
|
-
* @deprecated 请使用 {@link scrollToElement} 代替
|
|
22
|
-
*/
|
|
23
|
-
export declare const scrollToCenter: (element: HTMLElement | null, container: HTMLElement | null, options?: ScrollOptions) => void;
|
|
24
|
-
/** useScrollToCenter Hook 的配置选项 */
|
|
25
|
-
interface UseScrollToCenterOptions {
|
|
26
|
-
/** 初始值,用于首次渲染时自动滚动到该值对应的元素(通过 data-value 属性匹配) */
|
|
27
|
-
initialValue?: string | number;
|
|
28
|
-
/** 对齐方式:'center' 居中 | 'start' 起始 | 'end' 末尾 | 'nearest' 最近可见,默认 'center' */
|
|
29
|
-
align?: ScrollAlign;
|
|
30
|
-
/** 滚动行为:'smooth' 平滑滚动 | 'instant' 瞬间滚动 | 'auto' 自动,默认 'smooth' */
|
|
31
|
-
behavior?: ScrollBehavior;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Hook: 用于可滚动 Tabs 的自动居中
|
|
35
|
-
* https://www.radix-ui.com/primitives/docs/components/tabs
|
|
36
|
-
*
|
|
37
|
-
* @param options - 配置选项
|
|
38
|
-
* @param options.initialValue - 初始值,首次渲染时自动滚动到该值对应的元素
|
|
39
|
-
* @param options.align - 对齐方式,默认 'center'
|
|
40
|
-
* @param options.behavior - 滚动行为,默认 'smooth'
|
|
41
|
-
*
|
|
42
|
-
* @returns 返回对象包含:
|
|
43
|
-
* - `containerRef` - 绑定到可滚动容器的 ref
|
|
44
|
-
* - `scrollToValue` - 滚动到指定 data-value 值的元素
|
|
45
|
-
* - `scrollTo` - 滚动到指定 HTMLElement 元素
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```tsx
|
|
49
|
-
* const { containerRef, scrollToValue } = useScrollToCenter({
|
|
50
|
-
* initialValue: activeTab, // 首次渲染时滚动到初始值
|
|
51
|
-
* });
|
|
52
|
-
*
|
|
53
|
-
* <Tabs.List ref={containerRef}>
|
|
54
|
-
* <Tabs.Trigger data-value="tab1">Tab 1</Tabs.Trigger>
|
|
55
|
-
* </Tabs.List>
|
|
56
|
-
*
|
|
57
|
-
* 如果<Tabs.List 里面又嵌套了可以滚动的div,那么ref必须绑定在可以滚动的div上
|
|
58
|
-
*
|
|
59
|
-
* // 切换时调用
|
|
60
|
-
* scrollToValue('tab1');
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
export declare const useScrollToCenter: <T extends string | number = string>(options?: UseScrollToCenterOptions) => {
|
|
64
|
-
/** 绑定到可滚动容器的 ref */
|
|
65
|
-
containerRef: import("react").RefObject<HTMLDivElement | null>;
|
|
66
|
-
/** 滚动到指定 data-value 值的元素 */
|
|
67
|
-
scrollToValue: (value: T, scrollOptions?: ScrollOptions) => void;
|
|
68
|
-
/** 滚动到指定 HTMLElement 元素 */
|
|
69
|
-
scrollTo: (element: HTMLElement | null, scrollOptions?: ScrollOptions) => void;
|
|
70
|
-
};
|
|
71
|
-
export {};
|
|
72
|
-
//# sourceMappingURL=scroll-to-center.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-to-center.d.ts","sourceRoot":"","sources":["../../src/utils/scroll-to-center.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,KAAK,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAE1D,aAAa;AACb,UAAU,aAAa;IACnB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,4EAA4E;IAC5E,KAAK,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GACxB,SAAS,WAAW,GAAG,IAAI,EAC3B,WAAW,WAAW,GAAG,IAAI,EAC7B,UAAS,aAAkB,SAmD9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,YA3Dd,WAAW,GAAG,IAAI,aAChB,WAAW,GAAG,IAAI,YACpB,aAAa,SAyDmB,CAAC;AAE9C,mCAAmC;AACnC,UAAU,wBAAwB;IAC9B,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAChE,UAAS,wBAA6B;IA8DlC,oBAAoB;;IAEpB,4BAA4B;2BArCpB,CAAC,kBAAkB,aAAa;IAuCxC,2BAA2B;wBAjBjB,WAAW,GAAG,IAAI,kBAAkB,aAAa;CAoBlE,CAAC"}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { useRef, useCallback, useEffect } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* 将元素滚动到容器指定位置
|
|
4
|
-
* @param element - 要滚动到的目标元素,为 null 时不执行滚动
|
|
5
|
-
* @param container - 可滚动的容器元素,为 null 时不执行滚动
|
|
6
|
-
* @param options - 滚动配置选项
|
|
7
|
-
* @param options.behavior - 滚动行为,默认 'smooth'
|
|
8
|
-
* @param options.align - 对齐方式,默认 'center'
|
|
9
|
-
*/
|
|
10
|
-
export const scrollToElement = (element, container, options = {}) => {
|
|
11
|
-
if (!element || !container)
|
|
12
|
-
return;
|
|
13
|
-
const { behavior = 'smooth', align = 'center' } = options;
|
|
14
|
-
// 使用 getBoundingClientRect 计算相对位置(更可靠,不受 DOM 层级影响)
|
|
15
|
-
const containerRect = container.getBoundingClientRect();
|
|
16
|
-
const elementRect = element.getBoundingClientRect();
|
|
17
|
-
const elementLeftRelative = elementRect.left - containerRect.left + container.scrollLeft;
|
|
18
|
-
const containerWidth = container.offsetWidth;
|
|
19
|
-
const elementWidth = element.offsetWidth;
|
|
20
|
-
const maxScroll = container.scrollWidth - containerWidth;
|
|
21
|
-
let scrollLeft;
|
|
22
|
-
switch (align) {
|
|
23
|
-
case 'start':
|
|
24
|
-
scrollLeft = elementLeftRelative;
|
|
25
|
-
break;
|
|
26
|
-
case 'end':
|
|
27
|
-
scrollLeft = elementLeftRelative - containerWidth + elementWidth;
|
|
28
|
-
break;
|
|
29
|
-
case 'nearest': {
|
|
30
|
-
const currentScroll = container.scrollLeft;
|
|
31
|
-
const elementRight = elementLeftRelative + elementWidth;
|
|
32
|
-
const visibleLeft = currentScroll;
|
|
33
|
-
const visibleRight = currentScroll + containerWidth;
|
|
34
|
-
if (elementLeftRelative < visibleLeft) {
|
|
35
|
-
scrollLeft = elementLeftRelative;
|
|
36
|
-
}
|
|
37
|
-
else if (elementRight > visibleRight) {
|
|
38
|
-
scrollLeft = elementRight - containerWidth;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
return; // 已在视口内,不滚动
|
|
42
|
-
}
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
case 'center':
|
|
46
|
-
default:
|
|
47
|
-
scrollLeft = elementLeftRelative - containerWidth / 2 + elementWidth / 2;
|
|
48
|
-
}
|
|
49
|
-
// 限制在有效范围内
|
|
50
|
-
const clampedScroll = Math.max(0, Math.min(scrollLeft, maxScroll));
|
|
51
|
-
container.scrollTo({
|
|
52
|
-
left: clampedScroll,
|
|
53
|
-
behavior,
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* scrollToElement 的别名,保持向后兼容
|
|
58
|
-
* @deprecated 请使用 {@link scrollToElement} 代替
|
|
59
|
-
*/
|
|
60
|
-
export const scrollToCenter = scrollToElement;
|
|
61
|
-
/**
|
|
62
|
-
* Hook: 用于可滚动 Tabs 的自动居中
|
|
63
|
-
* https://www.radix-ui.com/primitives/docs/components/tabs
|
|
64
|
-
*
|
|
65
|
-
* @param options - 配置选项
|
|
66
|
-
* @param options.initialValue - 初始值,首次渲染时自动滚动到该值对应的元素
|
|
67
|
-
* @param options.align - 对齐方式,默认 'center'
|
|
68
|
-
* @param options.behavior - 滚动行为,默认 'smooth'
|
|
69
|
-
*
|
|
70
|
-
* @returns 返回对象包含:
|
|
71
|
-
* - `containerRef` - 绑定到可滚动容器的 ref
|
|
72
|
-
* - `scrollToValue` - 滚动到指定 data-value 值的元素
|
|
73
|
-
* - `scrollTo` - 滚动到指定 HTMLElement 元素
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```tsx
|
|
77
|
-
* const { containerRef, scrollToValue } = useScrollToCenter({
|
|
78
|
-
* initialValue: activeTab, // 首次渲染时滚动到初始值
|
|
79
|
-
* });
|
|
80
|
-
*
|
|
81
|
-
* <Tabs.List ref={containerRef}>
|
|
82
|
-
* <Tabs.Trigger data-value="tab1">Tab 1</Tabs.Trigger>
|
|
83
|
-
* </Tabs.List>
|
|
84
|
-
*
|
|
85
|
-
* 如果<Tabs.List 里面又嵌套了可以滚动的div,那么ref必须绑定在可以滚动的div上
|
|
86
|
-
*
|
|
87
|
-
* // 切换时调用
|
|
88
|
-
* scrollToValue('tab1');
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
export const useScrollToCenter = (options = {}) => {
|
|
92
|
-
const { initialValue, align = 'center', behavior = 'smooth' } = options;
|
|
93
|
-
const containerRef = useRef(null);
|
|
94
|
-
const initializedRef = useRef(false);
|
|
95
|
-
// 初始渲染时滚动到初始值(无动画)
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
if (initializedRef.current || initialValue === undefined)
|
|
98
|
-
return;
|
|
99
|
-
initializedRef.current = true;
|
|
100
|
-
// 延迟执行,确保 DOM 渲染完成
|
|
101
|
-
requestAnimationFrame(() => {
|
|
102
|
-
const container = containerRef.current;
|
|
103
|
-
const element = container === null || container === void 0 ? void 0 : container.querySelector(`[data-value="${initialValue}"]`);
|
|
104
|
-
scrollToElement(element, container, { behavior: 'instant', align });
|
|
105
|
-
});
|
|
106
|
-
}, [initialValue, align]);
|
|
107
|
-
/**
|
|
108
|
-
* 滚动到指定 data-value 值的元素
|
|
109
|
-
* @param value - 目标元素的 data-value 属性值
|
|
110
|
-
* @param scrollOptions - 可选的滚动配置,覆盖默认配置
|
|
111
|
-
*/
|
|
112
|
-
const scrollToValue = useCallback((value, scrollOptions) => {
|
|
113
|
-
requestAnimationFrame(() => {
|
|
114
|
-
const container = containerRef.current;
|
|
115
|
-
const element = container === null || container === void 0 ? void 0 : container.querySelector(`[data-value="${value}"]`);
|
|
116
|
-
scrollToElement(element, container, {
|
|
117
|
-
behavior,
|
|
118
|
-
align,
|
|
119
|
-
...scrollOptions,
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
}, [align, behavior]);
|
|
123
|
-
/**
|
|
124
|
-
* 滚动到指定的 HTMLElement 元素
|
|
125
|
-
* @param element - 目标 HTMLElement 元素
|
|
126
|
-
* @param scrollOptions - 可选的滚动配置,覆盖默认配置
|
|
127
|
-
*/
|
|
128
|
-
const scrollTo = useCallback((element, scrollOptions) => {
|
|
129
|
-
requestAnimationFrame(() => {
|
|
130
|
-
scrollToElement(element, containerRef.current, {
|
|
131
|
-
behavior,
|
|
132
|
-
align,
|
|
133
|
-
...scrollOptions,
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
}, [align, behavior]);
|
|
137
|
-
return {
|
|
138
|
-
/** 绑定到可滚动容器的 ref */
|
|
139
|
-
containerRef,
|
|
140
|
-
/** 滚动到指定 data-value 值的元素 */
|
|
141
|
-
scrollToValue,
|
|
142
|
-
/** 滚动到指定 HTMLElement 元素 */
|
|
143
|
-
scrollTo,
|
|
144
|
-
};
|
|
145
|
-
};
|
package/dist/utils/tailwind.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type ClassValue } from 'clsx';
|
|
2
|
-
/**
|
|
3
|
-
* // ❌ 直接用 twMerge 很麻烦
|
|
4
|
-
* twMerge(`base ${isActive ? 'bg-blue-500' : ''} ${isDisabled ? 'opacity-50' : ''}`)
|
|
5
|
-
*
|
|
6
|
-
* // ✅ 用 cn 更简洁
|
|
7
|
-
* cn('base', isActive && 'bg-blue-500', isDisabled && 'opacity-50')
|
|
8
|
-
* cn('base', { 'bg-blue-500': isActive, 'opacity-50': isDisabled })
|
|
9
|
-
*
|
|
10
|
-
* 合并css样式
|
|
11
|
-
* @param inputs
|
|
12
|
-
*/
|
|
13
|
-
export declare function cn(...inputs: ClassValue[]): string;
|
|
14
|
-
//# sourceMappingURL=tailwind.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tailwind.d.ts","sourceRoot":"","sources":["../../src/utils/tailwind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,UAAU,EAAC,MAAM,MAAM,CAAA;AAI1C;;;;;;;;;;GAUG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
package/dist/utils/tailwind.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { clsx } from 'clsx';
|
|
2
|
-
import { twMerge } from "tailwind-merge";
|
|
3
|
-
/**
|
|
4
|
-
* // ❌ 直接用 twMerge 很麻烦
|
|
5
|
-
* twMerge(`base ${isActive ? 'bg-blue-500' : ''} ${isDisabled ? 'opacity-50' : ''}`)
|
|
6
|
-
*
|
|
7
|
-
* // ✅ 用 cn 更简洁
|
|
8
|
-
* cn('base', isActive && 'bg-blue-500', isDisabled && 'opacity-50')
|
|
9
|
-
* cn('base', { 'bg-blue-500': isActive, 'opacity-50': isDisabled })
|
|
10
|
-
*
|
|
11
|
-
* 合并css样式
|
|
12
|
-
* @param inputs
|
|
13
|
-
*/
|
|
14
|
-
export function cn(...inputs) {
|
|
15
|
-
return twMerge(clsx(inputs));
|
|
16
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|