deepsea-components 3.2.0 → 3.2.1

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.
@@ -71,7 +71,11 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
71
71
  element?: RefObject<HTMLDivElement>;
72
72
  }
73
73
  export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
74
- export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
74
+ export interface GapAndCount {
75
+ count: number;
76
+ gap: number;
77
+ }
78
+ export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): GapAndCount;
75
79
  export interface ManualFlowProps<T> extends FlowProps<T> {
76
80
  /** 组件宽度,必须指定 */
77
81
  width: number;
@@ -41,21 +41,20 @@ function getGapRange(gap) {
41
41
  function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
42
42
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1;
43
43
  if (count === 1)
44
- return [count, 0];
44
+ return { count, gap: 0 };
45
45
  const averageGap = (width - itemWidth * count) / (count - 1);
46
46
  if (averageGap < minGap)
47
- return [count, minGap];
47
+ return { count, gap: minGap };
48
48
  if (maxGap !== "auto" && averageGap > maxGap)
49
- return [count, maxGap];
50
- return [count, averageGap];
49
+ return { count, gap: maxGap };
50
+ return { count, gap: averageGap };
51
51
  }
52
52
  function ManualFlow(props) {
53
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;
54
54
  rowGap ??= gap;
55
55
  columnGap ??= gap;
56
56
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
57
- const [columnCount, setColumnCount] = (0, import_react.useState)(1);
58
- const [columnGapSize, setColumnGapSize] = (0, import_react.useState)(minColumnGap);
57
+ const [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = (0, import_react.useState)(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap));
59
58
  const ele = (0, import_react.useRef)(null);
60
59
  const contentRows = Math.ceil(data.length / columnCount);
61
60
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows;
@@ -73,21 +72,16 @@ function ManualFlow(props) {
73
72
  return false;
74
73
  return index >= maxRows * columnCount;
75
74
  }
76
- function task() {
77
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap);
78
- setColumnCount(newColumnCount);
79
- setColumnGapSize(newColumnGapSize);
80
- }
81
75
  (0, import_react.useImperativeHandle)(element, () => ele.current, [ele.current]);
82
76
  (0, import_react.useEffect)(() => {
83
- task();
84
- }, []);
85
- (0, import_react.useEffect)(() => {
77
+ function task() {
78
+ setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap));
79
+ }
86
80
  if (throttle === 0)
87
81
  return task();
88
82
  const timeout = setTimeout(task, throttle || 200);
89
83
  return () => clearTimeout(timeout);
90
- }, [width, itemWidth, throttle, columnGap]);
84
+ }, [width, itemWidth, throttle, minColumnGap, maxColumnGap]);
91
85
  (0, import_react.useEffect)(() => {
92
86
  onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null });
93
87
  }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows]);
@@ -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?: 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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",
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 interface GapAndCount {\r\n count: number\r\n gap: number\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): GapAndCount {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return { count, gap: 0 }\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return { count, gap: minGap }\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return { count, gap: maxGap }\r\n return { count, gap: 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 [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))\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 useImperativeHandle(element, () => ele.current!, [ele.current])\r\n\r\n useEffect(() => {\r\n function task() {\r\n setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))\r\n }\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, minColumnGap, maxColumnGap])\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
  }
@@ -71,7 +71,11 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
71
71
  element?: RefObject<HTMLDivElement>;
72
72
  }
73
73
  export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
74
- export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
74
+ export interface GapAndCount {
75
+ count: number;
76
+ gap: number;
77
+ }
78
+ export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): GapAndCount;
75
79
  export interface ManualFlowProps<T> extends FlowProps<T> {
76
80
  /** 组件宽度,必须指定 */
77
81
  width: number;
@@ -13,11 +13,23 @@ export function getGapRange(gap) {
13
13
  }
14
14
  export function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
15
15
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1;
16
- if (count === 1) return [count, 0];
16
+ if (count === 1) return {
17
+ count,
18
+ gap: 0
19
+ };
17
20
  const averageGap = (width - itemWidth * count) / (count - 1);
18
- if (averageGap < minGap) return [count, minGap];
19
- if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap];
20
- return [count, averageGap];
21
+ if (averageGap < minGap) return {
22
+ count,
23
+ gap: minGap
24
+ };
25
+ if (maxGap !== "auto" && averageGap > maxGap) return {
26
+ count,
27
+ gap: maxGap
28
+ };
29
+ return {
30
+ count,
31
+ gap: averageGap
32
+ };
21
33
  }
22
34
  /** 手动组件,由外界指定宽度,性能更好 */
23
35
  export function ManualFlow(props) {
@@ -47,8 +59,10 @@ export function ManualFlow(props) {
47
59
  rowGap ??= gap;
48
60
  columnGap ??= gap;
49
61
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
50
- const [columnCount, setColumnCount] = useState(1);
51
- const [columnGapSize, setColumnGapSize] = useState(minColumnGap);
62
+ const [{
63
+ count: columnCount,
64
+ gap: columnGapSize
65
+ }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap));
52
66
  const ele = useRef(null);
53
67
  const contentRows = Math.ceil(data.length / columnCount);
54
68
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows;
@@ -65,20 +79,15 @@ export function ManualFlow(props) {
65
79
  if (typeof maxRows !== "number") return false;
66
80
  return index >= maxRows * columnCount;
67
81
  }
68
- function task() {
69
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap);
70
- setColumnCount(newColumnCount);
71
- setColumnGapSize(newColumnGapSize);
72
- }
73
82
  useImperativeHandle(element, () => ele.current, [ele.current]);
74
83
  useEffect(() => {
75
- task();
76
- }, []);
77
- useEffect(() => {
84
+ function task() {
85
+ setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap));
86
+ }
78
87
  if (throttle === 0) return task();
79
88
  const timeout = setTimeout(task, throttle || 200);
80
89
  return () => clearTimeout(timeout);
81
- }, [width, itemWidth, throttle, columnGap]);
90
+ }, [width, itemWidth, throttle, minColumnGap, maxColumnGap]);
82
91
  useEffect(() => {
83
92
  onSizeChange?.({
84
93
  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","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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"}
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","columnGapSize","setGapAndCount","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","current","task","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 interface GapAndCount {\r\n count: number\r\n gap: number\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): GapAndCount {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return { count, gap: 0 }\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return { count, gap: minGap }\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return { count, gap: maxGap }\r\n return { count, gap: 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 [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))\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 useImperativeHandle(element, () => ele.current!, [ele.current])\r\n\r\n useEffect(() => {\r\n function task() {\r\n setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))\r\n }\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, minColumnGap, maxColumnGap])\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.1",
4
4
  "description": "格数科技自用组件库",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -85,13 +85,18 @@ export function getGapRange(gap?: undefined | number | "auto" | (number | "auto"
85
85
  return [0, "auto"]
86
86
  }
87
87
 
88
- export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number] {
88
+ export interface GapAndCount {
89
+ count: number
90
+ gap: number
91
+ }
92
+
93
+ export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): GapAndCount {
89
94
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1
90
- if (count === 1) return [count, 0]
95
+ if (count === 1) return { count, gap: 0 }
91
96
  const averageGap = (width - itemWidth * count) / (count - 1)
92
- if (averageGap < minGap) return [count, minGap]
93
- if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap]
94
- return [count, averageGap]
97
+ if (averageGap < minGap) return { count, gap: minGap }
98
+ if (maxGap !== "auto" && averageGap > maxGap) return { count, gap: maxGap }
99
+ return { count, gap: averageGap }
95
100
  }
96
101
 
97
102
  export interface ManualFlowProps<T> extends FlowProps<T> {
@@ -105,8 +110,7 @@ export function ManualFlow<T>(props: ManualFlowProps<T>) {
105
110
  rowGap ??= gap
106
111
  columnGap ??= gap
107
112
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
108
- const [columnCount, setColumnCount] = useState(1)
109
- const [columnGapSize, setColumnGapSize] = useState(minColumnGap)
113
+ const [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
110
114
  const ele = useRef<HTMLDivElement>(null)
111
115
  const contentRows = Math.ceil(data.length / columnCount)
112
116
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows
@@ -126,23 +130,16 @@ export function ManualFlow<T>(props: ManualFlowProps<T>) {
126
130
  return index >= maxRows * columnCount
127
131
  }
128
132
 
129
- function task() {
130
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)
131
- setColumnCount(newColumnCount)
132
- setColumnGapSize(newColumnGapSize)
133
- }
134
-
135
133
  useImperativeHandle(element, () => ele.current!, [ele.current])
136
134
 
137
135
  useEffect(() => {
138
- task()
139
- }, [])
140
-
141
- useEffect(() => {
136
+ function task() {
137
+ setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
138
+ }
142
139
  if (throttle === 0) return task()
143
140
  const timeout = setTimeout(task, throttle || 200)
144
141
  return () => clearTimeout(timeout)
145
- }, [width, itemWidth, throttle, columnGap])
142
+ }, [width, itemWidth, throttle, minColumnGap, maxColumnGap])
146
143
 
147
144
  useEffect(() => {
148
145
  onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })