deepsea-components 3.0.1 → 3.0.2-beta.20240527151438

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.
@@ -1,4 +1,4 @@
1
- import { CSSProperties, HTMLAttributes, ReactNode } from "react";
1
+ import { CSSProperties, HTMLAttributes, Key, ReactNode } from "react";
2
2
  export interface FlowSizeData {
3
3
  /** 容器宽度 */
4
4
  width: number;
@@ -28,30 +28,40 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
28
28
  itemWidth: number;
29
29
  /** 元素高度 */
30
30
  itemHeight: number;
31
- /** 列间距 */
32
- columnGap?: number | null | (number | null)[];
31
+ /**
32
+ * 列间距
33
+ * 1. 如果是数字,表示列间距是固定的
34
+ * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的
35
+ * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值
36
+ */
37
+ columnGap?: number | "auto" | [number | "auto", number | "auto"];
33
38
  /** 行间距 */
34
39
  rowGap?: number;
40
+ gap?: number;
35
41
  /** 最大行数 */
36
42
  maxRows?: number | null;
37
43
  /** 源数据 */
38
44
  data: T[];
39
45
  /** 渲染 */
40
- render: (item: T, index: number, hidden: boolean) => ReactNode;
46
+ render: (item: T, index: number, arr: T[]) => ReactNode;
41
47
  /** key释放器,默认为 index */
42
- keyExactor?: (item: T, index: number) => string | number;
48
+ keyExactor?: (item: T, index: number, arr: T[]) => Key;
49
+ /** 容器类名 */
50
+ wrapperClassName?: string;
51
+ /** 容器样式 */
52
+ wrapperStyle?: CSSProperties;
43
53
  /** 容器类名 */
44
54
  containerClassName?: string;
45
55
  /** 容器样式 */
46
56
  containerStyle?: CSSProperties;
47
- /** 节流时间,单位毫秒,默认200ms,传入 null 不节流 */
48
- throttle?: number | null;
49
- /** 动画时间,单位毫秒,默认400ms,传入 null 不展示动画 */
50
- transitionDuration?: number | null;
57
+ /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */
58
+ throttle?: number;
59
+ /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */
60
+ transitionDuration?: number;
51
61
  /** 变化的回调函数 */
52
62
  onSizeChange?: (sizeData: FlowSizeData) => void;
53
63
  }
54
- export declare function getGapRange(gap?: undefined | number | null | (number | null)[]): [number, number | null];
55
- export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | null): [number, number];
64
+ export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
65
+ export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
56
66
  /** 自适应浮动组件 */
57
67
  export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -25,13 +25,16 @@ __export(Flow_exports, {
25
25
  getGapRange: () => getGapRange
26
26
  });
27
27
  module.exports = __toCommonJS(Flow_exports);
28
+ var import_css = require("@emotion/css");
29
+ var import_deepsea_tools = require("deepsea-tools");
28
30
  var import_react = require("react");
31
+ var import_utils = require("../utils");
29
32
  function getGapRange(gap) {
30
33
  if (typeof gap === "number")
31
34
  return [gap, gap];
32
35
  if (Array.isArray(gap))
33
- return [gap[0] || 0, gap[1]];
34
- return [0, null];
36
+ return [typeof gap[0] === "number" ? gap[0] : 0, gap[1]];
37
+ return [0, "auto"];
35
38
  }
36
39
  function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
37
40
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1;
@@ -40,12 +43,14 @@ function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
40
43
  const averageGap = (width - itemWidth * count) / (count - 1);
41
44
  if (averageGap < minGap)
42
45
  return [count, minGap];
43
- if (maxGap !== null && averageGap > maxGap)
46
+ if (maxGap !== "auto" && averageGap > maxGap)
44
47
  return [count, maxGap];
45
48
  return [count, averageGap];
46
49
  }
47
50
  function Flow(props) {
48
- const { itemWidth, itemHeight, columnGap, rowGap = 0, maxRows, data, render, keyExactor, className, style, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, ...rest } = props;
51
+ let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props;
52
+ rowGap ??= gap;
53
+ columnGap ??= gap;
49
54
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
50
55
  const [width, setWidth] = (0, import_react.useState)(0);
51
56
  const [columnCount, setColumnCount] = (0, import_react.useState)(1);
@@ -80,7 +85,7 @@ function Flow(props) {
80
85
  setColumnCount(newColumnCount);
81
86
  setColumnGapSize(newColumnGapSize);
82
87
  }
83
- if (throttle === null) {
88
+ if (throttle === 0) {
84
89
  task();
85
90
  } else {
86
91
  timeout = window.setTimeout(task, throttle || 200);
@@ -94,21 +99,63 @@ function Flow(props) {
94
99
  (0, import_react.useEffect)(() => {
95
100
  onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null });
96
101
  }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows]);
97
- return /* @__PURE__ */ React.createElement("div", { ref: ele, className, style: { position: "relative", boxSizing: "border-box", height, ...style }, ...rest }, showItems && data.map((item, index) => /* @__PURE__ */ React.createElement(
102
+ return /* @__PURE__ */ React.createElement(
98
103
  "div",
99
104
  {
100
- key: keyExactor ? keyExactor(item, index) : index,
101
- className: containerClassName,
102
- style: {
103
- position: "absolute",
104
- width: itemWidth,
105
- height: itemHeight,
106
- transition: transitionDuration !== null ? `all ${transitionDuration ?? 400}ms` : void 0,
107
- ...getPosition(index)
108
- }
105
+ ref: ele,
106
+ className: (0, import_deepsea_tools.clsx)(
107
+ import_css.css`
108
+ position: relative;
109
+ height: var(--height);
110
+ overflow: hidden;
111
+ `,
112
+ className
113
+ ),
114
+ style: (0, import_utils.styleWithCSSVariable)({ "--height": (0, import_utils.px)(height) }),
115
+ ...rest
109
116
  },
110
- /* @__PURE__ */ React.createElement("div", { style: { width: itemWidth, height: itemHeight, display: maxRows && index >= maxRows * columnCount ? "none" : "block", ...containerStyle } }, render(item, index, getHidden(index)))
111
- )));
117
+ showItems && data.map((item, index, arr) => /* @__PURE__ */ React.createElement(
118
+ "div",
119
+ {
120
+ key: keyExactor ? keyExactor(item, index, arr) : index,
121
+ className: (0, import_deepsea_tools.clsx)(
122
+ import_css.css`
123
+ position: absolute;
124
+ width: var(--width);
125
+ height: var(--height);
126
+ transition: var(--transition);
127
+ left: 0;
128
+ top: 0;
129
+ transform: translate(var(--left), var(--top));
130
+ `,
131
+ wrapperClassName
132
+ ),
133
+ style: (0, import_utils.styleWithCSSVariable)({
134
+ "--width": (0, import_utils.px)(itemWidth),
135
+ "--height": (0, import_utils.px)(itemHeight),
136
+ "--transition": transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
137
+ "--left": (0, import_utils.px)(getPosition(index).left),
138
+ "--top": (0, import_utils.px)(getPosition(index).top),
139
+ ...wrapperStyle
140
+ })
141
+ },
142
+ /* @__PURE__ */ React.createElement(
143
+ "div",
144
+ {
145
+ className: (0, import_deepsea_tools.clsx)(
146
+ import_css.css`
147
+ width: 100%;
148
+ height: 100%;
149
+ display: var(--display);
150
+ `,
151
+ containerClassName
152
+ ),
153
+ style: (0, import_utils.styleWithCSSVariable)({ "--display": getHidden(index) ? "none" : "block", ...containerStyle })
154
+ },
155
+ render(item, index, arr)
156
+ )
157
+ ))
158
+ );
112
159
  }
113
160
  // Annotate the CommonJS export names for ESM import in node:
114
161
  0 && (module.exports = {
@@ -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 { CSSProperties, HTMLAttributes, ReactNode, useEffect, useRef, useState } from \"react\"\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 columnGap?: number | null | (number | null)[]\r\n /** 行间距 */\r\n rowGap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data: T[]\r\n /** 渲染 */\r\n render: (item: T, index: number, hidden: boolean) => ReactNode\r\n /** key释放器,默认为 index */\r\n keyExactor?: (item: T, index: number) => string | number\r\n /** 容器类名 */\r\n containerClassName?: string\r\n /** 容器样式 */\r\n containerStyle?: CSSProperties\r\n /** 节流时间,单位毫秒,默认200ms,传入 null 不节流 */\r\n throttle?: number | null\r\n /** 动画时间,单位毫秒,默认400ms,传入 null 不展示动画 */\r\n transitionDuration?: number | null\r\n /** 变化的回调函数 */\r\n onSizeChange?: (sizeData: FlowSizeData) => void\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | null | (number | null)[]): [number, number | null] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [gap[0] || 0, gap[1]]\r\n return [0, null]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | null): [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 !== null && 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\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n const { itemWidth, itemHeight, columnGap, rowGap = 0, maxRows, data, render, keyExactor, className, style, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, ...rest } = props\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [width, setWidth] = useState(0)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const [showItems, setShowItems] = useState(false)\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 useEffect(() => {\r\n let timeout: number\r\n const observer = new ResizeObserver(entries => {\r\n clearTimeout(timeout)\r\n function task() {\r\n const { width } = entries[0].contentRect\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setShowItems(true)\r\n setWidth(width)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n if (throttle === null) {\r\n task()\r\n } else {\r\n timeout = window.setTimeout(task, throttle || 200)\r\n }\r\n })\r\n observer.observe(ele.current!)\r\n\r\n return () => {\r\n observer.disconnect()\r\n }\r\n }, [itemWidth, throttle, columnGap])\r\n\r\n useEffect(() => {\r\n onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, 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 ref={ele} className={className} style={{ position: \"relative\", boxSizing: \"border-box\", height, ...style }} {...rest}>\r\n {showItems &&\r\n data.map((item, index) => (\r\n <div\r\n key={keyExactor ? keyExactor(item, index) : index}\r\n className={containerClassName}\r\n style={{\r\n position: \"absolute\",\r\n width: itemWidth,\r\n height: itemHeight,\r\n transition: transitionDuration !== null ? `all ${transitionDuration ?? 400}ms` : undefined,\r\n ...getPosition(index)\r\n }}>\r\n <div style={{ width: itemWidth, height: itemHeight, display: maxRows && index >= maxRows * columnCount ? \"none\" : \"block\", ...containerStyle }}>{render(item, index, getHidden(index))}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, useEffect, useRef, useState } from \"react\"\r\nimport { px, styleWithCSSVariable } 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 wrapperClassName?: string\r\n /** 容器样式 */\r\n wrapperStyle?: CSSProperties\r\n /** 容器类名 */\r\n containerClassName?: string\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}\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\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [width, setWidth] = useState(0)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const [showItems, setShowItems] = useState(false)\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 useEffect(() => {\r\n let timeout: number\r\n const observer = new ResizeObserver(entries => {\r\n clearTimeout(timeout)\r\n function task() {\r\n const { width } = entries[0].contentRect\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setShowItems(true)\r\n setWidth(width)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n if (throttle === 0) {\r\n task()\r\n } else {\r\n timeout = window.setTimeout(task, throttle || 200)\r\n }\r\n })\r\n observer.observe(ele.current!)\r\n\r\n return () => {\r\n observer.disconnect()\r\n }\r\n }, [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={styleWithCSSVariable({ \"--height\": px(height) })}\r\n {...rest}>\r\n {showItems &&\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={styleWithCSSVariable({\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 ...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={styleWithCSSVariable({ \"--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"],
5
+ "mappings": "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",
6
6
  "names": ["width"]
7
7
  }
@@ -0,0 +1,8 @@
1
+ import { CSSProperties } from "react";
2
+ export type CSSVariableName = `--${string}`;
3
+ export type CSSVariableValue = string | number;
4
+ export interface StyleWithCSSVariable extends CSSProperties {
5
+ [X: CSSVariableName]: CSSVariableValue;
6
+ }
7
+ export declare function styleWithCSSVariable(style: StyleWithCSSVariable): CSSProperties;
8
+ export declare function px(value: number): string;
@@ -0,0 +1,37 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/index.ts
20
+ var utils_exports = {};
21
+ __export(utils_exports, {
22
+ px: () => px,
23
+ styleWithCSSVariable: () => styleWithCSSVariable
24
+ });
25
+ module.exports = __toCommonJS(utils_exports);
26
+ function styleWithCSSVariable(style) {
27
+ return style;
28
+ }
29
+ function px(value) {
30
+ return `${value}px`;
31
+ }
32
+ // Annotate the CommonJS export names for ESM import in node:
33
+ 0 && (module.exports = {
34
+ px,
35
+ styleWithCSSVariable
36
+ });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/index.ts"],
4
+ "sourcesContent": ["import { CSSProperties } from \"react\"\r\n\r\nexport type CSSVariableName = `--${string}`\r\n\r\nexport type CSSVariableValue = string | number\r\n\r\nexport interface StyleWithCSSVariable extends CSSProperties {\r\n [X: CSSVariableName]: CSSVariableValue\r\n}\r\n\r\nexport function styleWithCSSVariable(style: StyleWithCSSVariable): CSSProperties {\r\n return style\r\n}\r\n\r\nexport function px(value: number): string {\r\n return `${value}px`\r\n}"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,SAAS,qBAAqB,OAA4C;AAC7E,SAAO;AACX;AAEO,SAAS,GAAG,OAAuB;AACtC,SAAO,GAAG;AACd;",
6
+ "names": []
7
+ }
@@ -1,4 +1,4 @@
1
- import { CSSProperties, HTMLAttributes, ReactNode } from "react";
1
+ import { CSSProperties, HTMLAttributes, Key, ReactNode } from "react";
2
2
  export interface FlowSizeData {
3
3
  /** 容器宽度 */
4
4
  width: number;
@@ -28,30 +28,40 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
28
28
  itemWidth: number;
29
29
  /** 元素高度 */
30
30
  itemHeight: number;
31
- /** 列间距 */
32
- columnGap?: number | null | (number | null)[];
31
+ /**
32
+ * 列间距
33
+ * 1. 如果是数字,表示列间距是固定的
34
+ * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的
35
+ * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值
36
+ */
37
+ columnGap?: number | "auto" | [number | "auto", number | "auto"];
33
38
  /** 行间距 */
34
39
  rowGap?: number;
40
+ gap?: number;
35
41
  /** 最大行数 */
36
42
  maxRows?: number | null;
37
43
  /** 源数据 */
38
44
  data: T[];
39
45
  /** 渲染 */
40
- render: (item: T, index: number, hidden: boolean) => ReactNode;
46
+ render: (item: T, index: number, arr: T[]) => ReactNode;
41
47
  /** key释放器,默认为 index */
42
- keyExactor?: (item: T, index: number) => string | number;
48
+ keyExactor?: (item: T, index: number, arr: T[]) => Key;
49
+ /** 容器类名 */
50
+ wrapperClassName?: string;
51
+ /** 容器样式 */
52
+ wrapperStyle?: CSSProperties;
43
53
  /** 容器类名 */
44
54
  containerClassName?: string;
45
55
  /** 容器样式 */
46
56
  containerStyle?: CSSProperties;
47
- /** 节流时间,单位毫秒,默认200ms,传入 null 不节流 */
48
- throttle?: number | null;
49
- /** 动画时间,单位毫秒,默认400ms,传入 null 不展示动画 */
50
- transitionDuration?: number | null;
57
+ /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */
58
+ throttle?: number;
59
+ /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */
60
+ transitionDuration?: number;
51
61
  /** 变化的回调函数 */
52
62
  onSizeChange?: (sizeData: FlowSizeData) => void;
53
63
  }
54
- export declare function getGapRange(gap?: undefined | number | null | (number | null)[]): [number, number | null];
55
- export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | null): [number, number];
64
+ export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
65
+ export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
56
66
  /** 自适应浮动组件 */
57
67
  export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -1,40 +1,48 @@
1
1
  "use client";
2
2
 
3
+ import { css } from "@emotion/css";
4
+ import { clsx } from "deepsea-tools";
3
5
  import { useEffect, useRef, useState } from "react";
6
+ import { px, styleWithCSSVariable } from "../utils";
4
7
  import { jsx as _jsx } from "react/jsx-runtime";
5
8
  export function getGapRange(gap) {
6
9
  if (typeof gap === "number") return [gap, gap];
7
- if (Array.isArray(gap)) return [gap[0] || 0, gap[1]];
8
- return [0, null];
10
+ if (Array.isArray(gap)) return [typeof gap[0] === "number" ? gap[0] : 0, gap[1]];
11
+ return [0, "auto"];
9
12
  }
10
13
  export function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
11
14
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1;
12
15
  if (count === 1) return [count, 0];
13
16
  const averageGap = (width - itemWidth * count) / (count - 1);
14
17
  if (averageGap < minGap) return [count, minGap];
15
- if (maxGap !== null && averageGap > maxGap) return [count, maxGap];
18
+ if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap];
16
19
  return [count, averageGap];
17
20
  }
18
21
  /** 自适应浮动组件 */
19
22
  export function Flow(props) {
20
- const {
23
+ let {
21
24
  itemWidth,
22
25
  itemHeight,
23
26
  columnGap,
24
- rowGap = 0,
27
+ rowGap,
25
28
  maxRows,
26
29
  data,
27
30
  render,
28
31
  keyExactor,
29
32
  className,
30
33
  style,
31
- containerClassName,
32
- containerStyle,
34
+ wrapperClassName,
35
+ wrapperStyle,
33
36
  throttle,
34
37
  transitionDuration,
35
38
  onSizeChange,
39
+ containerClassName,
40
+ containerStyle,
41
+ gap = 0,
36
42
  ...rest
37
43
  } = props;
44
+ rowGap ??= gap;
45
+ columnGap ??= gap;
38
46
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
39
47
  const [width, setWidth] = useState(0);
40
48
  const [columnCount, setColumnCount] = useState(1);
@@ -70,7 +78,7 @@ export function Flow(props) {
70
78
  setColumnCount(newColumnCount);
71
79
  setColumnGapSize(newColumnGapSize);
72
80
  }
73
- if (throttle === null) {
81
+ if (throttle === 0) {
74
82
  task();
75
83
  } else {
76
84
  timeout = window.setTimeout(task, throttle || 200);
@@ -89,7 +97,7 @@ export function Flow(props) {
89
97
  itemHeight,
90
98
  columnGap: columnGapSize,
91
99
  columnCount,
92
- rowGap,
100
+ rowGap: rowGap,
93
101
  rowCount: contentShownRows,
94
102
  overflow: data.length > contentShownRows * columnCount,
95
103
  itemCount: data.length,
@@ -98,33 +106,46 @@ export function Flow(props) {
98
106
  }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows]);
99
107
  return /*#__PURE__*/_jsx("div", {
100
108
  ref: ele,
101
- className: className,
102
- style: {
103
- position: "relative",
104
- boxSizing: "border-box",
105
- height,
106
- ...style
107
- },
109
+ className: clsx(css`
110
+ position: relative;
111
+ height: var(--height);
112
+ overflow: hidden;
113
+ `, className),
114
+ style: styleWithCSSVariable({
115
+ "--height": px(height)
116
+ }),
108
117
  ...rest,
109
- children: showItems && data.map((item, index) => /*#__PURE__*/_jsx("div", {
110
- className: containerClassName,
111
- style: {
112
- position: "absolute",
113
- width: itemWidth,
114
- height: itemHeight,
115
- transition: transitionDuration !== null ? `all ${transitionDuration ?? 400}ms` : undefined,
116
- ...getPosition(index)
117
- },
118
+ children: showItems && data.map((item, index, arr) => /*#__PURE__*/_jsx("div", {
119
+ className: clsx(css`
120
+ position: absolute;
121
+ width: var(--width);
122
+ height: var(--height);
123
+ transition: var(--transition);
124
+ left: 0;
125
+ top: 0;
126
+ transform: translate(var(--left), var(--top));
127
+ `, wrapperClassName),
128
+ style: styleWithCSSVariable({
129
+ "--width": px(itemWidth),
130
+ "--height": px(itemHeight),
131
+ "--transition": transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
132
+ "--left": px(getPosition(index).left),
133
+ "--top": px(getPosition(index).top),
134
+ ...wrapperStyle
135
+ }),
118
136
  children: /*#__PURE__*/_jsx("div", {
119
- style: {
120
- width: itemWidth,
121
- height: itemHeight,
122
- display: maxRows && index >= maxRows * columnCount ? "none" : "block",
137
+ className: clsx(css`
138
+ width: 100%;
139
+ height: 100%;
140
+ display: var(--display);
141
+ `, containerClassName),
142
+ style: styleWithCSSVariable({
143
+ "--display": getHidden(index) ? "none" : "block",
123
144
  ...containerStyle
124
- },
125
- children: render(item, index, getHidden(index))
145
+ }),
146
+ children: render(item, index, arr)
126
147
  })
127
- }, keyExactor ? keyExactor(item, index) : index))
148
+ }, keyExactor ? keyExactor(item, index, arr) : index))
128
149
  });
129
150
  }
130
151
  //# sourceMappingURL=Flow.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","useState","jsx","_jsx","getGapRange","gap","Array","isArray","getGapCountAndSize","width","itemWidth","minGap","maxGap","count","Math","floor","averageGap","Flow","props","itemHeight","columnGap","rowGap","maxRows","data","render","keyExactor","className","style","containerClassName","containerStyle","throttle","transitionDuration","onSizeChange","rest","minColumnGap","maxColumnGap","setWidth","columnCount","setColumnCount","columnGapSize","setColumnGapSize","showItems","setShowItems","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","timeout","observer","ResizeObserver","entries","clearTimeout","task","contentRect","newColumnCount","newColumnGapSize","window","setTimeout","observe","current","disconnect","rowCount","overflow","itemCount","ref","position","boxSizing","children","map","item","transition","undefined","display"],"sources":["../../../src/components/Flow.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { CSSProperties, HTMLAttributes, ReactNode, useEffect, useRef, useState } from \"react\"\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 columnGap?: number | null | (number | null)[]\r\n /** 行间距 */\r\n rowGap?: number\r\n /** 最大行数 */\r\n maxRows?: number | null\r\n /** 源数据 */\r\n data: T[]\r\n /** 渲染 */\r\n render: (item: T, index: number, hidden: boolean) => ReactNode\r\n /** key释放器,默认为 index */\r\n keyExactor?: (item: T, index: number) => string | number\r\n /** 容器类名 */\r\n containerClassName?: string\r\n /** 容器样式 */\r\n containerStyle?: CSSProperties\r\n /** 节流时间,单位毫秒,默认200ms,传入 null 不节流 */\r\n throttle?: number | null\r\n /** 动画时间,单位毫秒,默认400ms,传入 null 不展示动画 */\r\n transitionDuration?: number | null\r\n /** 变化的回调函数 */\r\n onSizeChange?: (sizeData: FlowSizeData) => void\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | null | (number | null)[]): [number, number | null] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [gap[0] || 0, gap[1]]\r\n return [0, null]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | null): [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 !== null && 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\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n const { itemWidth, itemHeight, columnGap, rowGap = 0, maxRows, data, render, keyExactor, className, style, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, ...rest } = props\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [width, setWidth] = useState(0)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const [showItems, setShowItems] = useState(false)\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 useEffect(() => {\r\n let timeout: number\r\n const observer = new ResizeObserver(entries => {\r\n clearTimeout(timeout)\r\n function task() {\r\n const { width } = entries[0].contentRect\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setShowItems(true)\r\n setWidth(width)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n if (throttle === null) {\r\n task()\r\n } else {\r\n timeout = window.setTimeout(task, throttle || 200)\r\n }\r\n })\r\n observer.observe(ele.current!)\r\n\r\n return () => {\r\n observer.disconnect()\r\n }\r\n }, [itemWidth, throttle, columnGap])\r\n\r\n useEffect(() => {\r\n onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, 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 ref={ele} className={className} style={{ position: \"relative\", boxSizing: \"border-box\", height, ...style }} {...rest}>\r\n {showItems &&\r\n data.map((item, index) => (\r\n <div\r\n key={keyExactor ? keyExactor(item, index) : index}\r\n className={containerClassName}\r\n style={{\r\n position: \"absolute\",\r\n width: itemWidth,\r\n height: itemHeight,\r\n transition: transitionDuration !== null ? `all ${transitionDuration ?? 400}ms` : undefined,\r\n ...getPosition(index)\r\n }}>\r\n <div style={{ width: itemWidth, height: itemHeight, display: maxRows && index >= maxRows * columnCount ? \"none\" : \"block\", ...containerStyle }}>{render(item, index, getHidden(index))}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"names":["css","clsx","useEffect","useRef","useState","px","styleWithCSSVariable","jsx","_jsx","getGapRange","gap","Array","isArray","getGapCountAndSize","width","itemWidth","minGap","maxGap","count","Math","floor","averageGap","Flow","props","itemHeight","columnGap","rowGap","maxRows","data","render","keyExactor","className","style","wrapperClassName","wrapperStyle","throttle","transitionDuration","onSizeChange","containerClassName","containerStyle","rest","minColumnGap","maxColumnGap","setWidth","columnCount","setColumnCount","columnGapSize","setColumnGapSize","showItems","setShowItems","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","timeout","observer","ResizeObserver","entries","clearTimeout","task","contentRect","newColumnCount","newColumnGapSize","window","setTimeout","observe","current","disconnect","rowCount","overflow","itemCount","ref","children","map","item","arr"],"sources":["../../../src/components/Flow.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, useEffect, useRef, useState } from \"react\"\r\nimport { px, styleWithCSSVariable } 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 wrapperClassName?: string\r\n /** 容器样式 */\r\n wrapperStyle?: CSSProperties\r\n /** 容器类名 */\r\n containerClassName?: string\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}\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\n/** 自适应浮动组件 */\r\nexport function Flow<T>(props: FlowProps<T>) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [width, setWidth] = useState(0)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n const [showItems, setShowItems] = useState(false)\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 useEffect(() => {\r\n let timeout: number\r\n const observer = new ResizeObserver(entries => {\r\n clearTimeout(timeout)\r\n function task() {\r\n const { width } = entries[0].contentRect\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setShowItems(true)\r\n setWidth(width)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n if (throttle === 0) {\r\n task()\r\n } else {\r\n timeout = window.setTimeout(task, throttle || 200)\r\n }\r\n })\r\n observer.observe(ele.current!)\r\n\r\n return () => {\r\n observer.disconnect()\r\n }\r\n }, [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={styleWithCSSVariable({ \"--height\": px(height) })}\r\n {...rest}>\r\n {showItems &&\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={styleWithCSSVariable({\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 ...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={styleWithCSSVariable({ \"--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"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,GAAG,QAAQ,cAAc;AAClC,SAASC,IAAI,QAAQ,eAAe;AACpC,SAAwDC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAClG,SAASC,EAAE,EAAEC,oBAAoB;AAAkB,SAAAC,GAAA,IAAAC,IAAA;AAkEnD,OAAO,SAASC,WAAWA,CAACC,GAAuD,EAA6B;EAC5G,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE,OAAO,CAACA,GAAG,EAAEA,GAAG,CAAC;EAC9C,IAAIC,KAAK,CAACC,OAAO,CAACF,GAAG,CAAC,EAAE,OAAO,CAAC,OAAOA,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAGA,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAEA,GAAG,CAAC,CAAC,CAAC,CAAC;EAChF,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC;AACtB;AAEA,OAAO,SAASG,kBAAkBA,CAACC,KAAa,EAAEC,SAAiB,EAAEC,MAAc,EAAEC,MAAuB,EAAoB;EAC5H,MAAMC,KAAK,GAAGC,IAAI,CAACC,KAAK,CAAC,CAACN,KAAK,GAAGE,MAAM,KAAKD,SAAS,GAAGC,MAAM,CAAC,CAAC,IAAI,CAAC;EACtE,IAAIE,KAAK,KAAK,CAAC,EAAE,OAAO,CAACA,KAAK,EAAE,CAAC,CAAC;EAClC,MAAMG,UAAU,GAAG,CAACP,KAAK,GAAGC,SAAS,GAAGG,KAAK,KAAKA,KAAK,GAAG,CAAC,CAAC;EAC5D,IAAIG,UAAU,GAAGL,MAAM,EAAE,OAAO,CAACE,KAAK,EAAEF,MAAM,CAAC;EAC/C,IAAIC,MAAM,KAAK,MAAM,IAAII,UAAU,GAAGJ,MAAM,EAAE,OAAO,CAACC,KAAK,EAAED,MAAM,CAAC;EACpE,OAAO,CAACC,KAAK,EAAEG,UAAU,CAAC;AAC9B;AAOA;AACA,OAAO,SAASC,IAAIA,CAAIC,KAAmB,EAAE;EACzC,IAAI;IAAER,SAAS;IAAES,UAAU;IAAEC,SAAS;IAAEC,MAAM;IAAEC,OAAO;IAAEC,IAAI;IAAEC,MAAM;IAAEC,UAAU;IAAEC,SAAS;IAAEC,KAAK;IAAEC,gBAAgB;IAAEC,YAAY;IAAEC,QAAQ;IAAEC,kBAAkB;IAAEC,YAAY;IAAEC,kBAAkB;IAAEC,cAAc;IAAE7B,GAAG,GAAG,CAAC;IAAE,GAAG8B;EAAK,CAAC,GAAGjB,KAAK;EAC/OG,MAAM,KAAKhB,GAAG;EACde,SAAS,KAAKf,GAAG;EACjB,MAAM,CAAC+B,YAAY,EAAEC,YAAY,CAAC,GAAGjC,WAAW,CAACgB,SAAS,CAAC;EAC3D,MAAM,CAACX,KAAK,EAAE6B,QAAQ,CAAC,GAAGvC,QAAQ,CAAC,CAAC,CAAC;EACrC,MAAM,CAACwC,WAAW,EAAEC,cAAc,CAAC,GAAGzC,QAAQ,CAAC,CAAC,CAAC;EACjD,MAAM,CAAC0C,aAAa,EAAEC,gBAAgB,CAAC,GAAG3C,QAAQ,CAACqC,YAAY,CAAC;EAChE,MAAM,CAACO,SAAS,EAAEC,YAAY,CAAC,GAAG7C,QAAQ,CAAC,KAAK,CAAC;EACjD,MAAM8C,GAAG,GAAG/C,MAAM,CAAiB,IAAI,CAAC;EACxC,MAAMgD,WAAW,GAAGhC,IAAI,CAACiC,IAAI,CAACxB,IAAI,CAACyB,MAAM,GAAGT,WAAW,CAAC;EACxD,MAAMU,gBAAgB,GAAG,OAAO3B,OAAO,KAAK,QAAQ,GAAGR,IAAI,CAACoC,GAAG,CAACJ,WAAW,EAAExB,OAAO,CAAC,GAAGwB,WAAW;EACnG,MAAMK,MAAM,GAAGF,gBAAgB,GAAG,CAAC,GAAGA,gBAAgB,IAAI9B,UAAU,GAAGE,MAAM,CAAC,GAAGA,MAAM,GAAG,CAAC;EAE3F,SAAS+B,WAAWA,CAACC,KAAa,EAAY;IAC1C,MAAMC,CAAC,GAAGxC,IAAI,CAACC,KAAK,CAACsC,KAAK,GAAGd,WAAW,CAAC;IACzC,MAAMgB,CAAC,GAAGF,KAAK,GAAGC,CAAC,GAAGf,WAAW;IACjC,OAAO;MACHiB,IAAI,EAAED,CAAC,IAAI7C,SAAS,GAAG+B,aAAa,CAAC;MACrCgB,GAAG,EAAEH,CAAC,IAAInC,UAAU,GAAGE,MAAO;IAClC,CAAC;EACL;EAEA,SAASqC,SAASA,CAACL,KAAa,EAAE;IAC9B,IAAI,OAAO/B,OAAO,KAAK,QAAQ,EAAE,OAAO,KAAK;IAC7C,OAAO+B,KAAK,IAAI/B,OAAO,GAAGiB,WAAW;EACzC;EAEA1C,SAAS,CAAC,MAAM;IACZ,IAAI8D,OAAe;IACnB,MAAMC,QAAQ,GAAG,IAAIC,cAAc,CAACC,OAAO,IAAI;MAC3CC,YAAY,CAACJ,OAAO,CAAC;MACrB,SAASK,IAAIA,CAAA,EAAG;QACZ,MAAM;UAAEvD;QAAM,CAAC,GAAGqD,OAAO,CAAC,CAAC,CAAC,CAACG,WAAW;QACxC,MAAM,CAACC,cAAc,EAAEC,gBAAgB,CAAC,GAAG3D,kBAAkB,CAACC,KAAK,EAAEC,SAAS,EAAE0B,YAAY,EAAEC,YAAY,CAAC;QAC3GO,YAAY,CAAC,IAAI,CAAC;QAClBN,QAAQ,CAAC7B,KAAK,CAAC;QACf+B,cAAc,CAAC0B,cAAc,CAAC;QAC9BxB,gBAAgB,CAACyB,gBAAgB,CAAC;MACtC;MACA,IAAIrC,QAAQ,KAAK,CAAC,EAAE;QAChBkC,IAAI,CAAC,CAAC;MACV,CAAC,MAAM;QACHL,OAAO,GAAGS,MAAM,CAACC,UAAU,CAACL,IAAI,EAAElC,QAAQ,IAAI,GAAG,CAAC;MACtD;IACJ,CAAC,CAAC;IACF8B,QAAQ,CAACU,OAAO,CAACzB,GAAG,CAAC0B,OAAQ,CAAC;IAE9B,OAAO,MAAM;MACTX,QAAQ,CAACY,UAAU,CAAC,CAAC;IACzB,CAAC;EACL,CAAC,EAAE,CAAC9D,SAAS,EAAEoB,QAAQ,EAAEV,SAAS,CAAC,CAAC;EAEpCvB,SAAS,CAAC,MAAM;IACZmC,YAAY,GAAG;MAAEvB,KAAK;MAAE0C,MAAM;MAAEzC,SAAS;MAAES,UAAU;MAAEC,SAAS,EAAEqB,aAAa;MAAEF,WAAW;MAAElB,MAAM,EAAEA,MAAO;MAAEoD,QAAQ,EAAExB,gBAAgB;MAAEyB,QAAQ,EAAEnD,IAAI,CAACyB,MAAM,GAAGC,gBAAgB,GAAGV,WAAW;MAAEoC,SAAS,EAAEpD,IAAI,CAACyB,MAAM;MAAE1B,OAAO,EAAEA,OAAO,IAAI;IAAK,CAAC,CAAC;EAC1P,CAAC,EAAE,CAACb,KAAK,EAAE0C,MAAM,EAAEV,aAAa,EAAEF,WAAW,EAAElB,MAAM,EAAE4B,gBAAgB,EAAE1B,IAAI,CAACyB,MAAM,EAAEtC,SAAS,EAAES,UAAU,EAAEG,OAAO,CAAC,CAAC;EAEtH,oBACInB,IAAA;IACIyE,GAAG,EAAE/B,GAAI;IACTnB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AACpB;AACA;AACA;AACA,iBAAiB,EACD+B,SACJ,CAAE;IACFC,KAAK,EAAE1B,oBAAoB,CAAC;MAAE,UAAU,EAAED,EAAE,CAACmD,MAAM;IAAE,CAAC,CAAE;IAAA,GACpDhB,IAAI;IAAA0C,QAAA,EACPlC,SAAS,IACNpB,IAAI,CAACuD,GAAG,CAAC,CAACC,IAAI,EAAE1B,KAAK,EAAE2B,GAAG,kBACtB7E,IAAA;MAEIuB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,EACDiC,gBACJ,CAAE;MACFD,KAAK,EAAE1B,oBAAoB,CAAC;QACxB,SAAS,EAAED,EAAE,CAACU,SAAS,CAAC;QACxB,UAAU,EAAEV,EAAE,CAACmB,UAAU,CAAC;QAC1B,cAAc,EAAEY,kBAAkB,KAAK,CAAC,GAAG,MAAM,GAAI,OAAMA,kBAAkB,IAAI,GAAI,IAAG;QACxF,QAAQ,EAAE/B,EAAE,CAACoD,WAAW,CAACC,KAAK,CAAC,CAACG,IAAI,CAAC;QACrC,OAAO,EAAExD,EAAE,CAACoD,WAAW,CAACC,KAAK,CAAC,CAACI,GAAG,CAAC;QACnC,GAAG5B;MACP,CAAC,CAAE;MAAAgD,QAAA,eACH1E,IAAA;QACIuB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AACpC;AACA;AACA;AACA,iCAAiC,EACDsC,kBACJ,CAAE;QACFN,KAAK,EAAE1B,oBAAoB,CAAC;UAAE,WAAW,EAAEyD,SAAS,CAACL,KAAK,CAAC,GAAG,MAAM,GAAG,OAAO;UAAE,GAAGnB;QAAe,CAAC,CAAE;QAAA2C,QAAA,EACpGrD,MAAM,CAACuD,IAAI,EAAE1B,KAAK,EAAE2B,GAAG;MAAC,CACxB;IAAC,GAhCDvD,UAAU,GAAGA,UAAU,CAACsD,IAAI,EAAE1B,KAAK,EAAE2B,GAAG,CAAC,GAAG3B,KAiChD,CACR;EAAC,CACL,CAAC;AAEd"}
@@ -0,0 +1,8 @@
1
+ import { CSSProperties } from "react";
2
+ export type CSSVariableName = `--${string}`;
3
+ export type CSSVariableValue = string | number;
4
+ export interface StyleWithCSSVariable extends CSSProperties {
5
+ [X: CSSVariableName]: CSSVariableValue;
6
+ }
7
+ export declare function styleWithCSSVariable(style: StyleWithCSSVariable): CSSProperties;
8
+ export declare function px(value: number): string;
@@ -0,0 +1,7 @@
1
+ export function styleWithCSSVariable(style) {
2
+ return style;
3
+ }
4
+ export function px(value) {
5
+ return `${value}px`;
6
+ }
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["styleWithCSSVariable","style","px","value"],"sources":["../../../src/utils/index.ts"],"sourcesContent":["import { CSSProperties } from \"react\"\r\n\r\nexport type CSSVariableName = `--${string}`\r\n\r\nexport type CSSVariableValue = string | number\r\n\r\nexport interface StyleWithCSSVariable extends CSSProperties {\r\n [X: CSSVariableName]: CSSVariableValue\r\n}\r\n\r\nexport function styleWithCSSVariable(style: StyleWithCSSVariable): CSSProperties {\r\n return style\r\n}\r\n\r\nexport function px(value: number): string {\r\n return `${value}px`\r\n}"],"mappings":"AAUA,OAAO,SAASA,oBAAoBA,CAACC,KAA2B,EAAiB;EAC7E,OAAOA,KAAK;AAChB;AAEA,OAAO,SAASC,EAAEA,CAACC,KAAa,EAAU;EACtC,OAAQ,GAAEA,KAAM,IAAG;AACvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepsea-components",
3
- "version": "3.0.1",
3
+ "version": "3.0.2-beta.20240527151438",
4
4
  "description": "格数科技自用组件库",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -39,9 +39,10 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.3.1",
42
- "father": "^4.4.1"
42
+ "father": "^4.4.1",
43
+ "typescript": "^5.4.5"
43
44
  },
44
45
  "peerDependencies": {
45
- "react": ">=16.8.0"
46
+ "react": "^18.3.1"
46
47
  }
47
48
  }
@@ -1,6 +1,9 @@
1
1
  "use client"
2
2
 
3
- import { CSSProperties, HTMLAttributes, ReactNode, useEffect, useRef, useState } from "react"
3
+ import { css } from "@emotion/css"
4
+ import { clsx } from "deepsea-tools"
5
+ import { CSSProperties, HTMLAttributes, Key, ReactNode, useEffect, useRef, useState } from "react"
6
+ import { px, styleWithCSSVariable } from "../utils"
4
7
 
5
8
  export interface FlowSizeData {
6
9
  /** 容器宽度 */
@@ -32,42 +35,52 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
32
35
  itemWidth: number
33
36
  /** 元素高度 */
34
37
  itemHeight: number
35
- /** 列间距 */
36
- columnGap?: number | null | (number | null)[]
38
+ /**
39
+ * 列间距
40
+ * 1. 如果是数字,表示列间距是固定的
41
+ * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的
42
+ * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值
43
+ */
44
+ columnGap?: number | "auto" | [number | "auto", number | "auto"]
37
45
  /** 行间距 */
38
46
  rowGap?: number
47
+ gap?: number
39
48
  /** 最大行数 */
40
49
  maxRows?: number | null
41
50
  /** 源数据 */
42
51
  data: T[]
43
52
  /** 渲染 */
44
- render: (item: T, index: number, hidden: boolean) => ReactNode
53
+ render: (item: T, index: number, arr: T[]) => ReactNode
45
54
  /** key释放器,默认为 index */
46
- keyExactor?: (item: T, index: number) => string | number
55
+ keyExactor?: (item: T, index: number, arr: T[]) => Key
56
+ /** 容器类名 */
57
+ wrapperClassName?: string
58
+ /** 容器样式 */
59
+ wrapperStyle?: CSSProperties
47
60
  /** 容器类名 */
48
61
  containerClassName?: string
49
62
  /** 容器样式 */
50
63
  containerStyle?: CSSProperties
51
- /** 节流时间,单位毫秒,默认200ms,传入 null 不节流 */
52
- throttle?: number | null
53
- /** 动画时间,单位毫秒,默认400ms,传入 null 不展示动画 */
54
- transitionDuration?: number | null
64
+ /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */
65
+ throttle?: number
66
+ /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */
67
+ transitionDuration?: number
55
68
  /** 变化的回调函数 */
56
69
  onSizeChange?: (sizeData: FlowSizeData) => void
57
70
  }
58
71
 
59
- export function getGapRange(gap?: undefined | number | null | (number | null)[]): [number, number | null] {
72
+ export function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"] {
60
73
  if (typeof gap === "number") return [gap, gap]
61
- if (Array.isArray(gap)) return [gap[0] || 0, gap[1]]
62
- return [0, null]
74
+ if (Array.isArray(gap)) return [typeof gap[0] === "number" ? gap[0] : 0, gap[1]]
75
+ return [0, "auto"]
63
76
  }
64
77
 
65
- export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | null): [number, number] {
78
+ export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number] {
66
79
  const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1
67
80
  if (count === 1) return [count, 0]
68
81
  const averageGap = (width - itemWidth * count) / (count - 1)
69
82
  if (averageGap < minGap) return [count, minGap]
70
- if (maxGap !== null && averageGap > maxGap) return [count, maxGap]
83
+ if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap]
71
84
  return [count, averageGap]
72
85
  }
73
86
 
@@ -78,7 +91,9 @@ interface Position {
78
91
 
79
92
  /** 自适应浮动组件 */
80
93
  export function Flow<T>(props: FlowProps<T>) {
81
- const { itemWidth, itemHeight, columnGap, rowGap = 0, maxRows, data, render, keyExactor, className, style, containerClassName, containerStyle, throttle, transitionDuration, onSizeChange, ...rest } = props
94
+ let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props
95
+ rowGap ??= gap
96
+ columnGap ??= gap
82
97
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
83
98
  const [width, setWidth] = useState(0)
84
99
  const [columnCount, setColumnCount] = useState(1)
@@ -94,7 +109,7 @@ export function Flow<T>(props: FlowProps<T>) {
94
109
  const x = index - y * columnCount
95
110
  return {
96
111
  left: x * (itemWidth + columnGapSize),
97
- top: y * (itemHeight + rowGap)
112
+ top: y * (itemHeight + rowGap!)
98
113
  }
99
114
  }
100
115
 
@@ -115,7 +130,7 @@ export function Flow<T>(props: FlowProps<T>) {
115
130
  setColumnCount(newColumnCount)
116
131
  setColumnGapSize(newColumnGapSize)
117
132
  }
118
- if (throttle === null) {
133
+ if (throttle === 0) {
119
134
  task()
120
135
  } else {
121
136
  timeout = window.setTimeout(task, throttle || 200)
@@ -129,24 +144,58 @@ export function Flow<T>(props: FlowProps<T>) {
129
144
  }, [itemWidth, throttle, columnGap])
130
145
 
131
146
  useEffect(() => {
132
- onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })
147
+ onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })
133
148
  }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])
134
149
 
135
150
  return (
136
- <div ref={ele} className={className} style={{ position: "relative", boxSizing: "border-box", height, ...style }} {...rest}>
151
+ <div
152
+ ref={ele}
153
+ className={clsx(
154
+ css`
155
+ position: relative;
156
+ height: var(--height);
157
+ overflow: hidden;
158
+ `,
159
+ className
160
+ )}
161
+ style={styleWithCSSVariable({ "--height": px(height) })}
162
+ {...rest}>
137
163
  {showItems &&
138
- data.map((item, index) => (
164
+ data.map((item, index, arr) => (
139
165
  <div
140
- key={keyExactor ? keyExactor(item, index) : index}
141
- className={containerClassName}
142
- style={{
143
- position: "absolute",
144
- width: itemWidth,
145
- height: itemHeight,
146
- transition: transitionDuration !== null ? `all ${transitionDuration ?? 400}ms` : undefined,
147
- ...getPosition(index)
148
- }}>
149
- <div style={{ width: itemWidth, height: itemHeight, display: maxRows && index >= maxRows * columnCount ? "none" : "block", ...containerStyle }}>{render(item, index, getHidden(index))}</div>
166
+ key={keyExactor ? keyExactor(item, index, arr) : index}
167
+ className={clsx(
168
+ css`
169
+ position: absolute;
170
+ width: var(--width);
171
+ height: var(--height);
172
+ transition: var(--transition);
173
+ left: 0;
174
+ top: 0;
175
+ transform: translate(var(--left), var(--top));
176
+ `,
177
+ wrapperClassName
178
+ )}
179
+ style={styleWithCSSVariable({
180
+ "--width": px(itemWidth),
181
+ "--height": px(itemHeight),
182
+ "--transition": transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
183
+ "--left": px(getPosition(index).left),
184
+ "--top": px(getPosition(index).top),
185
+ ...wrapperStyle
186
+ })}>
187
+ <div
188
+ className={clsx(
189
+ css`
190
+ width: 100%;
191
+ height: 100%;
192
+ display: var(--display);
193
+ `,
194
+ containerClassName
195
+ )}
196
+ style={styleWithCSSVariable({ "--display": getHidden(index) ? "none" : "block", ...containerStyle })}>
197
+ {render(item, index, arr)}
198
+ </div>
150
199
  </div>
151
200
  ))}
152
201
  </div>
@@ -0,0 +1,17 @@
1
+ import { CSSProperties } from "react"
2
+
3
+ export type CSSVariableName = `--${string}`
4
+
5
+ export type CSSVariableValue = string | number
6
+
7
+ export interface StyleWithCSSVariable extends CSSProperties {
8
+ [X: CSSVariableName]: CSSVariableValue
9
+ }
10
+
11
+ export function styleWithCSSVariable(style: StyleWithCSSVariable): CSSProperties {
12
+ return style
13
+ }
14
+
15
+ export function px(value: number): string {
16
+ return `${value}px`
17
+ }