@rainbow-oh/yee-c 0.8.15 → 0.8.17

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 (56) hide show
  1. package/dist/cjs/Search/search.js +1 -1
  2. package/dist/cjs/Table/demo/fixed.d.ts +3 -0
  3. package/dist/cjs/Table/demo/fixed.js +123 -0
  4. package/dist/cjs/Table/hooks/useColumns.d.ts +2 -1
  5. package/dist/cjs/Table/hooks/useColumns.js +4 -3
  6. package/dist/cjs/Table/style/index.less +23 -3
  7. package/dist/cjs/Table/table.js +67 -21
  8. package/dist/cjs/Table/util/index.d.ts +1 -1
  9. package/dist/cjs/Table/util/index.js +16 -3
  10. package/dist/cjs/Tree/interface.d.ts +16 -0
  11. package/dist/cjs/Tree/tree-node.js +7 -2
  12. package/dist/cjs/Tree/tree.d.ts +2 -1
  13. package/dist/cjs/Tree/tree.js +6 -2
  14. package/dist/cjs/Tree/utils/tree-tools.d.ts +1 -0
  15. package/dist/cjs/Tree/utils/tree-tools.js +3 -1
  16. package/dist/cjs/style/themes.css +1 -1
  17. package/dist/cjs/style/variables.css +1 -1
  18. package/dist/cjs/version.d.ts +1 -1
  19. package/dist/cjs/version.js +1 -1
  20. package/dist/esm/Search/search.js +1 -1
  21. package/dist/esm/Table/demo/fixed.d.ts +3 -0
  22. package/dist/esm/Table/demo/fixed.js +84 -0
  23. package/dist/esm/Table/hooks/useColumns.d.ts +2 -1
  24. package/dist/esm/Table/hooks/useColumns.js +4 -3
  25. package/dist/esm/Table/style/index.less +23 -3
  26. package/dist/esm/Table/table.js +85 -26
  27. package/dist/esm/Table/util/index.d.ts +1 -1
  28. package/dist/esm/Table/util/index.js +16 -3
  29. package/dist/esm/Tree/interface.d.ts +16 -0
  30. package/dist/esm/Tree/tree-node.js +12 -2
  31. package/dist/esm/Tree/tree.d.ts +2 -1
  32. package/dist/esm/Tree/tree.js +15 -13
  33. package/dist/esm/Tree/utils/tree-tools.d.ts +1 -0
  34. package/dist/esm/Tree/utils/tree-tools.js +4 -1
  35. package/dist/esm/style/themes.css +1 -1
  36. package/dist/esm/style/variables.css +1 -1
  37. package/dist/esm/version.d.ts +1 -1
  38. package/dist/esm/version.js +1 -1
  39. package/dist/umd/yee-c.min.css +1 -1
  40. package/dist/umd/yee-c.min.js +1 -1
  41. package/package.json +1 -1
  42. package/src/Search/search.tsx +1 -1
  43. package/src/Table/demo/fixed.tsx +92 -0
  44. package/src/Table/hooks/useColumns.ts +4 -2
  45. package/src/Table/index.en-US.md +1 -0
  46. package/src/Table/index.zh-CN.md +1 -0
  47. package/src/Table/style/index.less +23 -3
  48. package/src/Table/table.tsx +88 -23
  49. package/src/Table/util/index.ts +32 -7
  50. package/src/Tree/index.en-US.md +20 -2
  51. package/src/Tree/index.zh-CN.md +20 -2
  52. package/src/Tree/interface.ts +16 -1
  53. package/src/Tree/tree-node.tsx +15 -2
  54. package/src/Tree/tree.tsx +6 -2
  55. package/src/Tree/utils/tree-tools.ts +4 -1
  56. package/src/version.ts +1 -1
@@ -0,0 +1,84 @@
1
+ import { Table } from "../..";
2
+ import React from 'react';
3
+ var columns = [{
4
+ title: 'Name',
5
+ dataIndex: 'name',
6
+ key: 'name',
7
+ fixed: 'left',
8
+ width: 140
9
+ }, {
10
+ title: 'Age',
11
+ dataIndex: 'age',
12
+ key: 'age',
13
+ fixed: 'left',
14
+ width: 100
15
+ }, {
16
+ title: 'Address',
17
+ dataIndex: 'address',
18
+ key: 'address',
19
+ width: 240
20
+ }, {
21
+ title: 'Company',
22
+ dataIndex: 'company',
23
+ key: 'company',
24
+ width: 180
25
+ }, {
26
+ title: 'Department',
27
+ dataIndex: 'department',
28
+ key: 'department',
29
+ width: 180
30
+ }, {
31
+ title: 'Email',
32
+ dataIndex: 'email',
33
+ key: 'email',
34
+ width: 240
35
+ }, {
36
+ title: 'Action',
37
+ key: 'action',
38
+ fixed: 'right',
39
+ width: 100,
40
+ render: function render(record) {
41
+ return /*#__PURE__*/React.createElement("a", {
42
+ onClick: function onClick() {
43
+ return console.log(record);
44
+ }
45
+ }, "View");
46
+ }
47
+ }];
48
+ var dataSource = [{
49
+ key: '1',
50
+ name: 'John Brown',
51
+ age: 32,
52
+ address: 'New York No. 1 Lake Park',
53
+ company: 'Acme Inc.',
54
+ department: 'Engineering',
55
+ email: 'john.brown@example.com'
56
+ }, {
57
+ key: '2',
58
+ name: 'Jim Green',
59
+ age: 42,
60
+ address: 'London No. 1 Lake Park',
61
+ company: 'Globex',
62
+ department: 'Marketing',
63
+ email: 'jim.green@example.com'
64
+ }, {
65
+ key: '3',
66
+ name: 'Joe Black',
67
+ age: 28,
68
+ address: 'Sidney No. 1 Lake Park',
69
+ company: 'Initech',
70
+ department: 'Product',
71
+ email: 'joe.black@example.com'
72
+ }];
73
+ export default (function () {
74
+ return /*#__PURE__*/React.createElement(Table, {
75
+ columns: columns,
76
+ dataSource: dataSource,
77
+ rowKey: "key",
78
+ pagination: false,
79
+ scroll: {
80
+ x: 1180
81
+ },
82
+ tableLayout: "fixed"
83
+ });
84
+ });
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
2
  import type { ColumnProps, ExpandableType, RowSelectionType, WrapedColumnProps } from '../interface';
3
- export default function useColumns({ children, columns, rowSelection, expandable, }: {
3
+ export default function useColumns({ children, columns, rowSelection, expandable, measuredColumnWidths, }: {
4
4
  children?: React.ReactElement<ColumnProps> | React.ReactElement<ColumnProps>[];
5
5
  columns: ColumnProps[];
6
6
  rowSelection?: RowSelectionType;
7
7
  expandable?: ExpandableType;
8
+ measuredColumnWidths?: number[];
8
9
  }): {
9
10
  wrapedColumns: WrapedColumnProps[];
10
11
  headerRows: import("../interface").HeaderCell[][];
@@ -21,7 +21,8 @@ export default function useColumns(_ref) {
21
21
  var children = _ref.children,
22
22
  columns = _ref.columns,
23
23
  rowSelection = _ref.rowSelection,
24
- expandable = _ref.expandable;
24
+ expandable = _ref.expandable,
25
+ measuredColumnWidths = _ref.measuredColumnWidths;
25
26
  var childColumns = useMemo(function () {
26
27
  return children ? getColumnsFromChild(children) : null;
27
28
  }, [children]);
@@ -33,13 +34,13 @@ export default function useColumns(_ref) {
33
34
  var base = deepClone(childColumns || columns || []) || [];
34
35
  var tree = injectSelectionExpand(base, rowSelection, expandable);
35
36
  var leaves = flattenLeafColumns(tree);
36
- var wraped = handleColumns(leaves);
37
+ var wraped = handleColumns(leaves, measuredColumnWidths);
37
38
  var rows = parseHeaderRows(tree, wraped);
38
39
  return {
39
40
  wrapedColumns: wraped,
40
41
  headerRows: rows
41
42
  };
42
- }, [childColumns, columns, rowSelection, expandable]),
43
+ }, [childColumns, columns, rowSelection, expandable, measuredColumnWidths]),
43
44
  wrapedColumns = _useMemo.wrapedColumns,
44
45
  headerRows = _useMemo.headerRows;
45
46
  return {
@@ -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
  }
@@ -27,6 +27,7 @@ import TBody from "./tbody";
27
27
  import TFooter from "./tfooter";
28
28
  import THeader from "./theader";
29
29
  import { GlobalContext } from "../Config-Provider";
30
+ import useLatest from "../hooks/useLatest";
30
31
  import mergeContextToProps from "../utils/mergeContextToProps";
31
32
  import omit from "../utils/omit";
32
33
  import { pickDataAttrs } from "../utils/types";
@@ -73,6 +74,10 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
73
74
  onChange = props.onChange,
74
75
  rest = _objectWithoutProperties(props, _excluded);
75
76
  var dataAttrs = pickDataAttrs(rest);
77
+ var _React$useState = React.useState(),
78
+ _React$useState2 = _slicedToArray(_React$useState, 2),
79
+ measuredColumnWidths = _React$useState2[0],
80
+ setMeasuredColumnWidths = _React$useState2[1];
76
81
  var getRowKey = React.useCallback(function (record) {
77
82
  var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : rowKey;
78
83
  return typeof key === 'function' ? key(record) : record[key];
@@ -86,7 +91,8 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
86
91
  children: children,
87
92
  columns: propColumns,
88
93
  expandable: expandable,
89
- rowSelection: rowSelection
94
+ rowSelection: rowSelection,
95
+ measuredColumnWidths: measuredColumnWidths
90
96
  }),
91
97
  wrapedColumns = _useColumns.wrapedColumns,
92
98
  headerRows = _useColumns.headerRows;
@@ -165,30 +171,70 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
165
171
 
166
172
  // Track filter changes to emit onChange after filtered data is recalculated
167
173
  var prevFilterRecordsRef = useRef(filterRecords);
168
- var contentWrapperRef = useRef(null);
169
174
  var contentRef = useRef(null);
170
- var _React$useState = React.useState({
175
+ var tableRef = useRef(null);
176
+ var _React$useState3 = React.useState({
171
177
  left: false,
172
178
  right: false
173
179
  }),
174
- _React$useState2 = _slicedToArray(_React$useState, 2),
175
- horizontalScroll = _React$useState2[0],
176
- setHorizontalScroll = _React$useState2[1];
180
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
181
+ horizontalScroll = _React$useState4[0],
182
+ setHorizontalScroll = _React$useState4[1];
177
183
  var updateHorizontalScroll = React.useCallback(function () {
178
- var wrapper = contentWrapperRef.current;
179
184
  var content = contentRef.current;
180
- if (!wrapper || !content) return;
181
- var scrollContainer = content.scrollWidth - content.clientWidth > 1 ? content : wrapper;
182
- var maxScrollLeft = scrollContainer.scrollWidth - scrollContainer.clientWidth;
185
+ if (!content) return;
186
+ var maxScrollLeft = content.scrollWidth - content.clientWidth;
183
187
  var hasHorizontalScroll = maxScrollLeft > 1;
184
188
  var next = {
185
- left: hasHorizontalScroll && scrollContainer.scrollLeft > 1,
186
- right: hasHorizontalScroll && scrollContainer.scrollLeft < maxScrollLeft - 1
189
+ left: hasHorizontalScroll && content.scrollLeft > 1,
190
+ right: hasHorizontalScroll && content.scrollLeft < maxScrollLeft - 1
187
191
  };
188
192
  setHorizontalScroll(function (current) {
189
193
  return current.left === next.left && current.right === next.right ? current : next;
190
194
  });
191
195
  }, []);
196
+
197
+ // A primitive signature of everything in the columns that can affect the
198
+ // measured layout, used as an effect dependency instead of the array itself.
199
+ var columnLayoutKey = useMemo(function () {
200
+ return wrapedColumns.map(function (column, index) {
201
+ var _ref2, _column$key, _column$fixed, _column$width;
202
+ return "".concat((_ref2 = (_column$key = column.key) !== null && _column$key !== void 0 ? _column$key : column.dataIndex) !== null && _ref2 !== void 0 ? _ref2 : index, ":").concat((_column$fixed = column.fixed) !== null && _column$fixed !== void 0 ? _column$fixed : '', ":").concat((_column$width = column.width) !== null && _column$width !== void 0 ? _column$width : '');
203
+ }).join('|');
204
+ }, [wrapedColumns]);
205
+
206
+ // Keep the latest columns in a ref so that the measure callback stays stable:
207
+ // `wrapedColumns` is derived from `measuredColumnWidths`, so depending on it
208
+ // directly would recreate the callback (and the ResizeObserver) on every
209
+ // measurement.
210
+ var wrapedColumnsRef = useLatest(wrapedColumns);
211
+ var updateMeasuredColumnWidths = React.useCallback(function () {
212
+ var _tableRef$current;
213
+ var columns = wrapedColumnsRef.current;
214
+ if (!columns.some(function (column) {
215
+ return column.fixed;
216
+ })) return;
217
+ var colElements = (_tableRef$current = tableRef.current) === null || _tableRef$current === void 0 ? void 0 : _tableRef$current.querySelectorAll(':scope > colgroup > col');
218
+ if (!colElements || colElements.length !== columns.length) return;
219
+
220
+ // Round to whole pixels: sticky offsets do not need sub-pixel precision,
221
+ // and raw fractional widths would otherwise flip-flop (scrollbar showing /
222
+ // hiding, browser zoom) and keep re-triggering renders.
223
+ var nextWidths = Array.from(colElements, function (column) {
224
+ return Math.round(column.getBoundingClientRect().width);
225
+ });
226
+ if (nextWidths.some(function (width) {
227
+ return !Number.isFinite(width) || width <= 0;
228
+ })) {
229
+ return;
230
+ }
231
+ setMeasuredColumnWidths(function (current) {
232
+ var unchanged = (current === null || current === void 0 ? void 0 : current.length) === nextWidths.length && current.every(function (width, index) {
233
+ return width === nextWidths[index];
234
+ });
235
+ return unchanged ? current : nextWidths;
236
+ });
237
+ }, [wrapedColumnsRef]);
192
238
  useEffect(function () {
193
239
  if (prevFilterRecordsRef.current === filterRecords) return;
194
240
  prevFilterRecordsRef.current = filterRecords;
@@ -204,24 +250,37 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
204
250
  action: 'filter'
205
251
  });
206
252
  }, [filterRecords, filters, sortedData, pagination, current, pageSize, sorters, onChange]);
253
+
254
+ // Observers are attached once: both callbacks are referentially stable.
207
255
  useEffect(function () {
208
- updateHorizontalScroll();
209
- var wrapper = contentWrapperRef.current;
210
256
  var content = contentRef.current;
211
- if (!wrapper || !content) return undefined;
257
+ var tableElement = tableRef.current;
258
+ if (!content || !tableElement) return undefined;
259
+ var handleResize = function handleResize() {
260
+ updateHorizontalScroll();
261
+ updateMeasuredColumnWidths();
262
+ };
212
263
  if (typeof ResizeObserver === 'undefined') {
213
- window.addEventListener('resize', updateHorizontalScroll);
264
+ window.addEventListener('resize', handleResize);
214
265
  return function () {
215
- return window.removeEventListener('resize', updateHorizontalScroll);
266
+ return window.removeEventListener('resize', handleResize);
216
267
  };
217
268
  }
218
- var resizeObserver = new ResizeObserver(updateHorizontalScroll);
219
- resizeObserver.observe(wrapper);
269
+ var resizeObserver = new ResizeObserver(handleResize);
220
270
  resizeObserver.observe(content);
271
+ resizeObserver.observe(tableElement);
221
272
  return function () {
222
273
  return resizeObserver.disconnect();
223
274
  };
224
- }, [updateHorizontalScroll, wrapedColumns, pageData, scroll === null || scroll === void 0 ? void 0 : scroll.x]);
275
+ }, [updateHorizontalScroll, updateMeasuredColumnWidths]);
276
+
277
+ // Re-sync when something that can change the layout changes. `columnLayoutKey`
278
+ // is a primitive, so a measurement round-trip (which produces a new
279
+ // `wrapedColumns` array with identical layout config) does not retrigger it.
280
+ useEffect(function () {
281
+ updateHorizontalScroll();
282
+ updateMeasuredColumnWidths();
283
+ }, [columnLayoutKey, pageData, scroll === null || scroll === void 0 ? void 0 : scroll.x, scroll === null || scroll === void 0 ? void 0 : scroll.y, updateHorizontalScroll, updateMeasuredColumnWidths]);
225
284
  var renderHeader = function renderHeader() {
226
285
  return /*#__PURE__*/React.createElement(Header, {
227
286
  prefixCls: prefixCls,
@@ -269,6 +328,7 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
269
328
  var renderTable = function renderTable() {
270
329
  var tableProps = {
271
330
  style: _objectSpread(_objectSpread({}, styles === null || styles === void 0 ? void 0 : styles.table), {}, {
331
+ minWidth: scroll === null || scroll === void 0 ? void 0 : scroll.x,
272
332
  tableLayout: pageData !== null && pageData !== void 0 && pageData.length ? tableLayout : undefined
273
333
  }),
274
334
  className: clsx(_defineProperty({}, "".concat(prefixCls, "-bordered"), bordered), classNames === null || classNames === void 0 ? void 0 : classNames.table)
@@ -283,19 +343,18 @@ var Table = /*#__PURE__*/React.forwardRef(function (baseprops, ref) {
283
343
  locale: locale,
284
344
  rowKey: rowKey
285
345
  }
286
- }, /*#__PURE__*/React.createElement("table", tableProps, /*#__PURE__*/React.createElement(ColGroup, {
346
+ }, /*#__PURE__*/React.createElement("table", _extends({
347
+ ref: tableRef
348
+ }, tableProps), /*#__PURE__*/React.createElement(ColGroup, {
287
349
  columns: wrapedColumns
288
350
  }), renderTHeader(), renderTBody(), renderTFooter()));
289
351
  return /*#__PURE__*/React.createElement("div", {
290
- ref: contentWrapperRef,
291
- className: clsx("".concat(prefixCls, "-content-wrapper"), _defineProperty(_defineProperty({}, "".concat(prefixCls, "-content-wrapper-scroll-left"), horizontalScroll.left), "".concat(prefixCls, "-content-wrapper-scroll-right"), horizontalScroll.right)),
292
- onScroll: updateHorizontalScroll
352
+ className: clsx("".concat(prefixCls, "-content-wrapper"), _defineProperty(_defineProperty({}, "".concat(prefixCls, "-content-wrapper-scroll-left"), horizontalScroll.left), "".concat(prefixCls, "-content-wrapper-scroll-right"), horizontalScroll.right))
293
353
  }, /*#__PURE__*/React.createElement("div", {
294
354
  ref: contentRef,
295
355
  className: clsx("".concat(prefixCls, "-content"), _defineProperty(_defineProperty({}, "".concat(prefixCls, "-").concat(size, "-size"), size), "".concat(prefixCls, "-fixed-header"), scroll === null || scroll === void 0 ? void 0 : scroll.y)),
296
356
  style: {
297
- height: scroll === null || scroll === void 0 ? void 0 : scroll.y,
298
- width: scroll === null || scroll === void 0 ? void 0 : scroll.x
357
+ height: scroll === null || scroll === void 0 ? void 0 : scroll.y
299
358
  },
300
359
  onScroll: updateHorizontalScroll
301
360
  }, table));
@@ -1,2 +1,2 @@
1
1
  import { WrapedColumnProps } from '../interface';
2
- export declare function handleColumns(columns: Array<WrapedColumnProps>): WrapedColumnProps[];
2
+ export declare function handleColumns(columns: Array<WrapedColumnProps>, measuredColumnWidths?: number[]): WrapedColumnProps[];
@@ -4,7 +4,20 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
- export function handleColumns(columns) {
7
+ var getColumnWidth = function getColumnWidth(column, index, measuredColumnWidths) {
8
+ var measuredWidth = measuredColumnWidths === null || measuredColumnWidths === void 0 ? void 0 : measuredColumnWidths[index];
9
+ if (Number.isFinite(measuredWidth) && measuredWidth && measuredWidth > 0) {
10
+ return measuredWidth;
11
+ }
12
+ if (typeof column.width === 'number') {
13
+ return column.width;
14
+ }
15
+ if (typeof column.width === 'string' && /^\s*\d+(?:\.\d+)?px\s*$/.test(column.width)) {
16
+ return Number.parseFloat(column.width);
17
+ }
18
+ return 0;
19
+ };
20
+ export function handleColumns(columns, measuredColumnWidths) {
8
21
  var leftWidthCount = 0;
9
22
  var rightWidthCount = 0;
10
23
  for (var i = 0; i < columns.length; i++) {
@@ -20,7 +33,7 @@ export function handleColumns(columns) {
20
33
  if (!nextIsFixedLeft) {
21
34
  col.isFixedLeftLast = true;
22
35
  }
23
- leftWidthCount = leftWidthCount + (col.width ? parseFloat(col.width) : 0);
36
+ leftWidthCount += getColumnWidth(col, i, measuredColumnWidths);
24
37
  }
25
38
  }
26
39
  for (var j = columns.length - 1; j >= 0; j--) {
@@ -33,7 +46,7 @@ export function handleColumns(columns) {
33
46
  if (((_columns2 = columns[j - 1]) === null || _columns2 === void 0 ? void 0 : _columns2.fixed) !== 'right') {
34
47
  _col.isFixedRightFirst = true;
35
48
  }
36
- rightWidthCount = rightWidthCount + (_col.width ? parseFloat(_col.width) : 0);
49
+ rightWidthCount += getColumnWidth(_col, j, measuredColumnWidths);
37
50
  }
38
51
  }
39
52
  return columns;
@@ -61,6 +61,13 @@ export type TreeNode<T> = {
61
61
  * All descendant uids (collected bottom-up). Used for check/uncheck propagation.
62
62
  */
63
63
  childUids?: Array<string>;
64
+ /**
65
+ * Extra content rendered after the label (e.g. tags, badges, action buttons).
66
+ * Only takes effect when `labelRender` is NOT provided at the Tree level.
67
+ * When `labelRender` is present, access this value via `node.extra` in your
68
+ * custom render function.
69
+ */
70
+ extra?: React.ReactNode | ((node: T) => React.ReactNode);
64
71
  /**
65
72
  * Original data
66
73
  */
@@ -157,6 +164,14 @@ export interface TreeProps<T> extends DataAttributeProps {
157
164
  * @default false
158
165
  */
159
166
  multiple?: boolean;
167
+ /**
168
+ * Custom render function for node label.
169
+ * When provided, takes full control of the label area rendering.
170
+ * The node's `extra` will NOT be appended automatically in this case;
171
+ * access it via `node.extra` if you need it in your custom render.
172
+ * The original `label` string is still used for `title` attribute fallback.
173
+ */
174
+ labelRender?: (node: TreeNode<T>) => React.ReactNode;
160
175
  /**
161
176
  * Customize node key, title, children field names
162
177
  */
@@ -164,6 +179,7 @@ export interface TreeProps<T> extends DataAttributeProps {
164
179
  key?: keyof T;
165
180
  label?: keyof T;
166
181
  children?: keyof T;
182
+ extra?: keyof T;
167
183
  };
168
184
  /**
169
185
  * Asynchronous data loading
@@ -21,6 +21,7 @@ var Node = function Node(props) {
21
21
  disabled = node.disabled,
22
22
  depth = node.depth,
23
23
  icon = node.icon,
24
+ extra = node.extra,
24
25
  original = node.original,
25
26
  lines = node.lines;
26
27
  var _useContext = useContext(TreeContext),
@@ -34,6 +35,7 @@ var Node = function Node(props) {
34
35
  indeterminateUids = _useContext.indeterminateUids,
35
36
  expandedUids = _useContext.expandedUids,
36
37
  switcherIcon = _useContext.switcherIcon,
38
+ labelRender = _useContext.labelRender,
37
39
  draggable = _useContext.draggable,
38
40
  draggingUid = _useContext.draggingUid,
39
41
  dropState = _useContext.dropState,
@@ -86,6 +88,12 @@ var Node = function Node(props) {
86
88
  var _title = title || (typeof label === 'string' ? label : undefined);
87
89
  var mergedIcon = icon || contextIcon;
88
90
  var _icon = typeof mergedIcon === 'function' ? mergedIcon(original) : mergedIcon;
91
+
92
+ // labelRender takes full control of the label content when provided
93
+ var content = labelRender ? labelRender(node) : label;
94
+
95
+ // extra: appended after the label content (only when labelRender is NOT used)
96
+ var _extra = !labelRender && extra ? typeof extra === 'function' ? extra(original) : extra : null;
89
97
  return /*#__PURE__*/React.createElement(Button, {
90
98
  className: clsx("".concat(prefixCls, "-node-label"), _defineProperty({}, "".concat(prefixCls, "-node-label-selected"), selected)),
91
99
  size: "small",
@@ -95,7 +103,9 @@ var Node = function Node(props) {
95
103
  onClick: disabled ? undefined : function () {
96
104
  return onSelect(uid);
97
105
  }
98
- }, label);
106
+ }, content, _extra && /*#__PURE__*/React.createElement("span", {
107
+ className: "".concat(prefixCls, "-node-extra")
108
+ }, _extra));
99
109
  };
100
110
  var renderEmptyNodes = function renderEmptyNodes(depth) {
101
111
  var temp = new Array(depth).fill(0);
@@ -111,7 +121,7 @@ var Node = function Node(props) {
111
121
  return /*#__PURE__*/React.createElement("span", {
112
122
  "aria-hidden": "true",
113
123
  className: "".concat(prefixCls, "-node-indent"),
114
- key: index
124
+ key: "node-empty-".concat(index)
115
125
  });
116
126
  });
117
127
  };
@@ -1,5 +1,5 @@
1
1
  import React, { ChangeEvent } from 'react';
2
- import type { DragPosition, TreeProps } from './interface';
2
+ import type { DragPosition, TreeNode, TreeProps } from './interface';
3
3
  import './style/index.less';
4
4
  type DropState = {
5
5
  uid: string;
@@ -12,6 +12,7 @@ export declare const TreeContext: React.Context<{
12
12
  icon?: React.ReactNode | ((props: any) => React.ReactNode);
13
13
  showLine?: boolean | undefined;
14
14
  switcherIcon?: [React.ReactNode, React.ReactNode] | undefined;
15
+ labelRender?: ((node: TreeNode<any>) => React.ReactNode) | undefined;
15
16
  selectedUids: Set<string>;
16
17
  checkedUids: Set<string>;
17
18
  indeterminateUids: Set<string>;
@@ -1,5 +1,5 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["prefixCls", "className", "style", "dataSource", "fieldNames", "defaultExpandAll", "expandedKeys", "defaultExpandedKeys", "selectedKeys", "defaultSelectedKeys", "checkedKeys", "defaultCheckedKeys", "checkable", "multiple", "showIcon", "icon", "showLine", "switcherIcon", "draggable", "allowDrop", "onDrop", "onSelect", "onCheck", "onExpand", "virtual", "height", "itemHeight"];
2
+ var _excluded = ["prefixCls", "className", "style", "dataSource", "fieldNames", "defaultExpandAll", "expandedKeys", "defaultExpandedKeys", "selectedKeys", "defaultSelectedKeys", "checkedKeys", "defaultCheckedKeys", "checkable", "multiple", "showIcon", "icon", "showLine", "switcherIcon", "draggable", "allowDrop", "onDrop", "onSelect", "onCheck", "onExpand", "labelRender", "virtual", "height", "itemHeight"];
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
5
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -134,8 +134,8 @@ function uidsToKeys(uids, map) {
134
134
  try {
135
135
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
136
136
  var _uid = _step2.value;
137
- var node = map.get(_uid);
138
- if (node) keys.push(node.key);
137
+ var _node = map.get(_uid);
138
+ if (_node) keys.push(_node.key);
139
139
  }
140
140
  } catch (err) {
141
141
  _iterator2.e(err);
@@ -210,6 +210,7 @@ var Tree = function Tree(baseprops) {
210
210
  onSelect = props.onSelect,
211
211
  onCheck = props.onCheck,
212
212
  onExpand = props.onExpand,
213
+ labelRender = props.labelRender,
213
214
  _props$virtual = props.virtual,
214
215
  virtual = _props$virtual === void 0 ? false : _props$virtual,
215
216
  height = props.height,
@@ -570,6 +571,7 @@ var Tree = function Tree(baseprops) {
570
571
  icon: icon,
571
572
  showLine: showLine,
572
573
  switcherIcon: switcherIcon,
574
+ labelRender: labelRender,
573
575
  selectedUids: selectedUidSet,
574
576
  checkedUids: checkedUidSet,
575
577
  indeterminateUids: indeterminateUidSet,
@@ -585,7 +587,7 @@ var Tree = function Tree(baseprops) {
585
587
  onNodeDragLeave: handleDragLeave,
586
588
  onNodeDrop: handleDrop
587
589
  };
588
- }, [prefixCls, checkable, showIcon, icon, showLine, switcherIcon, selectedUidSet, checkedUidSet, indeterminateUidSet, expandedUidSet, draggable, draggingUid, dropState,
590
+ }, [prefixCls, checkable, showIcon, icon, showLine, switcherIcon, labelRender, selectedUidSet, checkedUidSet, indeterminateUidSet, expandedUidSet, draggable, draggingUid, dropState,
589
591
  // handlers are stable (useEvent), but listed for correctness
590
592
  handleCheck, handleSelect, handleExpand, handleDragStart, handleDragOver, handleDragLeave, handleDrop]);
591
593
 
@@ -652,8 +654,8 @@ var Tree = function Tree(baseprops) {
652
654
  _step9;
653
655
  try {
654
656
  for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
655
- var node = _step9.value;
656
- if (node.depth === 0) {
657
+ var _node2 = _step9.value;
658
+ if (_node2.depth === 0) {
657
659
  // Root nodes are always visible, render directly without animation
658
660
  if (currentGroup) {
659
661
  segments.push(_objectSpread({
@@ -663,12 +665,12 @@ var Tree = function Tree(baseprops) {
663
665
  }
664
666
  segments.push({
665
667
  type: 'node',
666
- node: node
668
+ node: _node2
667
669
  });
668
670
  } else {
669
671
  // Non-root: group consecutive children under the same parent
670
- if (currentGroup && currentGroup.pUid === node.pUid) {
671
- currentGroup.nodes.push(node);
672
+ if (currentGroup && currentGroup.pUid === _node2.pUid) {
673
+ currentGroup.nodes.push(_node2);
672
674
  } else {
673
675
  if (currentGroup) {
674
676
  segments.push(_objectSpread({
@@ -676,8 +678,8 @@ var Tree = function Tree(baseprops) {
676
678
  }, currentGroup));
677
679
  }
678
680
  currentGroup = {
679
- pUid: node.pUid,
680
- nodes: [node]
681
+ pUid: _node2.pUid,
682
+ nodes: [_node2]
681
683
  };
682
684
  }
683
685
  }
@@ -701,7 +703,7 @@ var Tree = function Tree(baseprops) {
701
703
  value: contextValue
702
704
  }, /*#__PURE__*/React.createElement(AnimatePresence, {
703
705
  initial: false
704
- }, segments.map(function (segment) {
706
+ }, segments.map(function (segment, index) {
705
707
  if (segment.type === 'node') {
706
708
  return /*#__PURE__*/React.createElement(TreeNodeComp, {
707
709
  node: segment.node,
@@ -712,7 +714,7 @@ var Tree = function Tree(baseprops) {
712
714
  // Replacing this tree after dragStart removes the browser's drag
713
715
  // source and cancels the drag before dragOver/drop can fire.
714
716
  return /*#__PURE__*/React.createElement(motion.div, {
715
- key: segment.pUid + '\x01children',
717
+ key: segment.pUid + index + '\x01children',
716
718
  initial: {
717
719
  height: 0,
718
720
  opacity: 0
@@ -49,6 +49,7 @@ export declare function tree2array<T extends Record<string, unknown>>(tree: T |
49
49
  key: keyof T;
50
50
  label: keyof T;
51
51
  children: keyof T;
52
+ extra?: keyof T;
52
53
  }): [TreeNode<T>[], Map<string, TreeNode<T>>];
53
54
  /**
54
55
  * Check whether array `a` contains every element in `b`.
@@ -172,7 +172,8 @@ export function tree2array(tree, fieldNames) {
172
172
  var map = new Map();
173
173
  var key = fieldNames.key,
174
174
  label = fieldNames.label,
175
- children = fieldNames.children;
175
+ children = fieldNames.children,
176
+ extra = fieldNames.extra;
176
177
 
177
178
  /**
178
179
  * Walk returns the list of descendant uids so the parent can collect them
@@ -190,6 +191,7 @@ export function tree2array(tree, fieldNames) {
190
191
  var rawKey = node[key];
191
192
  var _label = node[label];
192
193
  var _children = node[children];
194
+ var _extra = extra ? node[extra] : node.extra;
193
195
  var nextPath = [].concat(_toConsumableArray(path), [rawKey]);
194
196
  var uid = pUid ? "".concat(pUid, "\0").concat(String(rawKey)) : String(rawKey);
195
197
  var isParent = Array.isArray(_children) && _children.length > 0;
@@ -200,6 +202,7 @@ export function tree2array(tree, fieldNames) {
200
202
  key: rawKey,
201
203
  label: _label,
202
204
  title: node.title,
205
+ extra: _extra,
203
206
  path: path,
204
207
  pUid: pUid,
205
208
  depth: depth,
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * @rainbow-oh/yee-c CSS Variables
3
3
  * Auto-generated, do not edit manually
4
- * Generated on 2026-07-31T06:58:34.574Z
4
+ * Generated on 2026-08-05T09:43:58.935Z
5
5
  */
6
6
 
7
7
  /* ========== color.blue.css ========== */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * @rainbow-oh/yee-c CSS Variables
3
3
  * Auto-generated, do not edit manually
4
- * Generated on 2026-07-31T06:58:34.574Z
4
+ * Generated on 2026-08-05T09:43:58.935Z
5
5
  */
6
6
 
7
7
  /* ========== color.css ========== */