@rainbow-oh/yee-c 0.8.14 → 0.8.16

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.
Files changed (69) hide show
  1. package/dist/cjs/Progress/circle.js +1 -1
  2. package/dist/cjs/Progress/line.js +1 -1
  3. package/dist/cjs/Progress/progress.js +2 -0
  4. package/dist/cjs/Progress/steps.js +1 -1
  5. package/dist/cjs/Search/search.js +45 -16
  6. package/dist/cjs/Select/interface.d.ts +2 -1
  7. package/dist/cjs/Spin/demo/types.js +1 -1
  8. package/dist/cjs/Spin/indicator.d.ts +1 -1
  9. package/dist/cjs/Spin/indicator.js +144 -0
  10. package/dist/cjs/Spin/interface.d.ts +1 -1
  11. package/dist/cjs/Spin/style/index.less +86 -0
  12. package/dist/cjs/Table/demo/fixed.d.ts +3 -0
  13. package/dist/cjs/Table/demo/fixed.js +123 -0
  14. package/dist/cjs/Table/hooks/useColumns.d.ts +2 -1
  15. package/dist/cjs/Table/hooks/useColumns.js +4 -3
  16. package/dist/cjs/Table/style/index.less +23 -3
  17. package/dist/cjs/Table/table.js +67 -21
  18. package/dist/cjs/Table/util/index.d.ts +1 -1
  19. package/dist/cjs/Table/util/index.js +16 -3
  20. package/dist/cjs/style/themes.css +1 -1
  21. package/dist/cjs/style/variables.css +1 -1
  22. package/dist/cjs/version.d.ts +1 -1
  23. package/dist/cjs/version.js +1 -1
  24. package/dist/esm/Progress/circle.js +2 -1
  25. package/dist/esm/Progress/line.js +2 -1
  26. package/dist/esm/Progress/progress.js +2 -0
  27. package/dist/esm/Progress/steps.js +6 -1
  28. package/dist/esm/Search/search.js +31 -7
  29. package/dist/esm/Select/interface.d.ts +2 -1
  30. package/dist/esm/Spin/demo/types.js +10 -7
  31. package/dist/esm/Spin/indicator.d.ts +1 -1
  32. package/dist/esm/Spin/indicator.js +137 -0
  33. package/dist/esm/Spin/interface.d.ts +1 -1
  34. package/dist/esm/Spin/style/index.less +86 -0
  35. package/dist/esm/Table/demo/fixed.d.ts +3 -0
  36. package/dist/esm/Table/demo/fixed.js +84 -0
  37. package/dist/esm/Table/hooks/useColumns.d.ts +2 -1
  38. package/dist/esm/Table/hooks/useColumns.js +4 -3
  39. package/dist/esm/Table/style/index.less +23 -3
  40. package/dist/esm/Table/table.js +85 -26
  41. package/dist/esm/Table/util/index.d.ts +1 -1
  42. package/dist/esm/Table/util/index.js +16 -3
  43. package/dist/esm/style/themes.css +1 -1
  44. package/dist/esm/style/variables.css +1 -1
  45. package/dist/esm/version.d.ts +1 -1
  46. package/dist/esm/version.js +1 -1
  47. package/dist/umd/yee-c.min.css +1 -1
  48. package/dist/umd/yee-c.min.js +1 -1
  49. package/package.json +1 -1
  50. package/src/Progress/circle.tsx +1 -1
  51. package/src/Progress/line.tsx +1 -1
  52. package/src/Progress/progress.tsx +2 -0
  53. package/src/Progress/steps.tsx +3 -1
  54. package/src/Search/search.tsx +33 -4
  55. package/src/Select/interface.ts +2 -1
  56. package/src/Spin/demo/types.tsx +18 -3
  57. package/src/Spin/index.en-US.md +5 -2
  58. package/src/Spin/index.zh-CN.md +5 -2
  59. package/src/Spin/indicator.tsx +165 -1
  60. package/src/Spin/interface.ts +1 -1
  61. package/src/Spin/style/index.less +86 -0
  62. package/src/Table/demo/fixed.tsx +92 -0
  63. package/src/Table/hooks/useColumns.ts +4 -2
  64. package/src/Table/index.en-US.md +1 -0
  65. package/src/Table/index.zh-CN.md +1 -0
  66. package/src/Table/style/index.less +23 -3
  67. package/src/Table/table.tsx +88 -23
  68. package/src/Table/util/index.ts +32 -7
  69. package/src/version.ts +1 -1
@@ -85,15 +85,34 @@
85
85
  overflow: auto;
86
86
 
87
87
  &-wrapper {
88
- overflow: auto;
89
88
  width: 100%;
90
89
 
91
90
  &-scroll-left @{pls}-cell-fixed-left-last {
92
- box-shadow: 6px 0 6px -4px var(--yee-table-fixed-left-after-bs-color);
91
+ &::after {
92
+ content: '';
93
+ pointer-events: none;
94
+ position: absolute;
95
+ display: block;
96
+ height: 100%;
97
+ width: 15px;
98
+ right: -15px;
99
+ top: 0;
100
+ box-shadow: inset 4px 0 8px -4px var(--yee-table-fixed-left-after-bs-color);
101
+ }
93
102
  }
94
103
 
95
104
  &-scroll-right @{pls}-cell-fixed-right-first {
96
- box-shadow: -6px 0 6px -4px var(--yee-table-fixed-right-after-bs-color);
105
+ &::after {
106
+ content: '';
107
+ pointer-events: none;
108
+ position: absolute;
109
+ display: block;
110
+ height: 100%;
111
+ width: 15px;
112
+ left: -15px;
113
+ top: 0;
114
+ box-shadow: inset -4px 0 8px -4px var(--yee-table-fixed-right-after-bs-color);
115
+ }
97
116
  }
98
117
  }
99
118
 
@@ -156,6 +175,7 @@
156
175
  &-fixed-left,
157
176
  &-fixed-right {
158
177
  position: sticky;
178
+ z-index: 1;
159
179
  background-color: var(--yee-table-fixed-column-bg-color);
160
180
  }
161
181
  }
@@ -12,6 +12,7 @@ import TFooter from './tfooter';
12
12
  import THeader from './theader';
13
13
 
14
14
  import { GlobalContext } from '../Config-Provider';
15
+ import useLatest from '../hooks/useLatest';
15
16
  import mergeContextToProps from '../utils/mergeContextToProps';
16
17
  import omit from '../utils/omit';
17
18
  import { pickDataAttrs } from '../utils/types';
@@ -61,6 +62,8 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
61
62
  } = props;
62
63
 
63
64
  const dataAttrs = pickDataAttrs(rest as Record<string, unknown>);
65
+ const [measuredColumnWidths, setMeasuredColumnWidths] =
66
+ React.useState<number[]>();
64
67
 
65
68
  const getRowKey = React.useCallback(
66
69
  (record: Record<string, any>, key = rowKey) => {
@@ -80,6 +83,7 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
80
83
  columns: propColumns,
81
84
  expandable,
82
85
  rowSelection,
86
+ measuredColumnWidths,
83
87
  });
84
88
 
85
89
  // Filter
@@ -153,27 +157,22 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
153
157
 
154
158
  // Track filter changes to emit onChange after filtered data is recalculated
155
159
  const prevFilterRecordsRef = useRef(filterRecords);
156
- const contentWrapperRef = useRef<HTMLDivElement>(null);
157
160
  const contentRef = useRef<HTMLDivElement>(null);
161
+ const tableRef = useRef<HTMLTableElement>(null);
158
162
  const [horizontalScroll, setHorizontalScroll] = React.useState({
159
163
  left: false,
160
164
  right: false,
161
165
  });
162
166
 
163
167
  const updateHorizontalScroll = React.useCallback(() => {
164
- const wrapper = contentWrapperRef.current;
165
168
  const content = contentRef.current;
166
- if (!wrapper || !content) return;
169
+ if (!content) return;
167
170
 
168
- const scrollContainer =
169
- content.scrollWidth - content.clientWidth > 1 ? content : wrapper;
170
- const maxScrollLeft =
171
- scrollContainer.scrollWidth - scrollContainer.clientWidth;
171
+ const maxScrollLeft = content.scrollWidth - content.clientWidth;
172
172
  const hasHorizontalScroll = maxScrollLeft > 1;
173
173
  const next = {
174
- left: hasHorizontalScroll && scrollContainer.scrollLeft > 1,
175
- right:
176
- hasHorizontalScroll && scrollContainer.scrollLeft < maxScrollLeft - 1,
174
+ left: hasHorizontalScroll && content.scrollLeft > 1,
175
+ right: hasHorizontalScroll && content.scrollLeft < maxScrollLeft - 1,
177
176
  };
178
177
 
179
178
  setHorizontalScroll((current) =>
@@ -183,6 +182,54 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
183
182
  );
184
183
  }, []);
185
184
 
185
+ // A primitive signature of everything in the columns that can affect the
186
+ // measured layout, used as an effect dependency instead of the array itself.
187
+ const columnLayoutKey = useMemo(
188
+ () =>
189
+ wrapedColumns
190
+ .map(
191
+ (column, index) =>
192
+ `${column.key ?? column.dataIndex ?? index}:${
193
+ column.fixed ?? ''
194
+ }:${column.width ?? ''}`,
195
+ )
196
+ .join('|'),
197
+ [wrapedColumns],
198
+ );
199
+
200
+ // Keep the latest columns in a ref so that the measure callback stays stable:
201
+ // `wrapedColumns` is derived from `measuredColumnWidths`, so depending on it
202
+ // directly would recreate the callback (and the ResizeObserver) on every
203
+ // measurement.
204
+ const wrapedColumnsRef = useLatest(wrapedColumns);
205
+
206
+ const updateMeasuredColumnWidths = React.useCallback(() => {
207
+ const columns = wrapedColumnsRef.current;
208
+ if (!columns.some((column) => column.fixed)) return;
209
+
210
+ const colElements = tableRef.current?.querySelectorAll(
211
+ ':scope > colgroup > col',
212
+ );
213
+ if (!colElements || colElements.length !== columns.length) return;
214
+
215
+ // Round to whole pixels: sticky offsets do not need sub-pixel precision,
216
+ // and raw fractional widths would otherwise flip-flop (scrollbar showing /
217
+ // hiding, browser zoom) and keep re-triggering renders.
218
+ const nextWidths = Array.from(colElements, (column) =>
219
+ Math.round(column.getBoundingClientRect().width),
220
+ );
221
+ if (nextWidths.some((width) => !Number.isFinite(width) || width <= 0)) {
222
+ return;
223
+ }
224
+
225
+ setMeasuredColumnWidths((current) => {
226
+ const unchanged =
227
+ current?.length === nextWidths.length &&
228
+ current.every((width, index) => width === nextWidths[index]);
229
+ return unchanged ? current : nextWidths;
230
+ });
231
+ }, [wrapedColumnsRef]);
232
+
186
233
  useEffect(() => {
187
234
  if (prevFilterRecordsRef.current === filterRecords) return;
188
235
 
@@ -207,24 +254,43 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
207
254
  onChange,
208
255
  ]);
209
256
 
257
+ // Observers are attached once: both callbacks are referentially stable.
210
258
  useEffect(() => {
211
- updateHorizontalScroll();
212
-
213
- const wrapper = contentWrapperRef.current;
214
259
  const content = contentRef.current;
215
- if (!wrapper || !content) return undefined;
260
+ const tableElement = tableRef.current;
261
+ if (!content || !tableElement) return undefined;
262
+
263
+ const handleResize = () => {
264
+ updateHorizontalScroll();
265
+ updateMeasuredColumnWidths();
266
+ };
216
267
 
217
268
  if (typeof ResizeObserver === 'undefined') {
218
- window.addEventListener('resize', updateHorizontalScroll);
219
- return () => window.removeEventListener('resize', updateHorizontalScroll);
269
+ window.addEventListener('resize', handleResize);
270
+ return () => window.removeEventListener('resize', handleResize);
220
271
  }
221
272
 
222
- const resizeObserver = new ResizeObserver(updateHorizontalScroll);
223
- resizeObserver.observe(wrapper);
273
+ const resizeObserver = new ResizeObserver(handleResize);
224
274
  resizeObserver.observe(content);
275
+ resizeObserver.observe(tableElement);
225
276
 
226
277
  return () => resizeObserver.disconnect();
227
- }, [updateHorizontalScroll, wrapedColumns, pageData, scroll?.x]);
278
+ }, [updateHorizontalScroll, updateMeasuredColumnWidths]);
279
+
280
+ // Re-sync when something that can change the layout changes. `columnLayoutKey`
281
+ // is a primitive, so a measurement round-trip (which produces a new
282
+ // `wrapedColumns` array with identical layout config) does not retrigger it.
283
+ useEffect(() => {
284
+ updateHorizontalScroll();
285
+ updateMeasuredColumnWidths();
286
+ }, [
287
+ columnLayoutKey,
288
+ pageData,
289
+ scroll?.x,
290
+ scroll?.y,
291
+ updateHorizontalScroll,
292
+ updateMeasuredColumnWidths,
293
+ ]);
228
294
 
229
295
  const renderHeader = () => {
230
296
  return (
@@ -283,6 +349,7 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
283
349
  const tableProps = {
284
350
  style: {
285
351
  ...styles?.table,
352
+ minWidth: scroll?.x,
286
353
  tableLayout: pageData?.length ? tableLayout : undefined,
287
354
  },
288
355
  className: clsx(
@@ -302,7 +369,7 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
302
369
  rowKey,
303
370
  }}
304
371
  >
305
- <table {...tableProps}>
372
+ <table ref={tableRef} {...tableProps}>
306
373
  <ColGroup columns={wrapedColumns} />
307
374
  {renderTHeader()}
308
375
  {renderTBody()}
@@ -313,12 +380,10 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
313
380
 
314
381
  return (
315
382
  <div
316
- ref={contentWrapperRef}
317
383
  className={clsx(`${prefixCls}-content-wrapper`, {
318
384
  [`${prefixCls}-content-wrapper-scroll-left`]: horizontalScroll.left,
319
385
  [`${prefixCls}-content-wrapper-scroll-right`]: horizontalScroll.right,
320
386
  })}
321
- onScroll={updateHorizontalScroll}
322
387
  >
323
388
  <div
324
389
  ref={contentRef}
@@ -326,7 +391,7 @@ const Table = React.forwardRef<HTMLDivElement, TableProps>((baseprops, ref) => {
326
391
  [`${prefixCls}-${size}-size`]: size,
327
392
  [`${prefixCls}-fixed-header`]: scroll?.y,
328
393
  })}
329
- style={{ height: scroll?.y, width: scroll?.x }}
394
+ style={{ height: scroll?.y }}
330
395
  onScroll={updateHorizontalScroll}
331
396
  >
332
397
  {table}
@@ -1,11 +1,38 @@
1
1
  import { WrapedColumnProps } from '../interface';
2
2
 
3
- export function handleColumns(columns: Array<WrapedColumnProps>) {
3
+ const getColumnWidth = (
4
+ column: WrapedColumnProps,
5
+ index: number,
6
+ measuredColumnWidths?: number[],
7
+ ) => {
8
+ const measuredWidth = measuredColumnWidths?.[index];
9
+ if (Number.isFinite(measuredWidth) && measuredWidth && measuredWidth > 0) {
10
+ return measuredWidth;
11
+ }
12
+
13
+ if (typeof column.width === 'number') {
14
+ return column.width;
15
+ }
16
+
17
+ if (
18
+ typeof column.width === 'string' &&
19
+ /^\s*\d+(?:\.\d+)?px\s*$/.test(column.width)
20
+ ) {
21
+ return Number.parseFloat(column.width);
22
+ }
23
+
24
+ return 0;
25
+ };
26
+
27
+ export function handleColumns(
28
+ columns: Array<WrapedColumnProps>,
29
+ measuredColumnWidths?: number[],
30
+ ) {
4
31
  let leftWidthCount = 0;
5
32
  let rightWidthCount = 0;
6
33
 
7
34
  for (let i = 0; i < columns.length; i++) {
8
- const col = columns[i] || ({} as any);
35
+ const col = columns[i] || ({} as WrapedColumnProps);
9
36
  if (col.fixed === true || col.fixed === 'left') {
10
37
  col.fixed = 'left';
11
38
  col.style = { ...col.style, left: leftWidthCount };
@@ -14,20 +41,18 @@ export function handleColumns(columns: Array<WrapedColumnProps>) {
14
41
  if (!nextIsFixedLeft) {
15
42
  col.isFixedLeftLast = true;
16
43
  }
17
- leftWidthCount =
18
- leftWidthCount + (col.width ? parseFloat(col.width as string) : 0);
44
+ leftWidthCount += getColumnWidth(col, i, measuredColumnWidths);
19
45
  }
20
46
  }
21
47
 
22
48
  for (let j = columns.length - 1; j >= 0; j--) {
23
- const col = columns[j] || ({} as any);
49
+ const col = columns[j] || ({} as WrapedColumnProps);
24
50
  if (col.fixed === 'right') {
25
51
  col.style = { ...col.style, right: rightWidthCount };
26
52
  if (columns[j - 1]?.fixed !== 'right') {
27
53
  col.isFixedRightFirst = true;
28
54
  }
29
- rightWidthCount =
30
- rightWidthCount + (col.width ? parseFloat(col.width as string) : 0);
55
+ rightWidthCount += getColumnWidth(col, j, measuredColumnWidths);
31
56
  }
32
57
  }
33
58
  return columns;
package/src/version.ts CHANGED
@@ -4,7 +4,7 @@ declare global {
4
4
  }
5
5
  }
6
6
 
7
- export const version = "0.8.14";
7
+ export const version = "0.8.16";
8
8
 
9
9
  if (typeof window !== 'undefined') {
10
10
  window.__yee_c_version__ = version;