deepsea-components 3.2.0-beta.20240606185348 → 3.2.0
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/cjs/components/Flow.d.ts +7 -1
- package/dist/cjs/components/Flow.js +5 -3
- package/dist/cjs/components/Flow.js.map +2 -2
- package/dist/esm/components/Flow.d.ts +7 -1
- package/dist/esm/components/Flow.js +4 -3
- package/dist/esm/components/Flow.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Flow.tsx +9 -9
|
@@ -41,7 +41,7 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
|
|
|
41
41
|
/** 最大行数 */
|
|
42
42
|
maxRows?: number | null;
|
|
43
43
|
/** 源数据 */
|
|
44
|
-
data
|
|
44
|
+
data?: T[];
|
|
45
45
|
/** 渲染 */
|
|
46
46
|
render: (item: T, index: number, arr: T[]) => ReactNode;
|
|
47
47
|
/** key释放器,默认为 index */
|
|
@@ -72,5 +72,11 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
|
|
|
72
72
|
}
|
|
73
73
|
export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
|
|
74
74
|
export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
|
|
75
|
+
export interface ManualFlowProps<T> extends FlowProps<T> {
|
|
76
|
+
/** 组件宽度,必须指定 */
|
|
77
|
+
width: number;
|
|
78
|
+
}
|
|
79
|
+
/** 手动组件,由外界指定宽度,性能更好 */
|
|
80
|
+
export declare function ManualFlow<T>(props: ManualFlowProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
75
81
|
/** 自适应浮动组件 */
|
|
76
82
|
export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var Flow_exports = {};
|
|
22
22
|
__export(Flow_exports, {
|
|
23
23
|
Flow: () => Flow,
|
|
24
|
+
ManualFlow: () => ManualFlow,
|
|
24
25
|
getGapCountAndSize: () => getGapCountAndSize,
|
|
25
26
|
getGapRange: () => getGapRange
|
|
26
27
|
});
|
|
@@ -48,8 +49,8 @@ function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
|
|
|
48
49
|
return [count, maxGap];
|
|
49
50
|
return [count, averageGap];
|
|
50
51
|
}
|
|
51
|
-
function
|
|
52
|
-
let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props;
|
|
52
|
+
function ManualFlow(props) {
|
|
53
|
+
let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data = [], render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props;
|
|
53
54
|
rowGap ??= gap;
|
|
54
55
|
columnGap ??= gap;
|
|
55
56
|
const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
|
|
@@ -157,11 +158,12 @@ function Flow(props) {
|
|
|
157
158
|
(0, import_react.useImperativeHandle)(element, () => ele.current, [ele.current]);
|
|
158
159
|
if (!size)
|
|
159
160
|
return /* @__PURE__ */ React.createElement("div", { ref: ele, ...rest });
|
|
160
|
-
return /* @__PURE__ */ React.createElement(
|
|
161
|
+
return /* @__PURE__ */ React.createElement(ManualFlow, { element: ele, ...props, width: size.width });
|
|
161
162
|
}
|
|
162
163
|
// Annotate the CommonJS export names for ESM import in node:
|
|
163
164
|
0 && (module.exports = {
|
|
164
165
|
Flow,
|
|
166
|
+
ManualFlow,
|
|
165
167
|
getGapCountAndSize,
|
|
166
168
|
getGapRange
|
|
167
169
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/Flow.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { useSize } from \"ahooks\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, RefObject, useEffect, useImperativeHandle, useRef, useState } from \"react\"\r\nimport { px, transformCSSVariable } from \"../utils\"\r\n\r\nexport interface FlowSizeData {\r\n /** 容器宽度 */\r\n width: number\r\n /** 容器高度 */\r\n height: number\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /** 列间距 */\r\n columnGap: number\r\n /** 列数 */\r\n columnCount: number\r\n /** 行间距 */\r\n rowGap: number\r\n /** 行数 */\r\n rowCount: number\r\n /** 元素格数 */\r\n itemCount: number\r\n /** 最大行数 */\r\n maxRows: number | null\r\n /** 是否有元素被隐藏 */\r\n overflow: boolean\r\n}\r\n\r\nexport interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /**\r\n * 列间距\r\n * 1. 如果是数字,表示列间距是固定的\r\n * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的\r\n * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值\r\n */\r\n columnGap?: number | \"auto\" | [number | \"auto\", number | \"auto\"]\r\n /** 行间距 */\r\n rowGap?: number\r\n gap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAoB;AACpB,oBAAwB;AACxB,2BAAqB;AACrB,mBAA2H;AAC3H,mBAAyC;AA2ElC,SAAS,YAAY,KAAoF;AAC5G,MAAI,OAAO,QAAQ;AAAU,WAAO,CAAC,KAAK,GAAG;AAC7C,MAAI,MAAM,QAAQ,GAAG;AAAG,WAAO,CAAC,OAAO,IAAI,CAAC,MAAM,WAAW,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;AAC/E,SAAO,CAAC,GAAG,MAAM;AACrB;AAEO,SAAS,mBAAmB,OAAe,WAAmB,QAAgB,QAA2C;AAC5H,QAAM,QAAQ,KAAK,OAAO,QAAQ,WAAW,YAAY,OAAO,KAAK;AACrE,MAAI,UAAU;AAAG,WAAO,CAAC,OAAO,CAAC;AACjC,QAAM,cAAc,QAAQ,YAAY,UAAU,QAAQ;AAC1D,MAAI,aAAa;AAAQ,WAAO,CAAC,OAAO,MAAM;AAC9C,MAAI,WAAW,UAAU,aAAa;AAAQ,WAAO,CAAC,OAAO,MAAM;AACnE,SAAO,CAAC,OAAO,UAAU;AAC7B;
|
|
4
|
+
"sourcesContent": ["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { useSize } from \"ahooks\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, RefObject, useEffect, useImperativeHandle, useRef, useState } from \"react\"\r\nimport { px, transformCSSVariable } from \"../utils\"\r\n\r\nexport interface FlowSizeData {\r\n /** 容器宽度 */\r\n width: number\r\n /** 容器高度 */\r\n height: number\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /** 列间距 */\r\n columnGap: number\r\n /** 列数 */\r\n columnCount: number\r\n /** 行间距 */\r\n rowGap: number\r\n /** 行数 */\r\n rowCount: number\r\n /** 元素格数 */\r\n itemCount: number\r\n /** 最大行数 */\r\n maxRows: number | null\r\n /** 是否有元素被隐藏 */\r\n overflow: boolean\r\n}\r\n\r\nexport interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /**\r\n * 列间距\r\n * 1. 如果是数字,表示列间距是固定的\r\n * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的\r\n * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值\r\n */\r\n columnGap?: number | \"auto\" | [number | \"auto\", number | \"auto\"]\r\n /** 行间距 */\r\n rowGap?: number\r\n gap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data?: T[]\r\n /** 渲染 */\r\n render: (item: T, index: number, arr: T[]) => ReactNode\r\n /** key释放器,默认为 index */\r\n keyExactor?: (item: T, index: number, arr: T[]) => Key\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器类名\r\n */\r\n wrapperClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器样式\r\n */\r\n wrapperStyle?: CSSProperties\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器类名\r\n */\r\n containerClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器样式\r\n */\r\n containerStyle?: CSSProperties\r\n /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */\r\n throttle?: number\r\n /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */\r\n transitionDuration?: number\r\n /** 变化的回调函数 */\r\n onSizeChange?: (sizeData: FlowSizeData) => void\r\n element?: RefObject<HTMLDivElement>\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | \"auto\" | (number | \"auto\")[]): [number, number | \"auto\"] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [typeof gap[0] === \"number\" ? gap[0] : 0, gap[1]]\r\n return [0, \"auto\"]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): [number, number] {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return [count, 0]\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return [count, minGap]\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return [count, maxGap]\r\n return [count, averageGap]\r\n}\r\n\r\nexport interface ManualFlowProps<T> extends FlowProps<T> {\r\n /** 组件宽度,必须指定 */\r\n width: number\r\n}\r\n\r\n/** 手动组件,由外界指定宽度,性能更好 */\r\nexport function ManualFlow<T>(props: ManualFlowProps<T>) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data = [], render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const ele = useRef<HTMLDivElement>(null)\r\n const contentRows = Math.ceil(data.length / columnCount)\r\n const contentShownRows = typeof maxRows === \"number\" ? Math.min(contentRows, maxRows) : contentRows\r\n const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0\r\n\r\n function getPosition(index: number) {\r\n const y = Math.floor(index / columnCount)\r\n const x = index - y * columnCount\r\n return {\r\n left: x * (itemWidth + columnGapSize),\r\n top: y * (itemHeight + rowGap!)\r\n }\r\n }\r\n\r\n function getHidden(index: number) {\r\n if (typeof maxRows !== \"number\") return false\r\n return index >= maxRows * columnCount\r\n }\r\n\r\n function task() {\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n\r\n useEffect(() => {\r\n task()\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (throttle === 0) return task()\r\n const timeout = setTimeout(task, throttle || 200)\r\n return () => clearTimeout(timeout)\r\n }, [width, itemWidth, throttle, columnGap])\r\n\r\n useEffect(() => {\r\n onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })\r\n }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])\r\n\r\n return (\r\n <div\r\n ref={ele}\r\n className={clsx(\r\n css`\r\n position: relative;\r\n height: var(--height);\r\n overflow: hidden;\r\n `,\r\n className\r\n )}\r\n style={transformCSSVariable({ height: px(height) }, style)}\r\n {...rest}>\r\n {data.map((item, index, arr) => (\r\n <div\r\n key={keyExactor ? keyExactor(item, index, arr) : index}\r\n className={clsx(\r\n css`\r\n position: absolute;\r\n width: var(--width);\r\n height: var(--height);\r\n transition: var(--transition);\r\n left: 0;\r\n top: 0;\r\n transform: translate(var(--left), var(--top));\r\n `,\r\n wrapperClassName\r\n )}\r\n style={transformCSSVariable(\r\n {\r\n width: px(itemWidth),\r\n height: px(itemHeight),\r\n transition: transitionDuration === 0 ? \"none\" : `all ${transitionDuration || 400}ms`,\r\n left: px(getPosition(index).left),\r\n top: px(getPosition(index).top)\r\n },\r\n wrapperStyle\r\n )}>\r\n <div\r\n className={clsx(\r\n css`\r\n width: 100%;\r\n height: 100%;\r\n display: var(--display);\r\n `,\r\n containerClassName\r\n )}\r\n style={transformCSSVariable({ display: getHidden(index) ? \"none\" : \"block\" }, containerStyle)}>\r\n {render(item, index, arr)}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n\r\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n const { itemWidth, itemHeight, columnGap, rowGap, gap, maxRows, data, render, keyExactor, wrapperClassName, wrapperStyle, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, element, ...rest } = props\r\n const ele = useRef<HTMLDivElement>(null)\r\n const size = useSize(ele)\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n if (!size) return <div ref={ele} {...rest} />\r\n return <ManualFlow element={ele} {...props} width={size.width} />\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -41,7 +41,7 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
|
|
|
41
41
|
/** 最大行数 */
|
|
42
42
|
maxRows?: number | null;
|
|
43
43
|
/** 源数据 */
|
|
44
|
-
data
|
|
44
|
+
data?: T[];
|
|
45
45
|
/** 渲染 */
|
|
46
46
|
render: (item: T, index: number, arr: T[]) => ReactNode;
|
|
47
47
|
/** key释放器,默认为 index */
|
|
@@ -72,5 +72,11 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
|
|
|
72
72
|
}
|
|
73
73
|
export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
|
|
74
74
|
export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
|
|
75
|
+
export interface ManualFlowProps<T> extends FlowProps<T> {
|
|
76
|
+
/** 组件宽度,必须指定 */
|
|
77
|
+
width: number;
|
|
78
|
+
}
|
|
79
|
+
/** 手动组件,由外界指定宽度,性能更好 */
|
|
80
|
+
export declare function ManualFlow<T>(props: ManualFlowProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
75
81
|
/** 自适应浮动组件 */
|
|
76
82
|
export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -19,14 +19,15 @@ export function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
|
|
|
19
19
|
if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap];
|
|
20
20
|
return [count, averageGap];
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
/** 手动组件,由外界指定宽度,性能更好 */
|
|
23
|
+
export function ManualFlow(props) {
|
|
23
24
|
let {
|
|
24
25
|
itemWidth,
|
|
25
26
|
itemHeight,
|
|
26
27
|
columnGap,
|
|
27
28
|
rowGap,
|
|
28
29
|
maxRows,
|
|
29
|
-
data,
|
|
30
|
+
data = [],
|
|
30
31
|
render,
|
|
31
32
|
keyExactor,
|
|
32
33
|
className,
|
|
@@ -165,7 +166,7 @@ export function Flow(props) {
|
|
|
165
166
|
ref: ele,
|
|
166
167
|
...rest
|
|
167
168
|
});
|
|
168
|
-
return /*#__PURE__*/_jsx(
|
|
169
|
+
return /*#__PURE__*/_jsx(ManualFlow, {
|
|
169
170
|
element: ele,
|
|
170
171
|
...props,
|
|
171
172
|
width: size.width
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["css","useSize","clsx","useEffect","useImperativeHandle","useRef","useState","px","transformCSSVariable","jsx","_jsx","getGapRange","gap","Array","isArray","getGapCountAndSize","width","itemWidth","minGap","maxGap","count","Math","floor","averageGap","RealFlow","props","itemHeight","columnGap","rowGap","maxRows","data","render","keyExactor","className","style","wrapperClassName","wrapperStyle","throttle","transitionDuration","onSizeChange","containerClassName","containerStyle","element","rest","minColumnGap","maxColumnGap","columnCount","setColumnCount","columnGapSize","setColumnGapSize","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","task","newColumnCount","newColumnGapSize","current","timeout","setTimeout","clearTimeout","rowCount","overflow","itemCount","ref","children","map","item","arr","transition","display","Flow","size"],"sources":["../../../src/components/Flow.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { useSize } from \"ahooks\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, RefObject, useEffect, useImperativeHandle, useRef, useState } from \"react\"\r\nimport { px, transformCSSVariable } from \"../utils\"\r\n\r\nexport interface FlowSizeData {\r\n /** 容器宽度 */\r\n width: number\r\n /** 容器高度 */\r\n height: number\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /** 列间距 */\r\n columnGap: number\r\n /** 列数 */\r\n columnCount: number\r\n /** 行间距 */\r\n rowGap: number\r\n /** 行数 */\r\n rowCount: number\r\n /** 元素格数 */\r\n itemCount: number\r\n /** 最大行数 */\r\n maxRows: number | null\r\n /** 是否有元素被隐藏 */\r\n overflow: boolean\r\n}\r\n\r\nexport interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /**\r\n * 列间距\r\n * 1. 如果是数字,表示列间距是固定的\r\n * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的\r\n * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值\r\n */\r\n columnGap?: number | \"auto\" | [number | \"auto\", number | \"auto\"]\r\n /** 行间距 */\r\n rowGap?: number\r\n gap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data: T[]\r\n /** 渲染 */\r\n render: (item: T, index: number, arr: T[]) => ReactNode\r\n /** key释放器,默认为 index */\r\n keyExactor?: (item: T, index: number, arr: T[]) => Key\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器类名\r\n */\r\n wrapperClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器样式\r\n */\r\n wrapperStyle?: CSSProperties\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器类名\r\n */\r\n containerClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器样式\r\n */\r\n containerStyle?: CSSProperties\r\n /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */\r\n throttle?: number\r\n /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */\r\n transitionDuration?: number\r\n /** 变化的回调函数 */\r\n onSizeChange?: (sizeData: FlowSizeData) => void\r\n element?: RefObject<HTMLDivElement>\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | \"auto\" | (number | \"auto\")[]): [number, number | \"auto\"] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [typeof gap[0] === \"number\" ? gap[0] : 0, gap[1]]\r\n return [0, \"auto\"]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): [number, number] {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return [count, 0]\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return [count, minGap]\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return [count, maxGap]\r\n return [count, averageGap]\r\n}\r\n\r\ninterface Position {\r\n left: number\r\n top: number\r\n}\r\n\r\nfunction RealFlow<T>(props: FlowProps<T> & { width: number }) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n\r\n const ele = useRef<HTMLDivElement>(null)\r\n const contentRows = Math.ceil(data.length / columnCount)\r\n const contentShownRows = typeof maxRows === \"number\" ? Math.min(contentRows, maxRows) : contentRows\r\n const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0\r\n\r\n function getPosition(index: number): Position {\r\n const y = Math.floor(index / columnCount)\r\n const x = index - y * columnCount\r\n return {\r\n left: x * (itemWidth + columnGapSize),\r\n top: y * (itemHeight + rowGap!)\r\n }\r\n }\r\n\r\n function getHidden(index: number) {\r\n if (typeof maxRows !== \"number\") return false\r\n return index >= maxRows * columnCount\r\n }\r\n\r\n function task() {\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n\r\n useEffect(() => {\r\n task()\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (throttle === 0) return task()\r\n const timeout = setTimeout(task, throttle || 200)\r\n return () => clearTimeout(timeout)\r\n }, [width, itemWidth, throttle, columnGap])\r\n\r\n useEffect(() => {\r\n onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })\r\n }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])\r\n\r\n return (\r\n <div\r\n ref={ele}\r\n className={clsx(\r\n css`\r\n position: relative;\r\n height: var(--height);\r\n overflow: hidden;\r\n `,\r\n className\r\n )}\r\n style={transformCSSVariable({ height: px(height) }, style)}\r\n {...rest}>\r\n {data.map((item, index, arr) => (\r\n <div\r\n key={keyExactor ? keyExactor(item, index, arr) : index}\r\n className={clsx(\r\n css`\r\n position: absolute;\r\n width: var(--width);\r\n height: var(--height);\r\n transition: var(--transition);\r\n left: 0;\r\n top: 0;\r\n transform: translate(var(--left), var(--top));\r\n `,\r\n wrapperClassName\r\n )}\r\n style={transformCSSVariable(\r\n {\r\n width: px(itemWidth),\r\n height: px(itemHeight),\r\n transition: transitionDuration === 0 ? \"none\" : `all ${transitionDuration || 400}ms`,\r\n left: px(getPosition(index).left),\r\n top: px(getPosition(index).top)\r\n },\r\n wrapperStyle\r\n )}>\r\n <div\r\n className={clsx(\r\n css`\r\n width: 100%;\r\n height: 100%;\r\n display: var(--display);\r\n `,\r\n containerClassName\r\n )}\r\n style={transformCSSVariable({ display: getHidden(index) ? \"none\" : \"block\" }, containerStyle)}>\r\n {render(item, index, arr)}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n\r\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n const { itemWidth, itemHeight, columnGap, rowGap, gap, maxRows, data, render, keyExactor, wrapperClassName, wrapperStyle, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, element, ...rest } = props\r\n const ele = useRef<HTMLDivElement>(null)\r\n const size = useSize(ele)\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n if (!size) return <div ref={ele} {...rest} />\r\n return <RealFlow element={ele} {...props} width={size.width} />\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["css","useSize","clsx","useEffect","useImperativeHandle","useRef","useState","px","transformCSSVariable","jsx","_jsx","getGapRange","gap","Array","isArray","getGapCountAndSize","width","itemWidth","minGap","maxGap","count","Math","floor","averageGap","ManualFlow","props","itemHeight","columnGap","rowGap","maxRows","data","render","keyExactor","className","style","wrapperClassName","wrapperStyle","throttle","transitionDuration","onSizeChange","containerClassName","containerStyle","element","rest","minColumnGap","maxColumnGap","columnCount","setColumnCount","columnGapSize","setColumnGapSize","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","task","newColumnCount","newColumnGapSize","current","timeout","setTimeout","clearTimeout","rowCount","overflow","itemCount","ref","children","map","item","arr","transition","display","Flow","size"],"sources":["../../../src/components/Flow.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { useSize } from \"ahooks\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, RefObject, useEffect, useImperativeHandle, useRef, useState } from \"react\"\r\nimport { px, transformCSSVariable } from \"../utils\"\r\n\r\nexport interface FlowSizeData {\r\n /** 容器宽度 */\r\n width: number\r\n /** 容器高度 */\r\n height: number\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /** 列间距 */\r\n columnGap: number\r\n /** 列数 */\r\n columnCount: number\r\n /** 行间距 */\r\n rowGap: number\r\n /** 行数 */\r\n rowCount: number\r\n /** 元素格数 */\r\n itemCount: number\r\n /** 最大行数 */\r\n maxRows: number | null\r\n /** 是否有元素被隐藏 */\r\n overflow: boolean\r\n}\r\n\r\nexport interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\r\n /** 元素宽度 */\r\n itemWidth: number\r\n /** 元素高度 */\r\n itemHeight: number\r\n /**\r\n * 列间距\r\n * 1. 如果是数字,表示列间距是固定的\r\n * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的\r\n * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值\r\n */\r\n columnGap?: number | \"auto\" | [number | \"auto\", number | \"auto\"]\r\n /** 行间距 */\r\n rowGap?: number\r\n gap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data?: T[]\r\n /** 渲染 */\r\n render: (item: T, index: number, arr: T[]) => ReactNode\r\n /** key释放器,默认为 index */\r\n keyExactor?: (item: T, index: number, arr: T[]) => Key\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器类名\r\n */\r\n wrapperClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,外层容器样式\r\n */\r\n wrapperStyle?: CSSProperties\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器类名\r\n */\r\n containerClassName?: string\r\n /**\r\n * 渲染的元素由两层容器包裹,内层容器样式\r\n */\r\n containerStyle?: CSSProperties\r\n /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */\r\n throttle?: number\r\n /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */\r\n transitionDuration?: number\r\n /** 变化的回调函数 */\r\n onSizeChange?: (sizeData: FlowSizeData) => void\r\n element?: RefObject<HTMLDivElement>\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | \"auto\" | (number | \"auto\")[]): [number, number | \"auto\"] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [typeof gap[0] === \"number\" ? gap[0] : 0, gap[1]]\r\n return [0, \"auto\"]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): [number, number] {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return [count, 0]\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return [count, minGap]\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return [count, maxGap]\r\n return [count, averageGap]\r\n}\r\n\r\nexport interface ManualFlowProps<T> extends FlowProps<T> {\r\n /** 组件宽度,必须指定 */\r\n width: number\r\n}\r\n\r\n/** 手动组件,由外界指定宽度,性能更好 */\r\nexport function ManualFlow<T>(props: ManualFlowProps<T>) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data = [], render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const ele = useRef<HTMLDivElement>(null)\r\n const contentRows = Math.ceil(data.length / columnCount)\r\n const contentShownRows = typeof maxRows === \"number\" ? Math.min(contentRows, maxRows) : contentRows\r\n const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0\r\n\r\n function getPosition(index: number) {\r\n const y = Math.floor(index / columnCount)\r\n const x = index - y * columnCount\r\n return {\r\n left: x * (itemWidth + columnGapSize),\r\n top: y * (itemHeight + rowGap!)\r\n }\r\n }\r\n\r\n function getHidden(index: number) {\r\n if (typeof maxRows !== \"number\") return false\r\n return index >= maxRows * columnCount\r\n }\r\n\r\n function task() {\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n\r\n useEffect(() => {\r\n task()\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (throttle === 0) return task()\r\n const timeout = setTimeout(task, throttle || 200)\r\n return () => clearTimeout(timeout)\r\n }, [width, itemWidth, throttle, columnGap])\r\n\r\n useEffect(() => {\r\n onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })\r\n }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])\r\n\r\n return (\r\n <div\r\n ref={ele}\r\n className={clsx(\r\n css`\r\n position: relative;\r\n height: var(--height);\r\n overflow: hidden;\r\n `,\r\n className\r\n )}\r\n style={transformCSSVariable({ height: px(height) }, style)}\r\n {...rest}>\r\n {data.map((item, index, arr) => (\r\n <div\r\n key={keyExactor ? keyExactor(item, index, arr) : index}\r\n className={clsx(\r\n css`\r\n position: absolute;\r\n width: var(--width);\r\n height: var(--height);\r\n transition: var(--transition);\r\n left: 0;\r\n top: 0;\r\n transform: translate(var(--left), var(--top));\r\n `,\r\n wrapperClassName\r\n )}\r\n style={transformCSSVariable(\r\n {\r\n width: px(itemWidth),\r\n height: px(itemHeight),\r\n transition: transitionDuration === 0 ? \"none\" : `all ${transitionDuration || 400}ms`,\r\n left: px(getPosition(index).left),\r\n top: px(getPosition(index).top)\r\n },\r\n wrapperStyle\r\n )}>\r\n <div\r\n className={clsx(\r\n css`\r\n width: 100%;\r\n height: 100%;\r\n display: var(--display);\r\n `,\r\n containerClassName\r\n )}\r\n style={transformCSSVariable({ display: getHidden(index) ? \"none\" : \"block\" }, containerStyle)}>\r\n {render(item, index, arr)}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n\r\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n const { itemWidth, itemHeight, columnGap, rowGap, gap, maxRows, data, render, keyExactor, wrapperClassName, wrapperStyle, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, element, ...rest } = props\r\n const ele = useRef<HTMLDivElement>(null)\r\n const size = useSize(ele)\r\n useImperativeHandle(element, () => ele.current!, [ele.current])\r\n if (!size) return <div ref={ele} {...rest} />\r\n return <ManualFlow element={ele} {...props} width={size.width} />\r\n}\r\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepsea-components",
|
|
3
|
-
"version": "3.2.0
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "格数科技自用组件库",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -45,4 +45,4 @@
|
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": "^18.3.1"
|
|
47
47
|
}
|
|
48
|
-
}
|
|
48
|
+
}
|
package/src/components/Flow.tsx
CHANGED
|
@@ -49,7 +49,7 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
|
|
|
49
49
|
/** 最大行数 */
|
|
50
50
|
maxRows?: number | null
|
|
51
51
|
/** 源数据 */
|
|
52
|
-
data
|
|
52
|
+
data?: T[]
|
|
53
53
|
/** 渲染 */
|
|
54
54
|
render: (item: T, index: number, arr: T[]) => ReactNode
|
|
55
55
|
/** key释放器,默认为 index */
|
|
@@ -94,25 +94,25 @@ export function getGapCountAndSize(width: number, itemWidth: number, minGap: num
|
|
|
94
94
|
return [count, averageGap]
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
interface
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
export interface ManualFlowProps<T> extends FlowProps<T> {
|
|
98
|
+
/** 组件宽度,必须指定 */
|
|
99
|
+
width: number
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
/** 手动组件,由外界指定宽度,性能更好 */
|
|
103
|
+
export function ManualFlow<T>(props: ManualFlowProps<T>) {
|
|
104
|
+
let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data = [], render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, element, ...rest } = props
|
|
104
105
|
rowGap ??= gap
|
|
105
106
|
columnGap ??= gap
|
|
106
107
|
const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
|
|
107
108
|
const [columnCount, setColumnCount] = useState(1)
|
|
108
109
|
const [columnGapSize, setColumnGapSize] = useState(minColumnGap)
|
|
109
|
-
|
|
110
110
|
const ele = useRef<HTMLDivElement>(null)
|
|
111
111
|
const contentRows = Math.ceil(data.length / columnCount)
|
|
112
112
|
const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows
|
|
113
113
|
const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0
|
|
114
114
|
|
|
115
|
-
function getPosition(index: number)
|
|
115
|
+
function getPosition(index: number) {
|
|
116
116
|
const y = Math.floor(index / columnCount)
|
|
117
117
|
const x = index - y * columnCount
|
|
118
118
|
return {
|
|
@@ -211,5 +211,5 @@ export function Flow<T>(props: FlowProps<T>) {
|
|
|
211
211
|
const size = useSize(ele)
|
|
212
212
|
useImperativeHandle(element, () => ele.current!, [ele.current])
|
|
213
213
|
if (!size) return <div ref={ele} {...rest} />
|
|
214
|
-
return <
|
|
214
|
+
return <ManualFlow element={ele} {...props} width={size.width} />
|
|
215
215
|
}
|