deepsea-components 3.1.0 → 3.2.0-beta.20240606182955

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.
@@ -68,8 +68,10 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
68
68
  transitionDuration?: number;
69
69
  /** 变化的回调函数 */
70
70
  onSizeChange?: (sizeData: FlowSizeData) => void;
71
+ /** 宽度 */
72
+ width?: number;
71
73
  }
72
74
  export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
73
75
  export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
74
76
  /** 自适应浮动组件 */
75
- export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
77
+ export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element | null;
@@ -47,15 +47,13 @@ function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
47
47
  return [count, maxGap];
48
48
  return [count, averageGap];
49
49
  }
50
- function Flow(props) {
51
- let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props;
50
+ function RealFlow(props) {
51
+ let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, ...rest } = props;
52
52
  rowGap ??= gap;
53
53
  columnGap ??= gap;
54
54
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
55
- const [width, setWidth] = (0, import_react.useState)(0);
56
55
  const [columnCount, setColumnCount] = (0, import_react.useState)(1);
57
56
  const [columnGapSize, setColumnGapSize] = (0, import_react.useState)(minColumnGap);
58
- const [showItems, setShowItems] = (0, import_react.useState)(false);
59
57
  const ele = (0, import_react.useRef)(null);
60
58
  const contentRows = Math.ceil(data.length / columnCount);
61
59
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows;
@@ -73,29 +71,20 @@ function Flow(props) {
73
71
  return false;
74
72
  return index >= maxRows * columnCount;
75
73
  }
74
+ function task() {
75
+ const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap);
76
+ setColumnCount(newColumnCount);
77
+ setColumnGapSize(newColumnGapSize);
78
+ }
76
79
  (0, import_react.useEffect)(() => {
77
- let timeout;
78
- const observer = new ResizeObserver((entries) => {
79
- clearTimeout(timeout);
80
- function task() {
81
- const { width: width2 } = entries[0].contentRect;
82
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width2, itemWidth, minColumnGap, maxColumnGap);
83
- setShowItems(true);
84
- setWidth(width2);
85
- setColumnCount(newColumnCount);
86
- setColumnGapSize(newColumnGapSize);
87
- }
88
- if (throttle === 0) {
89
- task();
90
- } else {
91
- timeout = window.setTimeout(task, throttle || 200);
92
- }
93
- });
94
- observer.observe(ele.current);
95
- return () => {
96
- observer.disconnect();
97
- };
98
- }, [itemWidth, throttle, columnGap]);
80
+ task();
81
+ }, []);
82
+ (0, import_react.useEffect)(() => {
83
+ if (throttle === 0)
84
+ return task();
85
+ const timeout = setTimeout(task, throttle || 200);
86
+ return () => clearTimeout(timeout);
87
+ }, [width, itemWidth, throttle, columnGap]);
99
88
  (0, import_react.useEffect)(() => {
100
89
  onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null });
101
90
  }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows]);
@@ -114,20 +103,20 @@ function Flow(props) {
114
103
  style: (0, import_utils.transformCSSVariable)({ height: (0, import_utils.px)(height) }, style),
115
104
  ...rest
116
105
  },
117
- showItems && data.map((item, index, arr) => /* @__PURE__ */ React.createElement(
106
+ data.map((item, index, arr) => /* @__PURE__ */ React.createElement(
118
107
  "div",
119
108
  {
120
109
  key: keyExactor ? keyExactor(item, index, arr) : index,
121
110
  className: (0, import_deepsea_tools.clsx)(
122
111
  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
- `,
112
+ position: absolute;
113
+ width: var(--width);
114
+ height: var(--height);
115
+ transition: var(--transition);
116
+ left: 0;
117
+ top: 0;
118
+ transform: translate(var(--left), var(--top));
119
+ `,
131
120
  wrapperClassName
132
121
  ),
133
122
  style: (0, import_utils.transformCSSVariable)(
@@ -146,10 +135,10 @@ function Flow(props) {
146
135
  {
147
136
  className: (0, import_deepsea_tools.clsx)(
148
137
  import_css.css`
149
- width: 100%;
150
- height: 100%;
151
- display: var(--display);
152
- `,
138
+ width: 100%;
139
+ height: 100%;
140
+ display: var(--display);
141
+ `,
153
142
  containerClassName
154
143
  ),
155
144
  style: (0, import_utils.transformCSSVariable)({ display: getHidden(index) ? "none" : "block" }, containerStyle)
@@ -159,6 +148,12 @@ function Flow(props) {
159
148
  ))
160
149
  );
161
150
  }
151
+ function Flow(props) {
152
+ const { width, data } = props;
153
+ if (!width || data.length === 0)
154
+ return null;
155
+ return /* @__PURE__ */ React.createElement(RealFlow, { ...props, width });
156
+ }
162
157
  // Annotate the CommonJS export names for ESM import in node:
163
158
  0 && (module.exports = {
164
159
  Flow,
@@ -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 { clsx } from \"deepsea-tools\"\r\nimport { CSSProperties, HTMLAttributes, Key, ReactNode, useEffect, 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}\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={transformCSSVariable({ height: px(height) }, style)}\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={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"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAoB;AACpB,2BAAqB;AACrB,mBAA2F;AAC3F,mBAAyC;AA0ElC,SAAS,YAAY,KAAoF;AAC5G,MAAI,OAAO,QAAQ;AAAU,WAAO,CAAC,KAAK,GAAG;AAC7C,MAAI,MAAM,QAAQ,GAAG;AAAG,WAAO,CAAC,OAAO,IAAI,CAAC,MAAM,WAAW,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;AAC/E,SAAO,CAAC,GAAG,MAAM;AACrB;AAEO,SAAS,mBAAmB,OAAe,WAAmB,QAAgB,QAA2C;AAC5H,QAAM,QAAQ,KAAK,OAAO,QAAQ,WAAW,YAAY,OAAO,KAAK;AACrE,MAAI,UAAU;AAAG,WAAO,CAAC,OAAO,CAAC;AACjC,QAAM,cAAc,QAAQ,YAAY,UAAU,QAAQ;AAC1D,MAAI,aAAa;AAAQ,WAAO,CAAC,OAAO,MAAM;AAC9C,MAAI,WAAW,UAAU,aAAa;AAAQ,WAAO,CAAC,OAAO,MAAM;AACnE,SAAO,CAAC,OAAO,UAAU;AAC7B;AAQO,SAAS,KAAQ,OAAqB;AACzC,MAAI,EAAE,WAAW,YAAY,WAAW,QAAQ,SAAS,MAAM,QAAQ,YAAY,WAAW,OAAO,kBAAkB,cAAc,UAAU,oBAAoB,cAAc,oBAAoB,gBAAgB,MAAM,GAAG,GAAG,KAAK,IAAI;AAC1O,aAAW;AACX,gBAAc;AACd,QAAM,CAAC,cAAc,YAAY,IAAI,YAAY,SAAS;AAC1D,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAS,CAAC;AACpC,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAS,CAAC;AAChD,QAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAS,YAAY;AAC/D,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,KAAK;AAChD,QAAM,UAAM,qBAAuB,IAAI;AACvC,QAAM,cAAc,KAAK,KAAK,KAAK,SAAS,WAAW;AACvD,QAAM,mBAAmB,OAAO,YAAY,WAAW,KAAK,IAAI,aAAa,OAAO,IAAI;AACxF,QAAM,SAAS,mBAAmB,IAAI,oBAAoB,aAAa,UAAU,SAAS;AAE1F,WAAS,YAAY,OAAyB;AAC1C,UAAM,IAAI,KAAK,MAAM,QAAQ,WAAW;AACxC,UAAM,IAAI,QAAQ,IAAI;AACtB,WAAO;AAAA,MACH,MAAM,KAAK,YAAY;AAAA,MACvB,KAAK,KAAK,aAAa;AAAA,IAC3B;AAAA,EACJ;AAEA,WAAS,UAAU,OAAe;AAC9B,QAAI,OAAO,YAAY;AAAU,aAAO;AACxC,WAAO,SAAS,UAAU;AAAA,EAC9B;AAEA,8BAAU,MAAM;AACZ,QAAI;AACJ,UAAM,WAAW,IAAI,eAAe,aAAW;AAC3C,mBAAa,OAAO;AACpB,eAAS,OAAO;AACZ,cAAM,EAAE,OAAAA,OAAM,IAAI,QAAQ,CAAC,EAAE;AAC7B,cAAM,CAAC,gBAAgB,gBAAgB,IAAI,mBAAmBA,QAAO,WAAW,cAAc,YAAY;AAC1G,qBAAa,IAAI;AACjB,iBAASA,MAAK;AACd,uBAAe,cAAc;AAC7B,yBAAiB,gBAAgB;AAAA,MACrC;AACA,UAAI,aAAa,GAAG;AAChB,aAAK;AAAA,MACT,OAAO;AACH,kBAAU,OAAO,WAAW,MAAM,YAAY,GAAG;AAAA,MACrD;AAAA,IACJ,CAAC;AACD,aAAS,QAAQ,IAAI,OAAQ;AAE7B,WAAO,MAAM;AACT,eAAS,WAAW;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,WAAW,UAAU,SAAS,CAAC;AAEnC,8BAAU,MAAM;AACZ,mBAAe,EAAE,OAAO,QAAQ,WAAW,YAAY,WAAW,eAAe,aAAa,QAAiB,UAAU,kBAAkB,UAAU,KAAK,SAAS,mBAAmB,aAAa,WAAW,KAAK,QAAQ,SAAS,WAAW,KAAK,CAAC;AAAA,EACzP,GAAG,CAAC,OAAO,QAAQ,eAAe,aAAa,QAAQ,kBAAkB,KAAK,QAAQ,WAAW,YAAY,OAAO,CAAC;AAErH,SACI;AAAA,IAAC;AAAA;AAAA,MACG,KAAK;AAAA,MACL,eAAW;AAAA,QACP;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA;AAAA,MACJ;AAAA,MACA,WAAO,mCAAqB,EAAE,YAAQ,iBAAG,MAAM,EAAE,GAAG,KAAK;AAAA,MACxD,GAAG;AAAA;AAAA,IACH,aACG,KAAK,IAAI,CAAC,MAAM,OAAO,QACnB;AAAA,MAAC;AAAA;AAAA,QACG,KAAK,aAAa,WAAW,MAAM,OAAO,GAAG,IAAI;AAAA,QACjD,eAAW;AAAA,UACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UASA;AAAA,QACJ;AAAA,QACA,WAAO;AAAA,UACH;AAAA,YACI,WAAO,iBAAG,SAAS;AAAA,YACnB,YAAQ,iBAAG,UAAU;AAAA,YACrB,YAAY,uBAAuB,IAAI,SAAS,OAAO,sBAAsB;AAAA,YAC7E,UAAM,iBAAG,YAAY,KAAK,EAAE,IAAI;AAAA,YAChC,SAAK,iBAAG,YAAY,KAAK,EAAE,GAAG;AAAA,UAClC;AAAA,UACA;AAAA,QACJ;AAAA;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACG,eAAW;AAAA,YACP;AAAA;AAAA;AAAA;AAAA;AAAA,YAKA;AAAA,UACJ;AAAA,UACA,WAAO,mCAAqB,EAAE,SAAS,UAAU,KAAK,IAAI,SAAS,QAAQ,GAAG,cAAc;AAAA;AAAA,QAC3F,OAAO,MAAM,OAAO,GAAG;AAAA,MAC5B;AAAA,IACJ,CACH;AAAA,EACT;AAER;",
6
- "names": ["width"]
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, 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 /** 宽度 */\r\n width?: number\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | \"auto\" | (number | \"auto\")[]): [number, number | \"auto\"] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [typeof gap[0] === \"number\" ? gap[0] : 0, gap[1]]\r\n return [0, \"auto\"]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): [number, number] {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return [count, 0]\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return [count, minGap]\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return [count, maxGap]\r\n return [count, averageGap]\r\n}\r\n\r\ninterface Position {\r\n left: number\r\n top: number\r\n}\r\n\r\nfunction RealFlow<T>(props: FlowProps<T> & { width: number }) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n\r\n const ele = useRef<HTMLDivElement>(null)\r\n const contentRows = Math.ceil(data.length / columnCount)\r\n const contentShownRows = typeof maxRows === \"number\" ? Math.min(contentRows, maxRows) : contentRows\r\n const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0\r\n\r\n function getPosition(index: number): Position {\r\n const y = Math.floor(index / columnCount)\r\n const x = index - y * columnCount\r\n return {\r\n left: x * (itemWidth + columnGapSize),\r\n top: y * (itemHeight + rowGap!)\r\n }\r\n }\r\n\r\n function getHidden(index: number) {\r\n if (typeof maxRows !== \"number\") return false\r\n return index >= maxRows * columnCount\r\n }\r\n\r\n function task() {\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n\r\n 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 { width, data } = props\r\n if (!width || data.length === 0) return null\r\n return <RealFlow {...props} width={width} />\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
7
  }
@@ -2,5 +2,4 @@ import { MediaHTMLAttributes } from "react";
2
2
  export interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, "src"> {
3
3
  src: string;
4
4
  }
5
- declare const HlsPlayer: import("react").ForwardRefExoticComponent<HlsPlayerProps & import("react").RefAttributes<HTMLVideoElement>>;
6
- export default HlsPlayer;
5
+ export declare const HlsPlayer: import("react").ForwardRefExoticComponent<HlsPlayerProps & import("react").RefAttributes<HTMLVideoElement>>;
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/components/HlsPlayer.tsx
31
31
  var HlsPlayer_exports = {};
32
32
  __export(HlsPlayer_exports, {
33
- default: () => HlsPlayer_default
33
+ HlsPlayer: () => HlsPlayer
34
34
  });
35
35
  module.exports = __toCommonJS(HlsPlayer_exports);
36
36
  var import_hls = __toESM(require("hls.js"));
@@ -58,5 +58,8 @@ var HlsPlayer = (0, import_react.forwardRef)((props, ref) => {
58
58
  }, [src]);
59
59
  return /* @__PURE__ */ React.createElement("video", { ref: video, ...rest });
60
60
  });
61
- var HlsPlayer_default = HlsPlayer;
61
+ // Annotate the CommonJS export names for ESM import in node:
62
+ 0 && (module.exports = {
63
+ HlsPlayer
64
+ });
62
65
  //# sourceMappingURL=HlsPlayer.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/HlsPlayer.tsx"],
4
- "sourcesContent": ["\"use client\"\r\n\r\nimport Hls from \"hls.js\"\r\nimport { MediaHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from \"react\"\r\n\r\nexport interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, \"src\"> {\r\n src: string\r\n}\r\n\r\nconst HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {\r\n const { src, ...rest } = props\r\n const video = useRef<HTMLVideoElement>(null)\r\n\r\n useImperativeHandle(ref, () => video.current!, [])\r\n\r\n useEffect(() => {\r\n const { current: player } = video\r\n if (!player || !src) return\r\n if (player.canPlayType(\"application/vnd.apple.mpegurl\")) {\r\n player.src = src\r\n return\r\n }\r\n if (Hls.isSupported()) {\r\n const hls = new Hls()\r\n hls.loadSource(src)\r\n hls.attachMedia(player)\r\n return () => {\r\n hls.destroy()\r\n }\r\n }\r\n }, [src])\r\n\r\n return <video ref={video} {...rest} />\r\n})\r\n\r\nexport default HlsPlayer\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAgB;AAChB,mBAAwF;AAMxF,IAAM,gBAAY,yBAA6C,CAAC,OAAO,QAAQ;AAC3E,QAAM,EAAE,KAAK,GAAG,KAAK,IAAI;AACzB,QAAM,YAAQ,qBAAyB,IAAI;AAE3C,wCAAoB,KAAK,MAAM,MAAM,SAAU,CAAC,CAAC;AAEjD,8BAAU,MAAM;AACZ,UAAM,EAAE,SAAS,OAAO,IAAI;AAC5B,QAAI,CAAC,UAAU,CAAC;AAAK;AACrB,QAAI,OAAO,YAAY,+BAA+B,GAAG;AACrD,aAAO,MAAM;AACb;AAAA,IACJ;AACA,QAAI,WAAAA,QAAI,YAAY,GAAG;AACnB,YAAM,MAAM,IAAI,WAAAA,QAAI;AACpB,UAAI,WAAW,GAAG;AAClB,UAAI,YAAY,MAAM;AACtB,aAAO,MAAM;AACT,YAAI,QAAQ;AAAA,MAChB;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,oCAAC,WAAM,KAAK,OAAQ,GAAG,MAAM;AACxC,CAAC;AAED,IAAO,oBAAQ;",
4
+ "sourcesContent": ["\"use client\"\r\n\r\nimport Hls from \"hls.js\"\r\nimport { MediaHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from \"react\"\r\n\r\nexport interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, \"src\"> {\r\n src: string\r\n}\r\n\r\nexport const HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {\r\n const { src, ...rest } = props\r\n const video = useRef<HTMLVideoElement>(null)\r\n\r\n useImperativeHandle(ref, () => video.current!, [])\r\n\r\n useEffect(() => {\r\n const { current: player } = video\r\n if (!player || !src) return\r\n if (player.canPlayType(\"application/vnd.apple.mpegurl\")) {\r\n player.src = src\r\n return\r\n }\r\n if (Hls.isSupported()) {\r\n const hls = new Hls()\r\n hls.loadSource(src)\r\n hls.attachMedia(player)\r\n return () => {\r\n hls.destroy()\r\n }\r\n }\r\n }, [src])\r\n\r\n return <video ref={video} {...rest} />\r\n})\r\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAgB;AAChB,mBAAwF;AAMjF,IAAM,gBAAY,yBAA6C,CAAC,OAAO,QAAQ;AAClF,QAAM,EAAE,KAAK,GAAG,KAAK,IAAI;AACzB,QAAM,YAAQ,qBAAyB,IAAI;AAE3C,wCAAoB,KAAK,MAAM,MAAM,SAAU,CAAC,CAAC;AAEjD,8BAAU,MAAM;AACZ,UAAM,EAAE,SAAS,OAAO,IAAI;AAC5B,QAAI,CAAC,UAAU,CAAC;AAAK;AACrB,QAAI,OAAO,YAAY,+BAA+B,GAAG;AACrD,aAAO,MAAM;AACb;AAAA,IACJ;AACA,QAAI,WAAAA,QAAI,YAAY,GAAG;AACnB,YAAM,MAAM,IAAI,WAAAA,QAAI;AACpB,UAAI,WAAW,GAAG;AAClB,UAAI,YAAY,MAAM;AACtB,aAAO,MAAM;AACT,YAAI,QAAQ;AAAA,MAChB;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,oCAAC,WAAM,KAAK,OAAQ,GAAG,MAAM;AACxC,CAAC;",
6
6
  "names": ["Hls"]
7
7
  }
@@ -1,3 +1,5 @@
1
1
  import { HTMLAttributes } from "react";
2
- declare const Skeleton: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
3
- export default Skeleton;
2
+ export interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
3
+ loading?: boolean;
4
+ }
5
+ export declare const Skeleton: import("react").ForwardRefExoticComponent<SkeletonProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -20,14 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/components/Skeleton.tsx
21
21
  var Skeleton_exports = {};
22
22
  __export(Skeleton_exports, {
23
- default: () => Skeleton_default
23
+ Skeleton: () => Skeleton
24
24
  });
25
25
  module.exports = __toCommonJS(Skeleton_exports);
26
26
  var import_css = require("@emotion/css");
27
27
  var import_deepsea_tools = require("deepsea-tools");
28
28
  var import_react = require("react");
29
29
  var Skeleton = (0, import_react.forwardRef)((props, ref) => {
30
- const { className, ...rest } = props;
30
+ let { className, loading, children, ...rest } = props;
31
+ loading ??= children === void 0 || children === null;
31
32
  return /* @__PURE__ */ React.createElement(
32
33
  "div",
33
34
  {
@@ -42,20 +43,25 @@ var Skeleton = (0, import_react.forwardRef)((props, ref) => {
42
43
  background-position: 400px 0px;
43
44
  }
44
45
  }
45
-
46
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
47
- animation-duration: 1s;
48
- animation-fill-mode: forwards;
49
- animation-iteration-count: infinite;
50
- animation-name: shimmer;
51
- animation-timing-function: linear;
52
- background-size: 800px 104px;
53
46
  `,
47
+ loading && import_css.css`
48
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
49
+ animation-duration: 1s;
50
+ animation-fill-mode: forwards;
51
+ animation-iteration-count: infinite;
52
+ animation-name: shimmer;
53
+ animation-timing-function: linear;
54
+ background-size: 800px 104px;
55
+ `,
54
56
  className
55
57
  ),
56
58
  ...rest
57
- }
59
+ },
60
+ children
58
61
  );
59
62
  });
60
- var Skeleton_default = Skeleton;
63
+ // Annotate the CommonJS export names for ESM import in node:
64
+ 0 && (module.exports = {
65
+ Skeleton
66
+ });
61
67
  //# sourceMappingURL=Skeleton.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/Skeleton.tsx"],
4
- "sourcesContent": ["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { forwardRef, HTMLAttributes } from \"react\"\r\n\r\nconst Skeleton = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>((props, ref) => {\r\n const { className, ...rest } = props\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={clsx(\r\n css`\r\n @keyframes shimmer {\r\n 0% {\r\n background-position: -400px 0px;\r\n }\r\n 100% {\r\n background-position: 400px 0px;\r\n }\r\n }\r\n\r\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);\r\n animation-duration: 1s;\r\n animation-fill-mode: forwards;\r\n animation-iteration-count: infinite;\r\n animation-name: shimmer;\r\n animation-timing-function: linear;\r\n background-size: 800px 104px;\r\n `,\r\n className\r\n )}\r\n {...rest}\r\n />\r\n )\r\n})\r\n\r\nexport default Skeleton\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAoB;AACpB,2BAAqB;AACrB,mBAA2C;AAE3C,IAAM,eAAW,yBAA2D,CAAC,OAAO,QAAQ;AACxF,QAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAE/B,SACI;AAAA,IAAC;AAAA;AAAA,MACG;AAAA,MACA,eAAW;AAAA,QACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkBA;AAAA,MACJ;AAAA,MACC,GAAG;AAAA;AAAA,EACR;AAER,CAAC;AAED,IAAO,mBAAQ;",
4
+ "sourcesContent": ["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { forwardRef, HTMLAttributes } from \"react\"\r\n\r\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\r\n loading?: boolean\r\n}\r\n\r\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>((props, ref) => {\r\n let { className, loading, children, ...rest } = props\r\n\r\n loading ??= children === undefined || children === null\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={clsx(\r\n css`\r\n @keyframes shimmer {\r\n 0% {\r\n background-position: -400px 0px;\r\n }\r\n 100% {\r\n background-position: 400px 0px;\r\n }\r\n }\r\n `,\r\n loading &&\r\n css`\r\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);\r\n animation-duration: 1s;\r\n animation-fill-mode: forwards;\r\n animation-iteration-count: infinite;\r\n animation-name: shimmer;\r\n animation-timing-function: linear;\r\n background-size: 800px 104px;\r\n `,\r\n className\r\n )}\r\n {...rest}>\r\n {children}\r\n </div>\r\n )\r\n})\r\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAoB;AACpB,2BAAqB;AACrB,mBAA2C;AAMpC,IAAM,eAAW,yBAA0C,CAAC,OAAO,QAAQ;AAC9E,MAAI,EAAE,WAAW,SAAS,UAAU,GAAG,KAAK,IAAI;AAEhD,cAAY,aAAa,UAAa,aAAa;AAEnD,SACI;AAAA,IAAC;AAAA;AAAA,MACG;AAAA,MACA,eAAW;AAAA,QACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,WACI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASJ;AAAA,MACJ;AAAA,MACC,GAAG;AAAA;AAAA,IACH;AAAA,EACL;AAER,CAAC;",
6
6
  "names": []
7
7
  }
@@ -68,8 +68,10 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
68
68
  transitionDuration?: number;
69
69
  /** 变化的回调函数 */
70
70
  onSizeChange?: (sizeData: FlowSizeData) => void;
71
+ /** 宽度 */
72
+ width?: number;
71
73
  }
72
74
  export declare function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"];
73
75
  export declare function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): [number, number];
74
76
  /** 自适应浮动组件 */
75
- export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element;
77
+ export declare function Flow<T>(props: FlowProps<T>): import("react/jsx-runtime").JSX.Element | null;
@@ -18,8 +18,7 @@ export function getGapCountAndSize(width, itemWidth, minGap, maxGap) {
18
18
  if (maxGap !== "auto" && averageGap > maxGap) return [count, maxGap];
19
19
  return [count, averageGap];
20
20
  }
21
- /** 自适应浮动组件 */
22
- export function Flow(props) {
21
+ function RealFlow(props) {
23
22
  let {
24
23
  itemWidth,
25
24
  itemHeight,
@@ -39,15 +38,14 @@ export function Flow(props) {
39
38
  containerClassName,
40
39
  containerStyle,
41
40
  gap = 0,
41
+ width,
42
42
  ...rest
43
43
  } = props;
44
44
  rowGap ??= gap;
45
45
  columnGap ??= gap;
46
46
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap);
47
- const [width, setWidth] = useState(0);
48
47
  const [columnCount, setColumnCount] = useState(1);
49
48
  const [columnGapSize, setColumnGapSize] = useState(minColumnGap);
50
- const [showItems, setShowItems] = useState(false);
51
49
  const ele = useRef(null);
52
50
  const contentRows = Math.ceil(data.length / columnCount);
53
51
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows;
@@ -64,31 +62,19 @@ export function Flow(props) {
64
62
  if (typeof maxRows !== "number") return false;
65
63
  return index >= maxRows * columnCount;
66
64
  }
65
+ function task() {
66
+ const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap);
67
+ setColumnCount(newColumnCount);
68
+ setColumnGapSize(newColumnGapSize);
69
+ }
67
70
  useEffect(() => {
68
- let timeout;
69
- const observer = new ResizeObserver(entries => {
70
- clearTimeout(timeout);
71
- function task() {
72
- const {
73
- width
74
- } = entries[0].contentRect;
75
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap);
76
- setShowItems(true);
77
- setWidth(width);
78
- setColumnCount(newColumnCount);
79
- setColumnGapSize(newColumnGapSize);
80
- }
81
- if (throttle === 0) {
82
- task();
83
- } else {
84
- timeout = window.setTimeout(task, throttle || 200);
85
- }
86
- });
87
- observer.observe(ele.current);
88
- return () => {
89
- observer.disconnect();
90
- };
91
- }, [itemWidth, throttle, columnGap]);
71
+ task();
72
+ }, []);
73
+ useEffect(() => {
74
+ if (throttle === 0) return task();
75
+ const timeout = setTimeout(task, throttle || 200);
76
+ return () => clearTimeout(timeout);
77
+ }, [width, itemWidth, throttle, columnGap]);
92
78
  useEffect(() => {
93
79
  onSizeChange?.({
94
80
  width,
@@ -115,16 +101,16 @@ export function Flow(props) {
115
101
  height: px(height)
116
102
  }, style),
117
103
  ...rest,
118
- children: showItems && data.map((item, index, arr) => /*#__PURE__*/_jsx("div", {
104
+ children: data.map((item, index, arr) => /*#__PURE__*/_jsx("div", {
119
105
  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),
106
+ position: absolute;
107
+ width: var(--width);
108
+ height: var(--height);
109
+ transition: var(--transition);
110
+ left: 0;
111
+ top: 0;
112
+ transform: translate(var(--left), var(--top));
113
+ `, wrapperClassName),
128
114
  style: transformCSSVariable({
129
115
  width: px(itemWidth),
130
116
  height: px(itemHeight),
@@ -134,10 +120,10 @@ export function Flow(props) {
134
120
  }, wrapperStyle),
135
121
  children: /*#__PURE__*/_jsx("div", {
136
122
  className: clsx(css`
137
- width: 100%;
138
- height: 100%;
139
- display: var(--display);
140
- `, containerClassName),
123
+ width: 100%;
124
+ height: 100%;
125
+ display: var(--display);
126
+ `, containerClassName),
141
127
  style: transformCSSVariable({
142
128
  display: getHidden(index) ? "none" : "block"
143
129
  }, containerStyle),
@@ -146,4 +132,17 @@ export function Flow(props) {
146
132
  }, keyExactor ? keyExactor(item, index, arr) : index))
147
133
  });
148
134
  }
135
+
136
+ /** 自适应浮动组件 */
137
+ export function Flow(props) {
138
+ const {
139
+ width,
140
+ data
141
+ } = props;
142
+ if (!width || data.length === 0) return null;
143
+ return /*#__PURE__*/_jsx(RealFlow, {
144
+ ...props,
145
+ width: width
146
+ });
147
+ }
149
148
  //# sourceMappingURL=Flow.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["css","clsx","useEffect","useRef","useState","px","transformCSSVariable","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","transition","display"],"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, 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}\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={transformCSSVariable({ height: px(height) }, style)}\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={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"],"mappings":"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"}
1
+ {"version":3,"names":["css","clsx","useEffect","useRef","useState","px","transformCSSVariable","jsx","_jsx","getGapRange","gap","Array","isArray","getGapCountAndSize","width","itemWidth","minGap","maxGap","count","Math","floor","averageGap","RealFlow","props","itemHeight","columnGap","rowGap","maxRows","data","render","keyExactor","className","style","wrapperClassName","wrapperStyle","throttle","transitionDuration","onSizeChange","containerClassName","containerStyle","rest","minColumnGap","maxColumnGap","columnCount","setColumnCount","columnGapSize","setColumnGapSize","ele","contentRows","ceil","length","contentShownRows","min","height","getPosition","index","y","x","left","top","getHidden","task","newColumnCount","newColumnGapSize","timeout","setTimeout","clearTimeout","rowCount","overflow","itemCount","ref","children","map","item","arr","transition","display","Flow"],"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, 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 /** 宽度 */\r\n width?: number\r\n}\r\n\r\nexport function getGapRange(gap?: undefined | number | \"auto\" | (number | \"auto\")[]): [number, number | \"auto\"] {\r\n if (typeof gap === \"number\") return [gap, gap]\r\n if (Array.isArray(gap)) return [typeof gap[0] === \"number\" ? gap[0] : 0, gap[1]]\r\n return [0, \"auto\"]\r\n}\r\n\r\nexport function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | \"auto\"): [number, number] {\r\n const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1\r\n if (count === 1) return [count, 0]\r\n const averageGap = (width - itemWidth * count) / (count - 1)\r\n if (averageGap < minGap) return [count, minGap]\r\n if (maxGap !== \"auto\" && averageGap > maxGap) return [count, maxGap]\r\n return [count, averageGap]\r\n}\r\n\r\ninterface Position {\r\n left: number\r\n top: number\r\n}\r\n\r\nfunction RealFlow<T>(props: FlowProps<T> & { width: number }) {\r\n let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, ...rest } = props\r\n rowGap ??= gap\r\n columnGap ??= gap\r\n const [minColumnGap, maxColumnGap] = getGapRange(columnGap)\r\n const [columnCount, setColumnCount] = useState(1)\r\n const [columnGapSize, setColumnGapSize] = useState(minColumnGap)\r\n\r\n const ele = useRef<HTMLDivElement>(null)\r\n const contentRows = Math.ceil(data.length / columnCount)\r\n const contentShownRows = typeof maxRows === \"number\" ? Math.min(contentRows, maxRows) : contentRows\r\n const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0\r\n\r\n function getPosition(index: number): Position {\r\n const y = Math.floor(index / columnCount)\r\n const x = index - y * columnCount\r\n return {\r\n left: x * (itemWidth + columnGapSize),\r\n top: y * (itemHeight + rowGap!)\r\n }\r\n }\r\n\r\n function getHidden(index: number) {\r\n if (typeof maxRows !== \"number\") return false\r\n return index >= maxRows * columnCount\r\n }\r\n\r\n function task() {\r\n const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)\r\n setColumnCount(newColumnCount)\r\n setColumnGapSize(newColumnGapSize)\r\n }\r\n\r\n 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 { width, data } = props\r\n if (!width || data.length === 0) return null\r\n return <RealFlow {...props} width={width} />\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;AA4EnD,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,SAASC,QAAQA,CAAIC,KAAuC,EAAE;EAC1D,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;IAAEI,KAAK;IAAE,GAAG0B;EAAK,CAAC,GAAGjB,KAAK;EACtPG,MAAM,KAAKhB,GAAG;EACde,SAAS,KAAKf,GAAG;EACjB,MAAM,CAAC+B,YAAY,EAAEC,YAAY,CAAC,GAAGjC,WAAW,CAACgB,SAAS,CAAC;EAC3D,MAAM,CAACkB,WAAW,EAAEC,cAAc,CAAC,GAAGxC,QAAQ,CAAC,CAAC,CAAC;EACjD,MAAM,CAACyC,aAAa,EAAEC,gBAAgB,CAAC,GAAG1C,QAAQ,CAACqC,YAAY,CAAC;EAEhE,MAAMM,GAAG,GAAG5C,MAAM,CAAiB,IAAI,CAAC;EACxC,MAAM6C,WAAW,GAAG7B,IAAI,CAAC8B,IAAI,CAACrB,IAAI,CAACsB,MAAM,GAAGP,WAAW,CAAC;EACxD,MAAMQ,gBAAgB,GAAG,OAAOxB,OAAO,KAAK,QAAQ,GAAGR,IAAI,CAACiC,GAAG,CAACJ,WAAW,EAAErB,OAAO,CAAC,GAAGqB,WAAW;EACnG,MAAMK,MAAM,GAAGF,gBAAgB,GAAG,CAAC,GAAGA,gBAAgB,IAAI3B,UAAU,GAAGE,MAAM,CAAC,GAAGA,MAAM,GAAG,CAAC;EAE3F,SAAS4B,WAAWA,CAACC,KAAa,EAAY;IAC1C,MAAMC,CAAC,GAAGrC,IAAI,CAACC,KAAK,CAACmC,KAAK,GAAGZ,WAAW,CAAC;IACzC,MAAMc,CAAC,GAAGF,KAAK,GAAGC,CAAC,GAAGb,WAAW;IACjC,OAAO;MACHe,IAAI,EAAED,CAAC,IAAI1C,SAAS,GAAG8B,aAAa,CAAC;MACrCc,GAAG,EAAEH,CAAC,IAAIhC,UAAU,GAAGE,MAAO;IAClC,CAAC;EACL;EAEA,SAASkC,SAASA,CAACL,KAAa,EAAE;IAC9B,IAAI,OAAO5B,OAAO,KAAK,QAAQ,EAAE,OAAO,KAAK;IAC7C,OAAO4B,KAAK,IAAI5B,OAAO,GAAGgB,WAAW;EACzC;EAEA,SAASkB,IAAIA,CAAA,EAAG;IACZ,MAAM,CAACC,cAAc,EAAEC,gBAAgB,CAAC,GAAGlD,kBAAkB,CAACC,KAAK,EAAEC,SAAS,EAAE0B,YAAY,EAAEC,YAAY,CAAC;IAC3GE,cAAc,CAACkB,cAAc,CAAC;IAC9BhB,gBAAgB,CAACiB,gBAAgB,CAAC;EACtC;EAEA7D,SAAS,CAAC,MAAM;IACZ2D,IAAI,CAAC,CAAC;EACV,CAAC,EAAE,EAAE,CAAC;EAEN3D,SAAS,CAAC,MAAM;IACZ,IAAIiC,QAAQ,KAAK,CAAC,EAAE,OAAO0B,IAAI,CAAC,CAAC;IACjC,MAAMG,OAAO,GAAGC,UAAU,CAACJ,IAAI,EAAE1B,QAAQ,IAAI,GAAG,CAAC;IACjD,OAAO,MAAM+B,YAAY,CAACF,OAAO,CAAC;EACtC,CAAC,EAAE,CAAClD,KAAK,EAAEC,SAAS,EAAEoB,QAAQ,EAAEV,SAAS,CAAC,CAAC;EAE3CvB,SAAS,CAAC,MAAM;IACZmC,YAAY,GAAG;MAAEvB,KAAK;MAAEuC,MAAM;MAAEtC,SAAS;MAAES,UAAU;MAAEC,SAAS,EAAEoB,aAAa;MAAEF,WAAW;MAAEjB,MAAM,EAAEA,MAAO;MAAEyC,QAAQ,EAAEhB,gBAAgB;MAAEiB,QAAQ,EAAExC,IAAI,CAACsB,MAAM,GAAGC,gBAAgB,GAAGR,WAAW;MAAE0B,SAAS,EAAEzC,IAAI,CAACsB,MAAM;MAAEvB,OAAO,EAAEA,OAAO,IAAI;IAAK,CAAC,CAAC;EAC1P,CAAC,EAAE,CAACb,KAAK,EAAEuC,MAAM,EAAER,aAAa,EAAEF,WAAW,EAAEjB,MAAM,EAAEyB,gBAAgB,EAAEvB,IAAI,CAACsB,MAAM,EAAEnC,SAAS,EAAES,UAAU,EAAEG,OAAO,CAAC,CAAC;EAEtH,oBACInB,IAAA;IACI8D,GAAG,EAAEvB,GAAI;IACThB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AACpB;AACA;AACA;AACA,iBAAiB,EACD+B,SACJ,CAAE;IACFC,KAAK,EAAE1B,oBAAoB,CAAC;MAAE+C,MAAM,EAAEhD,EAAE,CAACgD,MAAM;IAAE,CAAC,EAAErB,KAAK,CAAE;IAAA,GACvDQ,IAAI;IAAA+B,QAAA,EACP3C,IAAI,CAAC4C,GAAG,CAAC,CAACC,IAAI,EAAElB,KAAK,EAAEmB,GAAG,kBACvBlE,IAAA;MAEIuB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB,EACDiC,gBACJ,CAAE;MACFD,KAAK,EAAE1B,oBAAoB,CACvB;QACIQ,KAAK,EAAET,EAAE,CAACU,SAAS,CAAC;QACpBsC,MAAM,EAAEhD,EAAE,CAACmB,UAAU,CAAC;QACtBmD,UAAU,EAAEvC,kBAAkB,KAAK,CAAC,GAAG,MAAM,GAAI,OAAMA,kBAAkB,IAAI,GAAI,IAAG;QACpFsB,IAAI,EAAErD,EAAE,CAACiD,WAAW,CAACC,KAAK,CAAC,CAACG,IAAI,CAAC;QACjCC,GAAG,EAAEtD,EAAE,CAACiD,WAAW,CAACC,KAAK,CAAC,CAACI,GAAG;MAClC,CAAC,EACDzB,YACJ,CAAE;MAAAqC,QAAA,eACF/D,IAAA;QACIuB,SAAS,EAAE9B,IAAI,CACXD,GAAI;AAChC;AACA;AACA;AACA,6BAA6B,EACDsC,kBACJ,CAAE;QACFN,KAAK,EAAE1B,oBAAoB,CAAC;UAAEsE,OAAO,EAAEhB,SAAS,CAACL,KAAK,CAAC,GAAG,MAAM,GAAG;QAAQ,CAAC,EAAEhB,cAAc,CAAE;QAAAgC,QAAA,EAC7F1C,MAAM,CAAC4C,IAAI,EAAElB,KAAK,EAAEmB,GAAG;MAAC,CACxB;IAAC,GAlCD5C,UAAU,GAAGA,UAAU,CAAC2C,IAAI,EAAElB,KAAK,EAAEmB,GAAG,CAAC,GAAGnB,KAmChD,CACR;EAAC,CACD,CAAC;AAEd;;AAEA;AACA,OAAO,SAASsB,IAAIA,CAAItD,KAAmB,EAAE;EACzC,MAAM;IAAET,KAAK;IAAEc;EAAK,CAAC,GAAGL,KAAK;EAC7B,IAAI,CAACT,KAAK,IAAIc,IAAI,CAACsB,MAAM,KAAK,CAAC,EAAE,OAAO,IAAI;EAC5C,oBAAO1C,IAAA,CAACc,QAAQ;IAAA,GAAKC,KAAK;IAAET,KAAK,EAAEA;EAAM,CAAE,CAAC;AAChD"}
@@ -2,5 +2,4 @@ import { MediaHTMLAttributes } from "react";
2
2
  export interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, "src"> {
3
3
  src: string;
4
4
  }
5
- declare const HlsPlayer: import("react").ForwardRefExoticComponent<HlsPlayerProps & import("react").RefAttributes<HTMLVideoElement>>;
6
- export default HlsPlayer;
5
+ export declare const HlsPlayer: import("react").ForwardRefExoticComponent<HlsPlayerProps & import("react").RefAttributes<HTMLVideoElement>>;
@@ -3,7 +3,7 @@
3
3
  import Hls from "hls.js";
4
4
  import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
5
5
  import { jsx as _jsx } from "react/jsx-runtime";
6
- const HlsPlayer = /*#__PURE__*/forwardRef((props, ref) => {
6
+ export const HlsPlayer = /*#__PURE__*/forwardRef((props, ref) => {
7
7
  const {
8
8
  src,
9
9
  ...rest
@@ -33,5 +33,4 @@ const HlsPlayer = /*#__PURE__*/forwardRef((props, ref) => {
33
33
  ...rest
34
34
  });
35
35
  });
36
- export default HlsPlayer;
37
36
  //# sourceMappingURL=HlsPlayer.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Hls","forwardRef","useEffect","useImperativeHandle","useRef","jsx","_jsx","HlsPlayer","props","ref","src","rest","video","current","player","canPlayType","isSupported","hls","loadSource","attachMedia","destroy"],"sources":["../../../src/components/HlsPlayer.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport Hls from \"hls.js\"\r\nimport { MediaHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from \"react\"\r\n\r\nexport interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, \"src\"> {\r\n src: string\r\n}\r\n\r\nconst HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {\r\n const { src, ...rest } = props\r\n const video = useRef<HTMLVideoElement>(null)\r\n\r\n useImperativeHandle(ref, () => video.current!, [])\r\n\r\n useEffect(() => {\r\n const { current: player } = video\r\n if (!player || !src) return\r\n if (player.canPlayType(\"application/vnd.apple.mpegurl\")) {\r\n player.src = src\r\n return\r\n }\r\n if (Hls.isSupported()) {\r\n const hls = new Hls()\r\n hls.loadSource(src)\r\n hls.attachMedia(player)\r\n return () => {\r\n hls.destroy()\r\n }\r\n }\r\n }, [src])\r\n\r\n return <video ref={video} {...rest} />\r\n})\r\n\r\nexport default HlsPlayer\r\n"],"mappings":"AAAA,YAAY;;AAEZ,OAAOA,GAAG,MAAM,QAAQ;AACxB,SAA8BC,UAAU,EAAEC,SAAS,EAAEC,mBAAmB,EAAEC,MAAM,QAAQ,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAM/F,MAAMC,SAAS,gBAAGN,UAAU,CAAmC,CAACO,KAAK,EAAEC,GAAG,KAAK;EAC3E,MAAM;IAAEC,GAAG;IAAE,GAAGC;EAAK,CAAC,GAAGH,KAAK;EAC9B,MAAMI,KAAK,GAAGR,MAAM,CAAmB,IAAI,CAAC;EAE5CD,mBAAmB,CAACM,GAAG,EAAE,MAAMG,KAAK,CAACC,OAAQ,EAAE,EAAE,CAAC;EAElDX,SAAS,CAAC,MAAM;IACZ,MAAM;MAAEW,OAAO,EAAEC;IAAO,CAAC,GAAGF,KAAK;IACjC,IAAI,CAACE,MAAM,IAAI,CAACJ,GAAG,EAAE;IACrB,IAAII,MAAM,CAACC,WAAW,CAAC,+BAA+B,CAAC,EAAE;MACrDD,MAAM,CAACJ,GAAG,GAAGA,GAAG;MAChB;IACJ;IACA,IAAIV,GAAG,CAACgB,WAAW,CAAC,CAAC,EAAE;MACnB,MAAMC,GAAG,GAAG,IAAIjB,GAAG,CAAC,CAAC;MACrBiB,GAAG,CAACC,UAAU,CAACR,GAAG,CAAC;MACnBO,GAAG,CAACE,WAAW,CAACL,MAAM,CAAC;MACvB,OAAO,MAAM;QACTG,GAAG,CAACG,OAAO,CAAC,CAAC;MACjB,CAAC;IACL;EACJ,CAAC,EAAE,CAACV,GAAG,CAAC,CAAC;EAET,oBAAOJ,IAAA;IAAOG,GAAG,EAAEG,KAAM;IAAA,GAAKD;EAAI,CAAG,CAAC;AAC1C,CAAC,CAAC;AAEF,eAAeJ,SAAS"}
1
+ {"version":3,"names":["Hls","forwardRef","useEffect","useImperativeHandle","useRef","jsx","_jsx","HlsPlayer","props","ref","src","rest","video","current","player","canPlayType","isSupported","hls","loadSource","attachMedia","destroy"],"sources":["../../../src/components/HlsPlayer.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport Hls from \"hls.js\"\r\nimport { MediaHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from \"react\"\r\n\r\nexport interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElement>, \"src\"> {\r\n src: string\r\n}\r\n\r\nexport const HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {\r\n const { src, ...rest } = props\r\n const video = useRef<HTMLVideoElement>(null)\r\n\r\n useImperativeHandle(ref, () => video.current!, [])\r\n\r\n useEffect(() => {\r\n const { current: player } = video\r\n if (!player || !src) return\r\n if (player.canPlayType(\"application/vnd.apple.mpegurl\")) {\r\n player.src = src\r\n return\r\n }\r\n if (Hls.isSupported()) {\r\n const hls = new Hls()\r\n hls.loadSource(src)\r\n hls.attachMedia(player)\r\n return () => {\r\n hls.destroy()\r\n }\r\n }\r\n }, [src])\r\n\r\n return <video ref={video} {...rest} />\r\n})\r\n"],"mappings":"AAAA,YAAY;;AAEZ,OAAOA,GAAG,MAAM,QAAQ;AACxB,SAA8BC,UAAU,EAAEC,SAAS,EAAEC,mBAAmB,EAAEC,MAAM,QAAQ,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAM/F,OAAO,MAAMC,SAAS,gBAAGN,UAAU,CAAmC,CAACO,KAAK,EAAEC,GAAG,KAAK;EAClF,MAAM;IAAEC,GAAG;IAAE,GAAGC;EAAK,CAAC,GAAGH,KAAK;EAC9B,MAAMI,KAAK,GAAGR,MAAM,CAAmB,IAAI,CAAC;EAE5CD,mBAAmB,CAACM,GAAG,EAAE,MAAMG,KAAK,CAACC,OAAQ,EAAE,EAAE,CAAC;EAElDX,SAAS,CAAC,MAAM;IACZ,MAAM;MAAEW,OAAO,EAAEC;IAAO,CAAC,GAAGF,KAAK;IACjC,IAAI,CAACE,MAAM,IAAI,CAACJ,GAAG,EAAE;IACrB,IAAII,MAAM,CAACC,WAAW,CAAC,+BAA+B,CAAC,EAAE;MACrDD,MAAM,CAACJ,GAAG,GAAGA,GAAG;MAChB;IACJ;IACA,IAAIV,GAAG,CAACgB,WAAW,CAAC,CAAC,EAAE;MACnB,MAAMC,GAAG,GAAG,IAAIjB,GAAG,CAAC,CAAC;MACrBiB,GAAG,CAACC,UAAU,CAACR,GAAG,CAAC;MACnBO,GAAG,CAACE,WAAW,CAACL,MAAM,CAAC;MACvB,OAAO,MAAM;QACTG,GAAG,CAACG,OAAO,CAAC,CAAC;MACjB,CAAC;IACL;EACJ,CAAC,EAAE,CAACV,GAAG,CAAC,CAAC;EAET,oBAAOJ,IAAA;IAAOG,GAAG,EAAEG,KAAM;IAAA,GAAKD;EAAI,CAAG,CAAC;AAC1C,CAAC,CAAC"}
@@ -1,3 +1,5 @@
1
1
  import { HTMLAttributes } from "react";
2
- declare const Skeleton: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
3
- export default Skeleton;
2
+ export interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
3
+ loading?: boolean;
4
+ }
5
+ export declare const Skeleton: import("react").ForwardRefExoticComponent<SkeletonProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -4,11 +4,14 @@ import { css } from "@emotion/css";
4
4
  import { clsx } from "deepsea-tools";
5
5
  import { forwardRef } from "react";
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
- const Skeleton = /*#__PURE__*/forwardRef((props, ref) => {
8
- const {
7
+ export const Skeleton = /*#__PURE__*/forwardRef((props, ref) => {
8
+ let {
9
9
  className,
10
+ loading,
11
+ children,
10
12
  ...rest
11
13
  } = props;
14
+ loading ??= children === undefined || children === null;
12
15
  return /*#__PURE__*/_jsx("div", {
13
16
  ref: ref,
14
17
  className: clsx(css`
@@ -20,17 +23,17 @@ const Skeleton = /*#__PURE__*/forwardRef((props, ref) => {
20
23
  background-position: 400px 0px;
21
24
  }
22
25
  }
23
-
24
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
25
- animation-duration: 1s;
26
- animation-fill-mode: forwards;
27
- animation-iteration-count: infinite;
28
- animation-name: shimmer;
29
- animation-timing-function: linear;
30
- background-size: 800px 104px;
31
- `, className),
32
- ...rest
26
+ `, loading && css`
27
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
28
+ animation-duration: 1s;
29
+ animation-fill-mode: forwards;
30
+ animation-iteration-count: infinite;
31
+ animation-name: shimmer;
32
+ animation-timing-function: linear;
33
+ background-size: 800px 104px;
34
+ `, className),
35
+ ...rest,
36
+ children: children
33
37
  });
34
38
  });
35
- export default Skeleton;
36
39
  //# sourceMappingURL=Skeleton.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["css","clsx","forwardRef","jsx","_jsx","Skeleton","props","ref","className","rest"],"sources":["../../../src/components/Skeleton.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { forwardRef, HTMLAttributes } from \"react\"\r\n\r\nconst Skeleton = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>((props, ref) => {\r\n const { className, ...rest } = props\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={clsx(\r\n css`\r\n @keyframes shimmer {\r\n 0% {\r\n background-position: -400px 0px;\r\n }\r\n 100% {\r\n background-position: 400px 0px;\r\n }\r\n }\r\n\r\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);\r\n animation-duration: 1s;\r\n animation-fill-mode: forwards;\r\n animation-iteration-count: infinite;\r\n animation-name: shimmer;\r\n animation-timing-function: linear;\r\n background-size: 800px 104px;\r\n `,\r\n className\r\n )}\r\n {...rest}\r\n />\r\n )\r\n})\r\n\r\nexport default Skeleton\r\n"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,GAAG,QAAQ,cAAc;AAClC,SAASC,IAAI,QAAQ,eAAe;AACpC,SAASC,UAAU,QAAwB,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAElD,MAAMC,QAAQ,gBAAGH,UAAU,CAAiD,CAACI,KAAK,EAAEC,GAAG,KAAK;EACxF,MAAM;IAAEC,SAAS;IAAE,GAAGC;EAAK,CAAC,GAAGH,KAAK;EAEpC,oBACIF,IAAA;IACIG,GAAG,EAAEA,GAAI;IACTC,SAAS,EAAEP,IAAI,CACXD,GAAI;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,EACDQ,SACJ,CAAE;IAAA,GACEC;EAAI,CACX,CAAC;AAEV,CAAC,CAAC;AAEF,eAAeJ,QAAQ"}
1
+ {"version":3,"names":["css","clsx","forwardRef","jsx","_jsx","Skeleton","props","ref","className","loading","children","rest","undefined"],"sources":["../../../src/components/Skeleton.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { css } from \"@emotion/css\"\r\nimport { clsx } from \"deepsea-tools\"\r\nimport { forwardRef, HTMLAttributes } from \"react\"\r\n\r\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\r\n loading?: boolean\r\n}\r\n\r\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>((props, ref) => {\r\n let { className, loading, children, ...rest } = props\r\n\r\n loading ??= children === undefined || children === null\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={clsx(\r\n css`\r\n @keyframes shimmer {\r\n 0% {\r\n background-position: -400px 0px;\r\n }\r\n 100% {\r\n background-position: 400px 0px;\r\n }\r\n }\r\n `,\r\n loading &&\r\n css`\r\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);\r\n animation-duration: 1s;\r\n animation-fill-mode: forwards;\r\n animation-iteration-count: infinite;\r\n animation-name: shimmer;\r\n animation-timing-function: linear;\r\n background-size: 800px 104px;\r\n `,\r\n className\r\n )}\r\n {...rest}>\r\n {children}\r\n </div>\r\n )\r\n})\r\n"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,GAAG,QAAQ,cAAc;AAClC,SAASC,IAAI,QAAQ,eAAe;AACpC,SAASC,UAAU,QAAwB,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAMlD,OAAO,MAAMC,QAAQ,gBAAGH,UAAU,CAAgC,CAACI,KAAK,EAAEC,GAAG,KAAK;EAC9E,IAAI;IAAEC,SAAS;IAAEC,OAAO;IAAEC,QAAQ;IAAE,GAAGC;EAAK,CAAC,GAAGL,KAAK;EAErDG,OAAO,KAAKC,QAAQ,KAAKE,SAAS,IAAIF,QAAQ,KAAK,IAAI;EAEvD,oBACIN,IAAA;IACIG,GAAG,EAAEA,GAAI;IACTC,SAAS,EAAEP,IAAI,CACXD,GAAI;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,EACDS,OAAO,IACHT,GAAI;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,EACLQ,SACJ,CAAE;IAAA,GACEG,IAAI;IAAAD,QAAA,EACPA;EAAQ,CACR,CAAC;AAEd,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepsea-components",
3
- "version": "3.1.0",
3
+ "version": "3.2.0-beta.20240606182955",
4
4
  "description": "格数科技自用组件库",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -45,4 +45,4 @@
45
45
  "peerDependencies": {
46
46
  "react": "^18.3.1"
47
47
  }
48
- }
48
+ }
@@ -61,7 +61,7 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
61
61
  * 渲染的元素由两层容器包裹,外层容器样式
62
62
  */
63
63
  wrapperStyle?: CSSProperties
64
- /**
64
+ /**
65
65
  * 渲染的元素由两层容器包裹,内层容器类名
66
66
  */
67
67
  containerClassName?: string
@@ -75,6 +75,8 @@ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "chil
75
75
  transitionDuration?: number
76
76
  /** 变化的回调函数 */
77
77
  onSizeChange?: (sizeData: FlowSizeData) => void
78
+ /** 宽度 */
79
+ width?: number
78
80
  }
79
81
 
80
82
  export function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"] {
@@ -97,16 +99,14 @@ interface Position {
97
99
  top: number
98
100
  }
99
101
 
100
- /** 自适应浮动组件 */
101
- export function Flow<T>(props: FlowProps<T>) {
102
- let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, ...rest } = props
102
+ function RealFlow<T>(props: FlowProps<T> & { width: number }) {
103
+ let { itemWidth, itemHeight, columnGap, rowGap, maxRows, data, render, keyExactor, className, style, wrapperClassName, wrapperStyle, throttle, transitionDuration, onSizeChange, containerClassName, containerStyle, gap = 0, width, ...rest } = props
103
104
  rowGap ??= gap
104
105
  columnGap ??= gap
105
106
  const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
106
- const [width, setWidth] = useState(0)
107
107
  const [columnCount, setColumnCount] = useState(1)
108
108
  const [columnGapSize, setColumnGapSize] = useState(minColumnGap)
109
- const [showItems, setShowItems] = useState(false)
109
+
110
110
  const ele = useRef<HTMLDivElement>(null)
111
111
  const contentRows = Math.ceil(data.length / columnCount)
112
112
  const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows
@@ -126,30 +126,21 @@ export function Flow<T>(props: FlowProps<T>) {
126
126
  return index >= maxRows * columnCount
127
127
  }
128
128
 
129
+ function task() {
130
+ const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)
131
+ setColumnCount(newColumnCount)
132
+ setColumnGapSize(newColumnGapSize)
133
+ }
134
+
129
135
  useEffect(() => {
130
- let timeout: number
131
- const observer = new ResizeObserver(entries => {
132
- clearTimeout(timeout)
133
- function task() {
134
- const { width } = entries[0].contentRect
135
- const [newColumnCount, newColumnGapSize] = getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap)
136
- setShowItems(true)
137
- setWidth(width)
138
- setColumnCount(newColumnCount)
139
- setColumnGapSize(newColumnGapSize)
140
- }
141
- if (throttle === 0) {
142
- task()
143
- } else {
144
- timeout = window.setTimeout(task, throttle || 200)
145
- }
146
- })
147
- observer.observe(ele.current!)
148
-
149
- return () => {
150
- observer.disconnect()
151
- }
152
- }, [itemWidth, throttle, columnGap])
136
+ task()
137
+ }, [])
138
+
139
+ useEffect(() => {
140
+ if (throttle === 0) return task()
141
+ const timeout = setTimeout(task, throttle || 200)
142
+ return () => clearTimeout(timeout)
143
+ }, [width, itemWidth, throttle, columnGap])
153
144
 
154
145
  useEffect(() => {
155
146
  onSizeChange?.({ width, height, itemWidth, itemHeight, columnGap: columnGapSize, columnCount, rowGap: rowGap!, rowCount: contentShownRows, overflow: data.length > contentShownRows * columnCount, itemCount: data.length, maxRows: maxRows ?? null })
@@ -168,46 +159,52 @@ export function Flow<T>(props: FlowProps<T>) {
168
159
  )}
169
160
  style={transformCSSVariable({ height: px(height) }, style)}
170
161
  {...rest}>
171
- {showItems &&
172
- data.map((item, index, arr) => (
162
+ {data.map((item, index, arr) => (
163
+ <div
164
+ key={keyExactor ? keyExactor(item, index, arr) : index}
165
+ className={clsx(
166
+ css`
167
+ position: absolute;
168
+ width: var(--width);
169
+ height: var(--height);
170
+ transition: var(--transition);
171
+ left: 0;
172
+ top: 0;
173
+ transform: translate(var(--left), var(--top));
174
+ `,
175
+ wrapperClassName
176
+ )}
177
+ style={transformCSSVariable(
178
+ {
179
+ width: px(itemWidth),
180
+ height: px(itemHeight),
181
+ transition: transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
182
+ left: px(getPosition(index).left),
183
+ top: px(getPosition(index).top)
184
+ },
185
+ wrapperStyle
186
+ )}>
173
187
  <div
174
- key={keyExactor ? keyExactor(item, index, arr) : index}
175
188
  className={clsx(
176
189
  css`
177
- position: absolute;
178
- width: var(--width);
179
- height: var(--height);
180
- transition: var(--transition);
181
- left: 0;
182
- top: 0;
183
- transform: translate(var(--left), var(--top));
190
+ width: 100%;
191
+ height: 100%;
192
+ display: var(--display);
184
193
  `,
185
- wrapperClassName
194
+ containerClassName
186
195
  )}
187
- style={transformCSSVariable(
188
- {
189
- width: px(itemWidth),
190
- height: px(itemHeight),
191
- transition: transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
192
- left: px(getPosition(index).left),
193
- top: px(getPosition(index).top)
194
- },
195
- wrapperStyle
196
- )}>
197
- <div
198
- className={clsx(
199
- css`
200
- width: 100%;
201
- height: 100%;
202
- display: var(--display);
203
- `,
204
- containerClassName
205
- )}
206
- style={transformCSSVariable({ display: getHidden(index) ? "none" : "block" }, containerStyle)}>
207
- {render(item, index, arr)}
208
- </div>
196
+ style={transformCSSVariable({ display: getHidden(index) ? "none" : "block" }, containerStyle)}>
197
+ {render(item, index, arr)}
209
198
  </div>
210
- ))}
199
+ </div>
200
+ ))}
211
201
  </div>
212
202
  )
213
203
  }
204
+
205
+ /** 自适应浮动组件 */
206
+ export function Flow<T>(props: FlowProps<T>) {
207
+ const { width, data } = props
208
+ if (!width || data.length === 0) return null
209
+ return <RealFlow {...props} width={width} />
210
+ }
@@ -7,7 +7,7 @@ export interface HlsPlayerProps extends Omit<MediaHTMLAttributes<HTMLVideoElemen
7
7
  src: string
8
8
  }
9
9
 
10
- const HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {
10
+ export const HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {
11
11
  const { src, ...rest } = props
12
12
  const video = useRef<HTMLVideoElement>(null)
13
13
 
@@ -32,5 +32,3 @@ const HlsPlayer = forwardRef<HTMLVideoElement, HlsPlayerProps>((props, ref) => {
32
32
 
33
33
  return <video ref={video} {...rest} />
34
34
  })
35
-
36
- export default HlsPlayer
@@ -4,8 +4,14 @@ import { css } from "@emotion/css"
4
4
  import { clsx } from "deepsea-tools"
5
5
  import { forwardRef, HTMLAttributes } from "react"
6
6
 
7
- const Skeleton = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>((props, ref) => {
8
- const { className, ...rest } = props
7
+ export interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
8
+ loading?: boolean
9
+ }
10
+
11
+ export const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>((props, ref) => {
12
+ let { className, loading, children, ...rest } = props
13
+
14
+ loading ??= children === undefined || children === null
9
15
 
10
16
  return (
11
17
  <div
@@ -20,20 +26,21 @@ const Skeleton = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>((pro
20
26
  background-position: 400px 0px;
21
27
  }
22
28
  }
23
-
24
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
25
- animation-duration: 1s;
26
- animation-fill-mode: forwards;
27
- animation-iteration-count: infinite;
28
- animation-name: shimmer;
29
- animation-timing-function: linear;
30
- background-size: 800px 104px;
31
29
  `,
30
+ loading &&
31
+ css`
32
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.067) 8%, rgba(0, 0, 0, 0.133) 18%, rgba(0, 0, 0, 0.067) 33%);
33
+ animation-duration: 1s;
34
+ animation-fill-mode: forwards;
35
+ animation-iteration-count: infinite;
36
+ animation-name: shimmer;
37
+ animation-timing-function: linear;
38
+ background-size: 800px 104px;
39
+ `,
32
40
  className
33
41
  )}
34
- {...rest}
35
- />
42
+ {...rest}>
43
+ {children}
44
+ </div>
36
45
  )
37
46
  })
38
-
39
- export default Skeleton