@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.
- package/dist/cjs/Progress/circle.js +1 -1
- package/dist/cjs/Progress/line.js +1 -1
- package/dist/cjs/Progress/progress.js +2 -0
- package/dist/cjs/Progress/steps.js +1 -1
- package/dist/cjs/Search/search.js +45 -16
- package/dist/cjs/Select/interface.d.ts +2 -1
- package/dist/cjs/Spin/demo/types.js +1 -1
- package/dist/cjs/Spin/indicator.d.ts +1 -1
- package/dist/cjs/Spin/indicator.js +144 -0
- package/dist/cjs/Spin/interface.d.ts +1 -1
- package/dist/cjs/Spin/style/index.less +86 -0
- package/dist/cjs/Table/demo/fixed.d.ts +3 -0
- package/dist/cjs/Table/demo/fixed.js +123 -0
- package/dist/cjs/Table/hooks/useColumns.d.ts +2 -1
- package/dist/cjs/Table/hooks/useColumns.js +4 -3
- package/dist/cjs/Table/style/index.less +23 -3
- package/dist/cjs/Table/table.js +67 -21
- package/dist/cjs/Table/util/index.d.ts +1 -1
- package/dist/cjs/Table/util/index.js +16 -3
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Progress/circle.js +2 -1
- package/dist/esm/Progress/line.js +2 -1
- package/dist/esm/Progress/progress.js +2 -0
- package/dist/esm/Progress/steps.js +6 -1
- package/dist/esm/Search/search.js +31 -7
- package/dist/esm/Select/interface.d.ts +2 -1
- package/dist/esm/Spin/demo/types.js +10 -7
- package/dist/esm/Spin/indicator.d.ts +1 -1
- package/dist/esm/Spin/indicator.js +137 -0
- package/dist/esm/Spin/interface.d.ts +1 -1
- package/dist/esm/Spin/style/index.less +86 -0
- package/dist/esm/Table/demo/fixed.d.ts +3 -0
- package/dist/esm/Table/demo/fixed.js +84 -0
- package/dist/esm/Table/hooks/useColumns.d.ts +2 -1
- package/dist/esm/Table/hooks/useColumns.js +4 -3
- package/dist/esm/Table/style/index.less +23 -3
- package/dist/esm/Table/table.js +85 -26
- package/dist/esm/Table/util/index.d.ts +1 -1
- package/dist/esm/Table/util/index.js +16 -3
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +1 -1
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Progress/circle.tsx +1 -1
- package/src/Progress/line.tsx +1 -1
- package/src/Progress/progress.tsx +2 -0
- package/src/Progress/steps.tsx +3 -1
- package/src/Search/search.tsx +33 -4
- package/src/Select/interface.ts +2 -1
- package/src/Spin/demo/types.tsx +18 -3
- package/src/Spin/index.en-US.md +5 -2
- package/src/Spin/index.zh-CN.md +5 -2
- package/src/Spin/indicator.tsx +165 -1
- package/src/Spin/interface.ts +1 -1
- package/src/Spin/style/index.less +86 -0
- package/src/Table/demo/fixed.tsx +92 -0
- package/src/Table/hooks/useColumns.ts +4 -2
- package/src/Table/index.en-US.md +1 -0
- package/src/Table/index.zh-CN.md +1 -0
- package/src/Table/style/index.less +23 -3
- package/src/Table/table.tsx +88 -23
- package/src/Table/util/index.ts +32 -7
- 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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/src/Table/table.tsx
CHANGED
|
@@ -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 (!
|
|
169
|
+
if (!content) return;
|
|
167
170
|
|
|
168
|
-
const
|
|
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 &&
|
|
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
|
-
|
|
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',
|
|
219
|
-
return () => window.removeEventListener('resize',
|
|
269
|
+
window.addEventListener('resize', handleResize);
|
|
270
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
220
271
|
}
|
|
221
272
|
|
|
222
|
-
const resizeObserver = new ResizeObserver(
|
|
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,
|
|
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
|
|
394
|
+
style={{ height: scroll?.y }}
|
|
330
395
|
onScroll={updateHorizontalScroll}
|
|
331
396
|
>
|
|
332
397
|
{table}
|
package/src/Table/util/index.ts
CHANGED
|
@@ -1,11 +1,38 @@
|
|
|
1
1
|
import { WrapedColumnProps } from '../interface';
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
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
|
|
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;
|