@expcat/tigercat-react 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import { useState, useEffect, useMemo, useCallback, Fragment } from 'react';
2
- import { getSpinnerSVG, getFixedColumnOffsets, filterData, sortData, paginateData, getRowKey, calculatePagination, getTableHeaderClasses, getExpandCellClasses, getCheckboxCellClasses, classNames, getTableHeaderCellClasses, tableEmptyStateClasses, getTableCellClasses, getTableRowClasses, expandedRowContentClasses, getSimplePaginationContainerClasses, getSimplePaginationTotalClasses, getSimplePaginationControlsClasses, getSimplePaginationSelectClasses, getSimplePaginationButtonsWrapperClasses, getSimplePaginationButtonClasses, getSimplePaginationPageIndicatorClasses, getTableWrapperClasses, tableBaseClasses, tableLoadingOverlayClasses, icon16ViewBox, expandIconButtonClasses, getExpandIconRotationClasses, icon24ViewBox, lockClosedIcon24PathD, lockOpenIcon24PathD, getSortIconClasses, sortAscIcon16PathD, sortDescIcon16PathD, sortBothIcon16PathD, getLoadingOverlaySpinnerClasses } from '@expcat/tigercat-core';
1
+ import React, { useState, useEffect, useMemo, useCallback } from 'react';
2
+ import { getSpinnerSVG, getFixedColumnOffsets, filterData, sortData, paginateData, getRowKey, calculatePagination, getExpandIconCellClasses, getTableHeaderClasses, getCheckboxCellClasses, classNames, getTableHeaderCellClasses, tableEmptyStateClasses, getTableCellClasses, getTableRowClasses, getExpandedRowClasses, getExpandedRowContentClasses, getSimplePaginationContainerClasses, getSimplePaginationTotalClasses, getSimplePaginationControlsClasses, getSimplePaginationSelectClasses, getSimplePaginationButtonsWrapperClasses, getSimplePaginationButtonClasses, getSimplePaginationPageIndicatorClasses, getTableWrapperClasses, tableBaseClasses, tableLoadingOverlayClasses, icon24ViewBox, lockClosedIcon24PathD, lockOpenIcon24PathD, icon16ViewBox, getSortIconClasses, sortAscIcon16PathD, sortDescIcon16PathD, sortBothIcon16PathD, getExpandIconClasses, expandChevronIcon16PathD, getLoadingOverlaySpinnerClasses } from '@expcat/tigercat-core';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
4
 
5
5
  // src/components/Table.tsx
@@ -22,6 +22,20 @@ var SortIcon = ({ direction }) => {
22
22
  var LockIcon = ({ locked }) => {
23
23
  return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: icon24ViewBox, fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: locked ? lockClosedIcon24PathD : lockOpenIcon24PathD }) });
24
24
  };
25
+ var ExpandIcon = ({ expanded }) => {
26
+ return /* @__PURE__ */ jsx(
27
+ "svg",
28
+ {
29
+ className: getExpandIconClasses(expanded),
30
+ width: "16",
31
+ height: "16",
32
+ viewBox: icon16ViewBox,
33
+ fill: "currentColor",
34
+ "aria-hidden": "true",
35
+ children: /* @__PURE__ */ jsx("path", { d: expandChevronIcon16PathD })
36
+ }
37
+ );
38
+ };
25
39
  var LoadingSpinner = () => /* @__PURE__ */ jsx(
26
40
  "svg",
27
41
  {
@@ -59,19 +73,19 @@ function Table({
59
73
  showTotal: true
60
74
  },
61
75
  rowSelection,
76
+ expandable,
62
77
  rowKey = "id",
63
78
  rowClassName,
64
79
  stickyHeader = false,
65
80
  maxHeight,
66
81
  tableLayout = "auto",
67
- expandable,
68
82
  onChange,
69
83
  onRowClick,
70
84
  onSelectionChange,
71
85
  onSortChange,
72
86
  onFilterChange,
73
87
  onPageChange,
74
- onExpandedRowsChange,
88
+ onExpandChange,
75
89
  className,
76
90
  ...props
77
91
  }) {
@@ -81,6 +95,7 @@ function Table({
81
95
  const isCurrentPageControlled = paginationConfig?.current !== void 0;
82
96
  const isPageSizeControlled = paginationConfig?.pageSize !== void 0;
83
97
  const isSelectionControlled = rowSelection?.selectedRowKeys !== void 0 && Array.isArray(rowSelection.selectedRowKeys);
98
+ const isExpandControlled = expandable?.expandedRowKeys !== void 0 && Array.isArray(expandable.expandedRowKeys);
84
99
  const [uncontrolledSortState, setUncontrolledSortState] = useState(
85
100
  defaultSort ?? { key: null, direction: null }
86
101
  );
@@ -94,11 +109,13 @@ function Table({
94
109
  () => paginationConfig?.defaultPageSize ?? paginationConfig?.pageSize ?? 10
95
110
  );
96
111
  const [uncontrolledSelectedRowKeys, setUncontrolledSelectedRowKeys] = useState(rowSelection?.defaultSelectedRowKeys ?? rowSelection?.selectedRowKeys ?? []);
112
+ const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = useState(expandable?.defaultExpandedRowKeys ?? expandable?.expandedRowKeys ?? []);
97
113
  const sortState = isSortControlled ? sort : uncontrolledSortState;
98
114
  const filterState = isFiltersControlled ? filters : uncontrolledFilterState;
99
115
  const currentPage = isCurrentPageControlled ? paginationConfig.current : uncontrolledCurrentPage;
100
116
  const currentPageSize = isPageSizeControlled ? paginationConfig.pageSize : uncontrolledCurrentPageSize;
101
117
  const selectedRowKeys = isSelectionControlled ? rowSelection.selectedRowKeys : uncontrolledSelectedRowKeys;
118
+ const expandedRowKeys = isExpandControlled ? expandable.expandedRowKeys : uncontrolledExpandedRowKeys;
102
119
  useEffect(() => {
103
120
  if (isSortControlled && sort) {
104
121
  setUncontrolledSortState(sort);
@@ -124,24 +141,11 @@ function Table({
124
141
  setUncontrolledSelectedRowKeys(rowSelection?.selectedRowKeys ?? []);
125
142
  }
126
143
  }, [isSelectionControlled, rowSelection?.selectedRowKeys]);
127
- const isExpandControlled = expandable?.expandedRowKeys !== void 0;
128
- const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = useState(expandable?.defaultExpandedRowKeys ?? expandable?.expandedRowKeys ?? []);
129
- const expandedRowKeys = isExpandControlled ? expandable.expandedRowKeys : uncontrolledExpandedRowKeys;
130
- const expandedRowKeySet = useMemo(
131
- () => new Set(expandedRowKeys),
132
- [expandedRowKeys]
133
- );
134
- const handleToggleExpand = useCallback(
135
- (key) => {
136
- const isExp = expandedRowKeySet.has(key);
137
- const next = isExp ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key];
138
- if (!isExpandControlled) {
139
- setUncontrolledExpandedRowKeys(next);
140
- }
141
- onExpandedRowsChange?.(next);
142
- },
143
- [expandedRowKeys, expandedRowKeySet, isExpandControlled, onExpandedRowsChange]
144
- );
144
+ useEffect(() => {
145
+ if (isExpandControlled) {
146
+ setUncontrolledExpandedRowKeys(expandable?.expandedRowKeys ?? []);
147
+ }
148
+ }, [isExpandControlled, expandable?.expandedRowKeys]);
145
149
  const [fixedOverrides, setFixedOverrides] = useState({});
146
150
  const displayColumns = useMemo(() => {
147
151
  return columns.map((column) => {
@@ -205,6 +209,10 @@ function Table({
205
209
  () => new Set(selectedRowKeys),
206
210
  [selectedRowKeys]
207
211
  );
212
+ const expandedRowKeySet = useMemo(
213
+ () => new Set(expandedRowKeys),
214
+ [expandedRowKeys]
215
+ );
208
216
  const paginationInfo = useMemo(() => {
209
217
  if (pagination === false) {
210
218
  return null;
@@ -316,11 +324,29 @@ function Table({
316
324
  },
317
325
  [sortState, filterState, onPageChange, onChange]
318
326
  );
327
+ const handleToggleExpand = useCallback(
328
+ (key, record) => {
329
+ const isExpanded = expandedRowKeySet.has(key);
330
+ const newKeys = isExpanded ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key];
331
+ if (!isExpandControlled) {
332
+ setUncontrolledExpandedRowKeys(newKeys);
333
+ }
334
+ onExpandChange?.(newKeys, record, !isExpanded);
335
+ },
336
+ [expandedRowKeySet, expandedRowKeys, isExpandControlled, onExpandChange]
337
+ );
319
338
  const handleRowClick = useCallback(
320
339
  (record, index) => {
321
340
  onRowClick?.(record, index);
341
+ if (expandable?.expandRowByClick) {
342
+ const key = getRowKey(record, rowKey, index);
343
+ const isExpandableRow = expandable?.rowExpandable ? expandable.rowExpandable(record) : true;
344
+ if (isExpandableRow) {
345
+ handleToggleExpand(key, record);
346
+ }
347
+ }
322
348
  },
323
- [onRowClick]
349
+ [onRowClick, expandable, rowKey, handleToggleExpand]
324
350
  );
325
351
  const handleSelectRow = useCallback(
326
352
  (key, checked) => {
@@ -368,8 +394,10 @@ function Table({
368
394
  return selectedRowKeys.length > 0 && !allSelected;
369
395
  }, [selectedRowKeys.length, allSelected]);
370
396
  const renderTableHeader = useCallback(() => {
397
+ const expandHeaderTh = expandable ? /* @__PURE__ */ jsx("th", { className: getExpandIconCellClasses(size), "aria-label": "Expand" }) : null;
398
+ const expandAtStart = expandable?.expandIconPosition !== "end";
371
399
  return /* @__PURE__ */ jsx("thead", { className: getTableHeaderClasses(stickyHeader), children: /* @__PURE__ */ jsxs("tr", { children: [
372
- expandable && expandable.expandIconPosition !== "end" && /* @__PURE__ */ jsx("th", { className: getExpandCellClasses(size) }),
400
+ expandAtStart && expandHeaderTh,
373
401
  rowSelection && rowSelection.showCheckbox !== false && rowSelection.type !== "radio" && /* @__PURE__ */ jsx("th", { className: getCheckboxCellClasses(size), children: /* @__PURE__ */ jsx(
374
402
  "input",
375
403
  {
@@ -463,7 +491,7 @@ function Table({
463
491
  column.key
464
492
  );
465
493
  }),
466
- expandable && expandable.expandIconPosition === "end" && /* @__PURE__ */ jsx("th", { className: getExpandCellClasses(size) })
494
+ !expandAtStart && expandHeaderTh
467
495
  ] }) });
468
496
  }, [
469
497
  displayColumns,
@@ -471,6 +499,7 @@ function Table({
471
499
  stickyHeader,
472
500
  sortState,
473
501
  rowSelection,
502
+ expandable,
474
503
  allSelected,
475
504
  someSelected,
476
505
  handleSort,
@@ -478,8 +507,7 @@ function Table({
478
507
  handleSelectAll,
479
508
  columnLockable,
480
509
  toggleColumnLock,
481
- fixedColumnsInfo,
482
- expandable
510
+ fixedColumnsInfo
483
511
  ]);
484
512
  const renderTableBody = useCallback(() => {
485
513
  if (loading) {
@@ -488,131 +516,117 @@ function Table({
488
516
  if (paginatedData.length === 0) {
489
517
  return /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: totalColumnCount, className: tableEmptyStateClasses, children: /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", children: emptyText }) }) }) });
490
518
  }
491
- const ExpandToggle = ({ rowKey: rk, expandableRow, expanded }) => expandableRow ? /* @__PURE__ */ jsx(
492
- "button",
493
- {
494
- className: classNames(expandIconButtonClasses, getExpandIconRotationClasses(expanded)),
495
- "aria-label": expanded ? "Collapse row" : "Expand row",
496
- onClick: (e) => {
497
- e.stopPropagation();
498
- handleToggleExpand(rk);
499
- },
500
- children: /* @__PURE__ */ jsx(
501
- "svg",
502
- {
503
- xmlns: "http://www.w3.org/2000/svg",
504
- viewBox: icon16ViewBox,
505
- fill: "currentColor",
506
- className: "w-4 h-4",
507
- children: /* @__PURE__ */ jsx("path", { d: "M6 3l6 5-6 5V3z" })
508
- }
509
- )
510
- }
511
- ) : null;
512
519
  return /* @__PURE__ */ jsx("tbody", { children: paginatedData.map((record, index) => {
513
520
  const key = pageRowKeys[index];
514
521
  const isSelected = selectedRowKeySet.has(key);
515
522
  const isExpanded = expandedRowKeySet.has(key);
516
- const isExpandableRow = expandable ? expandable.rowExpandable?.(record) ?? true : false;
523
+ const isRowExpandable = expandable ? expandable.rowExpandable ? expandable.rowExpandable(record) : true : false;
517
524
  const rowClass = typeof rowClassName === "function" ? rowClassName(record, index) : rowClassName;
518
- return /* @__PURE__ */ jsxs(Fragment, { children: [
519
- /* @__PURE__ */ jsxs(
520
- "tr",
521
- {
522
- className: classNames(
523
- getTableRowClasses(hoverable, striped, index % 2 === 0, rowClass),
524
- fixedColumnsInfo.hasFixedColumns && "group"
525
- ),
526
- onClick: () => handleRowClick(record, index),
527
- children: [
528
- expandable && expandable.expandIconPosition !== "end" && /* @__PURE__ */ jsx("td", { className: getExpandCellClasses(size), children: /* @__PURE__ */ jsx(
529
- ExpandToggle,
530
- {
531
- rowKey: key,
532
- expandableRow: isExpandableRow,
533
- expanded: isExpanded
534
- }
535
- ) }),
536
- rowSelection && rowSelection.showCheckbox !== false && /* @__PURE__ */ jsx("td", { className: getCheckboxCellClasses(size), children: /* @__PURE__ */ jsx(
537
- "input",
538
- {
539
- type: rowSelection?.type === "radio" ? "radio" : "checkbox",
540
- className: rowSelection?.type === "radio" ? "border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]" : "rounded border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]",
541
- checked: isSelected,
542
- disabled: rowSelection?.getCheckboxProps?.(record)?.disabled,
543
- onChange: (e) => handleSelectRow(key, e.target.checked),
544
- onClick: (e) => e.stopPropagation()
545
- }
546
- ) }),
547
- displayColumns.map((column) => {
548
- const dataKey = column.dataKey || column.key;
549
- const cellValue = record[dataKey];
550
- const isFixedLeft = column.fixed === "left";
551
- const isFixedRight = column.fixed === "right";
552
- const fixedStyle = isFixedLeft ? {
553
- position: "sticky",
554
- left: `${fixedColumnsInfo.leftOffsets[column.key] || 0}px`,
555
- zIndex: 10
556
- } : isFixedRight ? {
557
- position: "sticky",
558
- right: `${fixedColumnsInfo.rightOffsets[column.key] || 0}px`,
559
- zIndex: 10
560
- } : void 0;
561
- const widthStyle = column.width ? {
562
- width: typeof column.width === "number" ? `${column.width}px` : column.width
563
- } : void 0;
564
- const style = fixedStyle ? { ...widthStyle, ...fixedStyle } : widthStyle;
565
- const stickyBgClass = striped && index % 2 === 0 ? "bg-[var(--tiger-surface-muted,#f9fafb)]/50" : "bg-[var(--tiger-surface,#ffffff)]";
566
- const stickyCellClass = isFixedLeft || isFixedRight ? classNames(
567
- stickyBgClass,
568
- hoverable && "group-hover:bg-[var(--tiger-surface-muted,#f9fafb)]"
569
- ) : void 0;
570
- return /* @__PURE__ */ jsx(
571
- "td",
572
- {
573
- className: classNames(
574
- getTableCellClasses(size, column.align || "left", column.className),
575
- stickyCellClass
576
- ),
577
- style,
578
- children: column.render ? column.render(record, index) : cellValue
579
- },
580
- column.key
581
- );
582
- }),
583
- expandable && expandable.expandIconPosition === "end" && /* @__PURE__ */ jsx("td", { className: getExpandCellClasses(size), children: /* @__PURE__ */ jsx(
584
- ExpandToggle,
525
+ const expandToggleCell = expandable ? /* @__PURE__ */ jsx("td", { className: getExpandIconCellClasses(size), children: isRowExpandable && /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ className: "inline-flex items-center justify-center",
530
+ "aria-label": isExpanded ? "Collapse row" : "Expand row",
531
+ "aria-expanded": isExpanded,
532
+ onClick: (e) => {
533
+ e.stopPropagation();
534
+ handleToggleExpand(key, record);
535
+ },
536
+ children: /* @__PURE__ */ jsx(ExpandIcon, { expanded: isExpanded })
537
+ }
538
+ ) }) : null;
539
+ const expandAtStart = expandable?.expandIconPosition !== "end";
540
+ const rowNode = /* @__PURE__ */ jsxs(
541
+ "tr",
542
+ {
543
+ className: classNames(
544
+ getTableRowClasses(hoverable, striped, index % 2 === 0, rowClass),
545
+ fixedColumnsInfo.hasFixedColumns && "group"
546
+ ),
547
+ onClick: () => handleRowClick(record, index),
548
+ children: [
549
+ expandAtStart && expandToggleCell,
550
+ rowSelection && rowSelection.showCheckbox !== false && /* @__PURE__ */ jsx("td", { className: getCheckboxCellClasses(size), children: /* @__PURE__ */ jsx(
551
+ "input",
552
+ {
553
+ type: rowSelection?.type === "radio" ? "radio" : "checkbox",
554
+ className: rowSelection?.type === "radio" ? "border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]" : "rounded border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]",
555
+ checked: isSelected,
556
+ disabled: rowSelection?.getCheckboxProps?.(record)?.disabled,
557
+ onChange: (e) => handleSelectRow(key, e.target.checked),
558
+ onClick: (e) => e.stopPropagation()
559
+ }
560
+ ) }),
561
+ displayColumns.map((column) => {
562
+ const dataKey = column.dataKey || column.key;
563
+ const cellValue = record[dataKey];
564
+ const isFixedLeft = column.fixed === "left";
565
+ const isFixedRight = column.fixed === "right";
566
+ const fixedStyle = isFixedLeft ? {
567
+ position: "sticky",
568
+ left: `${fixedColumnsInfo.leftOffsets[column.key] || 0}px`,
569
+ zIndex: 10
570
+ } : isFixedRight ? {
571
+ position: "sticky",
572
+ right: `${fixedColumnsInfo.rightOffsets[column.key] || 0}px`,
573
+ zIndex: 10
574
+ } : void 0;
575
+ const widthStyle = column.width ? {
576
+ width: typeof column.width === "number" ? `${column.width}px` : column.width
577
+ } : void 0;
578
+ const style = fixedStyle ? { ...widthStyle, ...fixedStyle } : widthStyle;
579
+ const stickyBgClass = striped && index % 2 === 0 ? "bg-[var(--tiger-surface-muted,#f9fafb)]/50" : "bg-[var(--tiger-surface,#ffffff)]";
580
+ const stickyCellClass = isFixedLeft || isFixedRight ? classNames(
581
+ stickyBgClass,
582
+ hoverable && "group-hover:bg-[var(--tiger-surface-muted,#f9fafb)]"
583
+ ) : void 0;
584
+ return /* @__PURE__ */ jsx(
585
+ "td",
585
586
  {
586
- rowKey: key,
587
- expandableRow: isExpandableRow,
588
- expanded: isExpanded
589
- }
590
- ) })
591
- ]
592
- }
593
- ),
594
- expandable && isExpanded && isExpandableRow && /* @__PURE__ */ jsx("tr", { className: expandedRowContentClasses, children: /* @__PURE__ */ jsx("td", { colSpan: totalColumnCount, children: expandable.expandedRowRender(record, index) }) })
595
- ] }, key);
587
+ className: classNames(
588
+ getTableCellClasses(size, column.align || "left", column.className),
589
+ stickyCellClass
590
+ ),
591
+ style,
592
+ children: column.render ? column.render(record, index) : cellValue
593
+ },
594
+ column.key
595
+ );
596
+ }),
597
+ !expandAtStart && expandToggleCell
598
+ ]
599
+ },
600
+ key
601
+ );
602
+ if (expandable && isExpanded && isRowExpandable) {
603
+ const expandedContent = expandable.expandedRowRender ? expandable.expandedRowRender(record, index) : null;
604
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
605
+ rowNode,
606
+ /* @__PURE__ */ jsx("tr", { className: getExpandedRowClasses(), children: /* @__PURE__ */ jsx("td", { colSpan: totalColumnCount, className: getExpandedRowContentClasses(size), children: expandedContent }) }, `${key}-expanded`)
607
+ ] }, key);
608
+ }
609
+ return rowNode;
596
610
  }) });
597
611
  }, [
598
612
  loading,
599
613
  paginatedData,
600
614
  displayColumns,
601
615
  rowSelection,
616
+ expandable,
602
617
  emptyText,
603
618
  pageRowKeys,
604
619
  selectedRowKeySet,
620
+ expandedRowKeySet,
621
+ totalColumnCount,
605
622
  rowClassName,
606
623
  hoverable,
607
624
  striped,
608
625
  size,
609
626
  handleRowClick,
610
627
  handleSelectRow,
611
- fixedColumnsInfo,
612
- expandable,
613
- expandedRowKeySet,
614
628
  handleToggleExpand,
615
- totalColumnCount
629
+ fixedColumnsInfo
616
630
  ]);
617
631
  const renderPagination = useCallback(() => {
618
632
  if (pagination === false || !paginationInfo) {
@@ -1,4 +1,4 @@
1
- import { Table } from './chunk-PJ7NS7NX.mjs';
1
+ import { Table } from './chunk-KBTFBEPE.mjs';
2
2
  import { Select } from './chunk-MDZDPGRK.mjs';
3
3
  import { Pagination } from './chunk-NZLOLMT2.mjs';
4
4
  import { Input } from './chunk-RPTLVIBF.mjs';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunk6OVVMHZJ_js = require('./chunk-6OVVMHZJ.js');
3
+ var chunkZBVFM3GJ_js = require('./chunk-ZBVFM3GJ.js');
4
4
  var chunkTDRINUMH_js = require('./chunk-TDRINUMH.js');
5
5
  var chunk3GW3UAKB_js = require('./chunk-3GW3UAKB.js');
6
6
  var chunkOYCMGKQ7_js = require('./chunk-OYCMGKQ7.js');
@@ -187,7 +187,7 @@ var DataTableWithToolbar = ({
187
187
  const showPagination = pagination && typeof pagination === "object";
188
188
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClasses, "data-tiger-data-table-with-toolbar": true, children: [
189
189
  renderToolbar(),
190
- /* @__PURE__ */ jsxRuntime.jsx(chunk6OVVMHZJ_js.Table, { ...tableProps, pagination: false, className: tableClassName }),
190
+ /* @__PURE__ */ jsxRuntime.jsx(chunkZBVFM3GJ_js.Table, { ...tableProps, pagination: false, className: tableClassName }),
191
191
  showPagination ? /* @__PURE__ */ jsxRuntime.jsx(chunk3GW3UAKB_js.Pagination, { ...pagination, onChange: onPageChange, onPageSizeChange }) : null
192
192
  ] });
193
193
  };
@@ -1,9 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React = require('react');
4
4
  var tigercatCore = require('@expcat/tigercat-core');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefault(React);
10
+
7
11
  // src/components/Table.tsx
8
12
  var spinnerSvg = tigercatCore.getSpinnerSVG("spinner");
9
13
  var SortIcon = ({ direction }) => {
@@ -24,6 +28,20 @@ var SortIcon = ({ direction }) => {
24
28
  var LockIcon = ({ locked }) => {
25
29
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: tigercatCore.icon24ViewBox, fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: locked ? tigercatCore.lockClosedIcon24PathD : tigercatCore.lockOpenIcon24PathD }) });
26
30
  };
31
+ var ExpandIcon = ({ expanded }) => {
32
+ return /* @__PURE__ */ jsxRuntime.jsx(
33
+ "svg",
34
+ {
35
+ className: tigercatCore.getExpandIconClasses(expanded),
36
+ width: "16",
37
+ height: "16",
38
+ viewBox: tigercatCore.icon16ViewBox,
39
+ fill: "currentColor",
40
+ "aria-hidden": "true",
41
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.expandChevronIcon16PathD })
42
+ }
43
+ );
44
+ };
27
45
  var LoadingSpinner = () => /* @__PURE__ */ jsxRuntime.jsx(
28
46
  "svg",
29
47
  {
@@ -61,19 +79,19 @@ function Table({
61
79
  showTotal: true
62
80
  },
63
81
  rowSelection,
82
+ expandable,
64
83
  rowKey = "id",
65
84
  rowClassName,
66
85
  stickyHeader = false,
67
86
  maxHeight,
68
87
  tableLayout = "auto",
69
- expandable,
70
88
  onChange,
71
89
  onRowClick,
72
90
  onSelectionChange,
73
91
  onSortChange,
74
92
  onFilterChange,
75
93
  onPageChange,
76
- onExpandedRowsChange,
94
+ onExpandChange,
77
95
  className,
78
96
  ...props
79
97
  }) {
@@ -83,69 +101,59 @@ function Table({
83
101
  const isCurrentPageControlled = paginationConfig?.current !== void 0;
84
102
  const isPageSizeControlled = paginationConfig?.pageSize !== void 0;
85
103
  const isSelectionControlled = rowSelection?.selectedRowKeys !== void 0 && Array.isArray(rowSelection.selectedRowKeys);
86
- const [uncontrolledSortState, setUncontrolledSortState] = react.useState(
104
+ const isExpandControlled = expandable?.expandedRowKeys !== void 0 && Array.isArray(expandable.expandedRowKeys);
105
+ const [uncontrolledSortState, setUncontrolledSortState] = React.useState(
87
106
  defaultSort ?? { key: null, direction: null }
88
107
  );
89
- const [uncontrolledFilterState, setUncontrolledFilterState] = react.useState(
108
+ const [uncontrolledFilterState, setUncontrolledFilterState] = React.useState(
90
109
  defaultFilters ?? {}
91
110
  );
92
- const [uncontrolledCurrentPage, setUncontrolledCurrentPage] = react.useState(
111
+ const [uncontrolledCurrentPage, setUncontrolledCurrentPage] = React.useState(
93
112
  () => paginationConfig?.defaultCurrent ?? paginationConfig?.current ?? 1
94
113
  );
95
- const [uncontrolledCurrentPageSize, setUncontrolledCurrentPageSize] = react.useState(
114
+ const [uncontrolledCurrentPageSize, setUncontrolledCurrentPageSize] = React.useState(
96
115
  () => paginationConfig?.defaultPageSize ?? paginationConfig?.pageSize ?? 10
97
116
  );
98
- const [uncontrolledSelectedRowKeys, setUncontrolledSelectedRowKeys] = react.useState(rowSelection?.defaultSelectedRowKeys ?? rowSelection?.selectedRowKeys ?? []);
117
+ const [uncontrolledSelectedRowKeys, setUncontrolledSelectedRowKeys] = React.useState(rowSelection?.defaultSelectedRowKeys ?? rowSelection?.selectedRowKeys ?? []);
118
+ const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = React.useState(expandable?.defaultExpandedRowKeys ?? expandable?.expandedRowKeys ?? []);
99
119
  const sortState = isSortControlled ? sort : uncontrolledSortState;
100
120
  const filterState = isFiltersControlled ? filters : uncontrolledFilterState;
101
121
  const currentPage = isCurrentPageControlled ? paginationConfig.current : uncontrolledCurrentPage;
102
122
  const currentPageSize = isPageSizeControlled ? paginationConfig.pageSize : uncontrolledCurrentPageSize;
103
123
  const selectedRowKeys = isSelectionControlled ? rowSelection.selectedRowKeys : uncontrolledSelectedRowKeys;
104
- react.useEffect(() => {
124
+ const expandedRowKeys = isExpandControlled ? expandable.expandedRowKeys : uncontrolledExpandedRowKeys;
125
+ React.useEffect(() => {
105
126
  if (isSortControlled && sort) {
106
127
  setUncontrolledSortState(sort);
107
128
  }
108
129
  }, [isSortControlled, sort?.key, sort?.direction]);
109
- react.useEffect(() => {
130
+ React.useEffect(() => {
110
131
  if (isFiltersControlled && filters) {
111
132
  setUncontrolledFilterState(filters);
112
133
  }
113
134
  }, [isFiltersControlled, filters]);
114
- react.useEffect(() => {
135
+ React.useEffect(() => {
115
136
  if (isCurrentPageControlled) {
116
137
  setUncontrolledCurrentPage(paginationConfig.current);
117
138
  }
118
139
  }, [isCurrentPageControlled, paginationConfig?.current]);
119
- react.useEffect(() => {
140
+ React.useEffect(() => {
120
141
  if (isPageSizeControlled) {
121
142
  setUncontrolledCurrentPageSize(paginationConfig.pageSize);
122
143
  }
123
144
  }, [isPageSizeControlled, paginationConfig?.pageSize]);
124
- react.useEffect(() => {
145
+ React.useEffect(() => {
125
146
  if (isSelectionControlled) {
126
147
  setUncontrolledSelectedRowKeys(rowSelection?.selectedRowKeys ?? []);
127
148
  }
128
149
  }, [isSelectionControlled, rowSelection?.selectedRowKeys]);
129
- const isExpandControlled = expandable?.expandedRowKeys !== void 0;
130
- const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = react.useState(expandable?.defaultExpandedRowKeys ?? expandable?.expandedRowKeys ?? []);
131
- const expandedRowKeys = isExpandControlled ? expandable.expandedRowKeys : uncontrolledExpandedRowKeys;
132
- const expandedRowKeySet = react.useMemo(
133
- () => new Set(expandedRowKeys),
134
- [expandedRowKeys]
135
- );
136
- const handleToggleExpand = react.useCallback(
137
- (key) => {
138
- const isExp = expandedRowKeySet.has(key);
139
- const next = isExp ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key];
140
- if (!isExpandControlled) {
141
- setUncontrolledExpandedRowKeys(next);
142
- }
143
- onExpandedRowsChange?.(next);
144
- },
145
- [expandedRowKeys, expandedRowKeySet, isExpandControlled, onExpandedRowsChange]
146
- );
147
- const [fixedOverrides, setFixedOverrides] = react.useState({});
148
- const displayColumns = react.useMemo(() => {
150
+ React.useEffect(() => {
151
+ if (isExpandControlled) {
152
+ setUncontrolledExpandedRowKeys(expandable?.expandedRowKeys ?? []);
153
+ }
154
+ }, [isExpandControlled, expandable?.expandedRowKeys]);
155
+ const [fixedOverrides, setFixedOverrides] = React.useState({});
156
+ const displayColumns = React.useMemo(() => {
149
157
  return columns.map((column) => {
150
158
  const hasOverride = Object.prototype.hasOwnProperty.call(fixedOverrides, column.key);
151
159
  return {
@@ -154,23 +162,23 @@ function Table({
154
162
  };
155
163
  });
156
164
  }, [columns, fixedOverrides]);
157
- const totalColumnCount = react.useMemo(() => {
165
+ const totalColumnCount = React.useMemo(() => {
158
166
  let count = displayColumns.length;
159
167
  if (rowSelection && rowSelection.showCheckbox !== false) count++;
160
168
  if (expandable) count++;
161
169
  return count;
162
170
  }, [displayColumns.length, rowSelection, expandable]);
163
- const columnByKey = react.useMemo(() => {
171
+ const columnByKey = React.useMemo(() => {
164
172
  const map = {};
165
173
  for (const column of displayColumns) {
166
174
  map[column.key] = column;
167
175
  }
168
176
  return map;
169
177
  }, [displayColumns]);
170
- const fixedColumnsInfo = react.useMemo(() => {
178
+ const fixedColumnsInfo = React.useMemo(() => {
171
179
  return tigercatCore.getFixedColumnOffsets(displayColumns);
172
180
  }, [displayColumns]);
173
- const toggleColumnLock = react.useCallback(
181
+ const toggleColumnLock = React.useCallback(
174
182
  (columnKey) => {
175
183
  setFixedOverrides((prev) => {
176
184
  const original = columns.find((c) => c.key === columnKey)?.fixed;
@@ -184,7 +192,7 @@ function Table({
184
192
  },
185
193
  [columns]
186
194
  );
187
- const processedData = react.useMemo(() => {
195
+ const processedData = React.useMemo(() => {
188
196
  let data = dataSource;
189
197
  data = tigercatCore.filterData(data, filterState);
190
198
  if (sortState.key && sortState.direction) {
@@ -193,28 +201,32 @@ function Table({
193
201
  }
194
202
  return data;
195
203
  }, [dataSource, filterState, sortState, columnByKey]);
196
- const paginatedData = react.useMemo(() => {
204
+ const paginatedData = React.useMemo(() => {
197
205
  if (pagination === false) {
198
206
  return processedData;
199
207
  }
200
208
  return tigercatCore.paginateData(processedData, currentPage, currentPageSize);
201
209
  }, [processedData, currentPage, currentPageSize, pagination]);
202
- const pageRowKeys = react.useMemo(
210
+ const pageRowKeys = React.useMemo(
203
211
  () => paginatedData.map((record, index) => tigercatCore.getRowKey(record, rowKey, index)),
204
212
  [paginatedData, rowKey]
205
213
  );
206
- const selectedRowKeySet = react.useMemo(
214
+ const selectedRowKeySet = React.useMemo(
207
215
  () => new Set(selectedRowKeys),
208
216
  [selectedRowKeys]
209
217
  );
210
- const paginationInfo = react.useMemo(() => {
218
+ const expandedRowKeySet = React.useMemo(
219
+ () => new Set(expandedRowKeys),
220
+ [expandedRowKeys]
221
+ );
222
+ const paginationInfo = React.useMemo(() => {
211
223
  if (pagination === false) {
212
224
  return null;
213
225
  }
214
226
  const total = processedData.length;
215
227
  return tigercatCore.calculatePagination(total, currentPage, currentPageSize);
216
228
  }, [processedData.length, currentPage, currentPageSize, pagination]);
217
- const handleSort = react.useCallback(
229
+ const handleSort = React.useCallback(
218
230
  (columnKey) => {
219
231
  const column = columnByKey[columnKey];
220
232
  if (!column || !column.sortable) {
@@ -257,7 +269,7 @@ function Table({
257
269
  onChange
258
270
  ]
259
271
  );
260
- const handleFilter = react.useCallback(
272
+ const handleFilter = React.useCallback(
261
273
  (columnKey, value) => {
262
274
  const newFilterState = {
263
275
  ...filterState,
@@ -287,7 +299,7 @@ function Table({
287
299
  onChange
288
300
  ]
289
301
  );
290
- const handlePageChange = react.useCallback(
302
+ const handlePageChange = React.useCallback(
291
303
  (page) => {
292
304
  setUncontrolledCurrentPage(page);
293
305
  onPageChange?.({ current: page, pageSize: currentPageSize });
@@ -302,7 +314,7 @@ function Table({
302
314
  },
303
315
  [currentPageSize, sortState, filterState, onPageChange, onChange]
304
316
  );
305
- const handlePageSizeChange = react.useCallback(
317
+ const handlePageSizeChange = React.useCallback(
306
318
  (pageSize) => {
307
319
  setUncontrolledCurrentPageSize(pageSize);
308
320
  setUncontrolledCurrentPage(1);
@@ -318,13 +330,31 @@ function Table({
318
330
  },
319
331
  [sortState, filterState, onPageChange, onChange]
320
332
  );
321
- const handleRowClick = react.useCallback(
333
+ const handleToggleExpand = React.useCallback(
334
+ (key, record) => {
335
+ const isExpanded = expandedRowKeySet.has(key);
336
+ const newKeys = isExpanded ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key];
337
+ if (!isExpandControlled) {
338
+ setUncontrolledExpandedRowKeys(newKeys);
339
+ }
340
+ onExpandChange?.(newKeys, record, !isExpanded);
341
+ },
342
+ [expandedRowKeySet, expandedRowKeys, isExpandControlled, onExpandChange]
343
+ );
344
+ const handleRowClick = React.useCallback(
322
345
  (record, index) => {
323
346
  onRowClick?.(record, index);
347
+ if (expandable?.expandRowByClick) {
348
+ const key = tigercatCore.getRowKey(record, rowKey, index);
349
+ const isExpandableRow = expandable?.rowExpandable ? expandable.rowExpandable(record) : true;
350
+ if (isExpandableRow) {
351
+ handleToggleExpand(key, record);
352
+ }
353
+ }
324
354
  },
325
- [onRowClick]
355
+ [onRowClick, expandable, rowKey, handleToggleExpand]
326
356
  );
327
- const handleSelectRow = react.useCallback(
357
+ const handleSelectRow = React.useCallback(
328
358
  (key, checked) => {
329
359
  let newKeys;
330
360
  if (rowSelection?.type === "radio") {
@@ -343,7 +373,7 @@ function Table({
343
373
  },
344
374
  [rowSelection, selectedRowKeys, isSelectionControlled, onSelectionChange]
345
375
  );
346
- const handleSelectAll = react.useCallback(
376
+ const handleSelectAll = React.useCallback(
347
377
  (checked) => {
348
378
  if (checked) {
349
379
  const newKeys = pageRowKeys;
@@ -360,18 +390,20 @@ function Table({
360
390
  },
361
391
  [pageRowKeys, isSelectionControlled, onSelectionChange]
362
392
  );
363
- const allSelected = react.useMemo(() => {
393
+ const allSelected = React.useMemo(() => {
364
394
  if (pageRowKeys.length === 0) {
365
395
  return false;
366
396
  }
367
397
  return pageRowKeys.every((key) => selectedRowKeySet.has(key));
368
398
  }, [pageRowKeys, selectedRowKeySet]);
369
- const someSelected = react.useMemo(() => {
399
+ const someSelected = React.useMemo(() => {
370
400
  return selectedRowKeys.length > 0 && !allSelected;
371
401
  }, [selectedRowKeys.length, allSelected]);
372
- const renderTableHeader = react.useCallback(() => {
402
+ const renderTableHeader = React.useCallback(() => {
403
+ const expandHeaderTh = expandable ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: tigercatCore.getExpandIconCellClasses(size), "aria-label": "Expand" }) : null;
404
+ const expandAtStart = expandable?.expandIconPosition !== "end";
373
405
  return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: tigercatCore.getTableHeaderClasses(stickyHeader), children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
374
- expandable && expandable.expandIconPosition !== "end" && /* @__PURE__ */ jsxRuntime.jsx("th", { className: tigercatCore.getExpandCellClasses(size) }),
406
+ expandAtStart && expandHeaderTh,
375
407
  rowSelection && rowSelection.showCheckbox !== false && rowSelection.type !== "radio" && /* @__PURE__ */ jsxRuntime.jsx("th", { className: tigercatCore.getCheckboxCellClasses(size), children: /* @__PURE__ */ jsxRuntime.jsx(
376
408
  "input",
377
409
  {
@@ -465,7 +497,7 @@ function Table({
465
497
  column.key
466
498
  );
467
499
  }),
468
- expandable && expandable.expandIconPosition === "end" && /* @__PURE__ */ jsxRuntime.jsx("th", { className: tigercatCore.getExpandCellClasses(size) })
500
+ !expandAtStart && expandHeaderTh
469
501
  ] }) });
470
502
  }, [
471
503
  displayColumns,
@@ -473,6 +505,7 @@ function Table({
473
505
  stickyHeader,
474
506
  sortState,
475
507
  rowSelection,
508
+ expandable,
476
509
  allSelected,
477
510
  someSelected,
478
511
  handleSort,
@@ -480,143 +513,128 @@ function Table({
480
513
  handleSelectAll,
481
514
  columnLockable,
482
515
  toggleColumnLock,
483
- fixedColumnsInfo,
484
- expandable
516
+ fixedColumnsInfo
485
517
  ]);
486
- const renderTableBody = react.useCallback(() => {
518
+ const renderTableBody = React.useCallback(() => {
487
519
  if (loading) {
488
520
  return null;
489
521
  }
490
522
  if (paginatedData.length === 0) {
491
523
  return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColumnCount, className: tigercatCore.tableEmptyStateClasses, children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", children: emptyText }) }) }) });
492
524
  }
493
- const ExpandToggle = ({ rowKey: rk, expandableRow, expanded }) => expandableRow ? /* @__PURE__ */ jsxRuntime.jsx(
494
- "button",
495
- {
496
- className: tigercatCore.classNames(tigercatCore.expandIconButtonClasses, tigercatCore.getExpandIconRotationClasses(expanded)),
497
- "aria-label": expanded ? "Collapse row" : "Expand row",
498
- onClick: (e) => {
499
- e.stopPropagation();
500
- handleToggleExpand(rk);
501
- },
502
- children: /* @__PURE__ */ jsxRuntime.jsx(
503
- "svg",
504
- {
505
- xmlns: "http://www.w3.org/2000/svg",
506
- viewBox: tigercatCore.icon16ViewBox,
507
- fill: "currentColor",
508
- className: "w-4 h-4",
509
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3l6 5-6 5V3z" })
510
- }
511
- )
512
- }
513
- ) : null;
514
525
  return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: paginatedData.map((record, index) => {
515
526
  const key = pageRowKeys[index];
516
527
  const isSelected = selectedRowKeySet.has(key);
517
528
  const isExpanded = expandedRowKeySet.has(key);
518
- const isExpandableRow = expandable ? expandable.rowExpandable?.(record) ?? true : false;
529
+ const isRowExpandable = expandable ? expandable.rowExpandable ? expandable.rowExpandable(record) : true : false;
519
530
  const rowClass = typeof rowClassName === "function" ? rowClassName(record, index) : rowClassName;
520
- return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
521
- /* @__PURE__ */ jsxRuntime.jsxs(
522
- "tr",
523
- {
524
- className: tigercatCore.classNames(
525
- tigercatCore.getTableRowClasses(hoverable, striped, index % 2 === 0, rowClass),
526
- fixedColumnsInfo.hasFixedColumns && "group"
527
- ),
528
- onClick: () => handleRowClick(record, index),
529
- children: [
530
- expandable && expandable.expandIconPosition !== "end" && /* @__PURE__ */ jsxRuntime.jsx("td", { className: tigercatCore.getExpandCellClasses(size), children: /* @__PURE__ */ jsxRuntime.jsx(
531
- ExpandToggle,
532
- {
533
- rowKey: key,
534
- expandableRow: isExpandableRow,
535
- expanded: isExpanded
536
- }
537
- ) }),
538
- rowSelection && rowSelection.showCheckbox !== false && /* @__PURE__ */ jsxRuntime.jsx("td", { className: tigercatCore.getCheckboxCellClasses(size), children: /* @__PURE__ */ jsxRuntime.jsx(
539
- "input",
540
- {
541
- type: rowSelection?.type === "radio" ? "radio" : "checkbox",
542
- className: rowSelection?.type === "radio" ? "border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]" : "rounded border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]",
543
- checked: isSelected,
544
- disabled: rowSelection?.getCheckboxProps?.(record)?.disabled,
545
- onChange: (e) => handleSelectRow(key, e.target.checked),
546
- onClick: (e) => e.stopPropagation()
547
- }
548
- ) }),
549
- displayColumns.map((column) => {
550
- const dataKey = column.dataKey || column.key;
551
- const cellValue = record[dataKey];
552
- const isFixedLeft = column.fixed === "left";
553
- const isFixedRight = column.fixed === "right";
554
- const fixedStyle = isFixedLeft ? {
555
- position: "sticky",
556
- left: `${fixedColumnsInfo.leftOffsets[column.key] || 0}px`,
557
- zIndex: 10
558
- } : isFixedRight ? {
559
- position: "sticky",
560
- right: `${fixedColumnsInfo.rightOffsets[column.key] || 0}px`,
561
- zIndex: 10
562
- } : void 0;
563
- const widthStyle = column.width ? {
564
- width: typeof column.width === "number" ? `${column.width}px` : column.width
565
- } : void 0;
566
- const style = fixedStyle ? { ...widthStyle, ...fixedStyle } : widthStyle;
567
- const stickyBgClass = striped && index % 2 === 0 ? "bg-[var(--tiger-surface-muted,#f9fafb)]/50" : "bg-[var(--tiger-surface,#ffffff)]";
568
- const stickyCellClass = isFixedLeft || isFixedRight ? tigercatCore.classNames(
569
- stickyBgClass,
570
- hoverable && "group-hover:bg-[var(--tiger-surface-muted,#f9fafb)]"
571
- ) : void 0;
572
- return /* @__PURE__ */ jsxRuntime.jsx(
573
- "td",
574
- {
575
- className: tigercatCore.classNames(
576
- tigercatCore.getTableCellClasses(size, column.align || "left", column.className),
577
- stickyCellClass
578
- ),
579
- style,
580
- children: column.render ? column.render(record, index) : cellValue
581
- },
582
- column.key
583
- );
584
- }),
585
- expandable && expandable.expandIconPosition === "end" && /* @__PURE__ */ jsxRuntime.jsx("td", { className: tigercatCore.getExpandCellClasses(size), children: /* @__PURE__ */ jsxRuntime.jsx(
586
- ExpandToggle,
531
+ const expandToggleCell = expandable ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: tigercatCore.getExpandIconCellClasses(size), children: isRowExpandable && /* @__PURE__ */ jsxRuntime.jsx(
532
+ "button",
533
+ {
534
+ type: "button",
535
+ className: "inline-flex items-center justify-center",
536
+ "aria-label": isExpanded ? "Collapse row" : "Expand row",
537
+ "aria-expanded": isExpanded,
538
+ onClick: (e) => {
539
+ e.stopPropagation();
540
+ handleToggleExpand(key, record);
541
+ },
542
+ children: /* @__PURE__ */ jsxRuntime.jsx(ExpandIcon, { expanded: isExpanded })
543
+ }
544
+ ) }) : null;
545
+ const expandAtStart = expandable?.expandIconPosition !== "end";
546
+ const rowNode = /* @__PURE__ */ jsxRuntime.jsxs(
547
+ "tr",
548
+ {
549
+ className: tigercatCore.classNames(
550
+ tigercatCore.getTableRowClasses(hoverable, striped, index % 2 === 0, rowClass),
551
+ fixedColumnsInfo.hasFixedColumns && "group"
552
+ ),
553
+ onClick: () => handleRowClick(record, index),
554
+ children: [
555
+ expandAtStart && expandToggleCell,
556
+ rowSelection && rowSelection.showCheckbox !== false && /* @__PURE__ */ jsxRuntime.jsx("td", { className: tigercatCore.getCheckboxCellClasses(size), children: /* @__PURE__ */ jsxRuntime.jsx(
557
+ "input",
558
+ {
559
+ type: rowSelection?.type === "radio" ? "radio" : "checkbox",
560
+ className: rowSelection?.type === "radio" ? "border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]" : "rounded border-gray-300 text-[var(--tiger-primary,#2563eb)] focus:ring-[var(--tiger-primary,#2563eb)]",
561
+ checked: isSelected,
562
+ disabled: rowSelection?.getCheckboxProps?.(record)?.disabled,
563
+ onChange: (e) => handleSelectRow(key, e.target.checked),
564
+ onClick: (e) => e.stopPropagation()
565
+ }
566
+ ) }),
567
+ displayColumns.map((column) => {
568
+ const dataKey = column.dataKey || column.key;
569
+ const cellValue = record[dataKey];
570
+ const isFixedLeft = column.fixed === "left";
571
+ const isFixedRight = column.fixed === "right";
572
+ const fixedStyle = isFixedLeft ? {
573
+ position: "sticky",
574
+ left: `${fixedColumnsInfo.leftOffsets[column.key] || 0}px`,
575
+ zIndex: 10
576
+ } : isFixedRight ? {
577
+ position: "sticky",
578
+ right: `${fixedColumnsInfo.rightOffsets[column.key] || 0}px`,
579
+ zIndex: 10
580
+ } : void 0;
581
+ const widthStyle = column.width ? {
582
+ width: typeof column.width === "number" ? `${column.width}px` : column.width
583
+ } : void 0;
584
+ const style = fixedStyle ? { ...widthStyle, ...fixedStyle } : widthStyle;
585
+ const stickyBgClass = striped && index % 2 === 0 ? "bg-[var(--tiger-surface-muted,#f9fafb)]/50" : "bg-[var(--tiger-surface,#ffffff)]";
586
+ const stickyCellClass = isFixedLeft || isFixedRight ? tigercatCore.classNames(
587
+ stickyBgClass,
588
+ hoverable && "group-hover:bg-[var(--tiger-surface-muted,#f9fafb)]"
589
+ ) : void 0;
590
+ return /* @__PURE__ */ jsxRuntime.jsx(
591
+ "td",
587
592
  {
588
- rowKey: key,
589
- expandableRow: isExpandableRow,
590
- expanded: isExpanded
591
- }
592
- ) })
593
- ]
594
- }
595
- ),
596
- expandable && isExpanded && isExpandableRow && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: tigercatCore.expandedRowContentClasses, children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColumnCount, children: expandable.expandedRowRender(record, index) }) })
597
- ] }, key);
593
+ className: tigercatCore.classNames(
594
+ tigercatCore.getTableCellClasses(size, column.align || "left", column.className),
595
+ stickyCellClass
596
+ ),
597
+ style,
598
+ children: column.render ? column.render(record, index) : cellValue
599
+ },
600
+ column.key
601
+ );
602
+ }),
603
+ !expandAtStart && expandToggleCell
604
+ ]
605
+ },
606
+ key
607
+ );
608
+ if (expandable && isExpanded && isRowExpandable) {
609
+ const expandedContent = expandable.expandedRowRender ? expandable.expandedRowRender(record, index) : null;
610
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
611
+ rowNode,
612
+ /* @__PURE__ */ jsxRuntime.jsx("tr", { className: tigercatCore.getExpandedRowClasses(), children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColumnCount, className: tigercatCore.getExpandedRowContentClasses(size), children: expandedContent }) }, `${key}-expanded`)
613
+ ] }, key);
614
+ }
615
+ return rowNode;
598
616
  }) });
599
617
  }, [
600
618
  loading,
601
619
  paginatedData,
602
620
  displayColumns,
603
621
  rowSelection,
622
+ expandable,
604
623
  emptyText,
605
624
  pageRowKeys,
606
625
  selectedRowKeySet,
626
+ expandedRowKeySet,
627
+ totalColumnCount,
607
628
  rowClassName,
608
629
  hoverable,
609
630
  striped,
610
631
  size,
611
632
  handleRowClick,
612
633
  handleSelectRow,
613
- fixedColumnsInfo,
614
- expandable,
615
- expandedRowKeySet,
616
634
  handleToggleExpand,
617
- totalColumnCount
635
+ fixedColumnsInfo
618
636
  ]);
619
- const renderPagination = react.useCallback(() => {
637
+ const renderPagination = React.useCallback(() => {
620
638
  if (pagination === false || !paginationInfo) {
621
639
  return null;
622
640
  }
@@ -675,7 +693,7 @@ function Table({
675
693
  handlePageChange,
676
694
  handlePageSizeChange
677
695
  ]);
678
- const wrapperStyle = react.useMemo(
696
+ const wrapperStyle = React.useMemo(
679
697
  () => maxHeight ? {
680
698
  maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
681
699
  } : void 0,
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var chunkQ7GUWWG5_js = require('../chunk-Q7GUWWG5.js');
6
- require('../chunk-6OVVMHZJ.js');
5
+ var chunkLXX2ZDJN_js = require('../chunk-LXX2ZDJN.js');
6
+ require('../chunk-ZBVFM3GJ.js');
7
7
  require('../chunk-TDRINUMH.js');
8
8
  require('../chunk-3GW3UAKB.js');
9
9
  require('../chunk-OYCMGKQ7.js');
@@ -13,9 +13,9 @@ require('../chunk-F24IF2QL.js');
13
13
 
14
14
  Object.defineProperty(exports, "DataTableWithToolbar", {
15
15
  enumerable: true,
16
- get: function () { return chunkQ7GUWWG5_js.DataTableWithToolbar; }
16
+ get: function () { return chunkLXX2ZDJN_js.DataTableWithToolbar; }
17
17
  });
18
18
  Object.defineProperty(exports, "default", {
19
19
  enumerable: true,
20
- get: function () { return chunkQ7GUWWG5_js.DataTableWithToolbar_default; }
20
+ get: function () { return chunkLXX2ZDJN_js.DataTableWithToolbar_default; }
21
21
  });
@@ -1,5 +1,5 @@
1
- export { DataTableWithToolbar, DataTableWithToolbar_default as default } from '../chunk-FX2IBA4W.mjs';
2
- import '../chunk-PJ7NS7NX.mjs';
1
+ export { DataTableWithToolbar, DataTableWithToolbar_default as default } from '../chunk-LLHUBM6E.mjs';
2
+ import '../chunk-KBTFBEPE.mjs';
3
3
  import '../chunk-MDZDPGRK.mjs';
4
4
  import '../chunk-NZLOLMT2.mjs';
5
5
  import '../chunk-RPTLVIBF.mjs';
@@ -37,14 +37,14 @@ interface TableProps<T = Record<string, unknown>> extends TableProps$1<T> {
37
37
  pageSize: number;
38
38
  }) => void;
39
39
  /**
40
- * Expanded rows change handler
40
+ * Expand change handler
41
41
  */
42
- onExpandedRowsChange?: (expandedRowKeys: (string | number)[]) => void;
42
+ onExpandChange?: (expandedKeys: (string | number)[], record: T, expanded: boolean) => void;
43
43
  /**
44
44
  * Additional CSS classes
45
45
  */
46
46
  className?: string;
47
47
  }
48
- declare function Table<T extends Record<string, unknown> = Record<string, unknown>>({ columns, columnLockable, dataSource, sort, defaultSort, filters, defaultFilters, size, bordered, striped, hoverable, loading, emptyText, pagination, rowSelection, rowKey, rowClassName, stickyHeader, maxHeight, tableLayout, expandable, onChange, onRowClick, onSelectionChange, onSortChange, onFilterChange, onPageChange, onExpandedRowsChange, className, ...props }: TableProps<T>): react_jsx_runtime.JSX.Element;
48
+ declare function Table<T extends Record<string, unknown> = Record<string, unknown>>({ columns, columnLockable, dataSource, sort, defaultSort, filters, defaultFilters, size, bordered, striped, hoverable, loading, emptyText, pagination, rowSelection, expandable, rowKey, rowClassName, stickyHeader, maxHeight, tableLayout, onChange, onRowClick, onSelectionChange, onSortChange, onFilterChange, onPageChange, onExpandChange, className, ...props }: TableProps<T>): react_jsx_runtime.JSX.Element;
49
49
 
50
50
  export { Table, type TableProps };
@@ -37,14 +37,14 @@ interface TableProps<T = Record<string, unknown>> extends TableProps$1<T> {
37
37
  pageSize: number;
38
38
  }) => void;
39
39
  /**
40
- * Expanded rows change handler
40
+ * Expand change handler
41
41
  */
42
- onExpandedRowsChange?: (expandedRowKeys: (string | number)[]) => void;
42
+ onExpandChange?: (expandedKeys: (string | number)[], record: T, expanded: boolean) => void;
43
43
  /**
44
44
  * Additional CSS classes
45
45
  */
46
46
  className?: string;
47
47
  }
48
- declare function Table<T extends Record<string, unknown> = Record<string, unknown>>({ columns, columnLockable, dataSource, sort, defaultSort, filters, defaultFilters, size, bordered, striped, hoverable, loading, emptyText, pagination, rowSelection, rowKey, rowClassName, stickyHeader, maxHeight, tableLayout, expandable, onChange, onRowClick, onSelectionChange, onSortChange, onFilterChange, onPageChange, onExpandedRowsChange, className, ...props }: TableProps<T>): react_jsx_runtime.JSX.Element;
48
+ declare function Table<T extends Record<string, unknown> = Record<string, unknown>>({ columns, columnLockable, dataSource, sort, defaultSort, filters, defaultFilters, size, bordered, striped, hoverable, loading, emptyText, pagination, rowSelection, expandable, rowKey, rowClassName, stickyHeader, maxHeight, tableLayout, onChange, onRowClick, onSelectionChange, onSortChange, onFilterChange, onPageChange, onExpandChange, className, ...props }: TableProps<T>): react_jsx_runtime.JSX.Element;
49
49
 
50
50
  export { Table, type TableProps };
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunk6OVVMHZJ_js = require('../chunk-6OVVMHZJ.js');
3
+ var chunkZBVFM3GJ_js = require('../chunk-ZBVFM3GJ.js');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "Table", {
8
8
  enumerable: true,
9
- get: function () { return chunk6OVVMHZJ_js.Table; }
9
+ get: function () { return chunkZBVFM3GJ_js.Table; }
10
10
  });
@@ -1 +1 @@
1
- export { Table } from '../chunk-PJ7NS7NX.mjs';
1
+ export { Table } from '../chunk-KBTFBEPE.mjs';
package/dist/index.js CHANGED
@@ -44,8 +44,8 @@ var chunkIHH2O7YK_js = require('./chunk-IHH2O7YK.js');
44
44
  var chunkEHYSER2Z_js = require('./chunk-EHYSER2Z.js');
45
45
  var chunk3T7L3MHX_js = require('./chunk-3T7L3MHX.js');
46
46
  var chunkU3JOBIDU_js = require('./chunk-U3JOBIDU.js');
47
- var chunkQ7GUWWG5_js = require('./chunk-Q7GUWWG5.js');
48
- var chunk6OVVMHZJ_js = require('./chunk-6OVVMHZJ.js');
47
+ var chunkLXX2ZDJN_js = require('./chunk-LXX2ZDJN.js');
48
+ var chunkZBVFM3GJ_js = require('./chunk-ZBVFM3GJ.js');
49
49
  var chunkTDRINUMH_js = require('./chunk-TDRINUMH.js');
50
50
  var chunk3GW3UAKB_js = require('./chunk-3GW3UAKB.js');
51
51
  var chunkKAWE5LQZ_js = require('./chunk-KAWE5LQZ.js');
@@ -312,11 +312,11 @@ Object.defineProperty(exports, "ImageCropper", {
312
312
  });
313
313
  Object.defineProperty(exports, "DataTableWithToolbar", {
314
314
  enumerable: true,
315
- get: function () { return chunkQ7GUWWG5_js.DataTableWithToolbar; }
315
+ get: function () { return chunkLXX2ZDJN_js.DataTableWithToolbar; }
316
316
  });
317
317
  Object.defineProperty(exports, "Table", {
318
318
  enumerable: true,
319
- get: function () { return chunk6OVVMHZJ_js.Table; }
319
+ get: function () { return chunkZBVFM3GJ_js.Table; }
320
320
  });
321
321
  Object.defineProperty(exports, "Select", {
322
322
  enumerable: true,
package/dist/index.mjs CHANGED
@@ -42,8 +42,8 @@ export { Icon } from './chunk-TUA5PDRX.mjs';
42
42
  export { CropUpload } from './chunk-QFYS5QIZ.mjs';
43
43
  export { Modal } from './chunk-JNLX47UL.mjs';
44
44
  export { ImageCropper } from './chunk-2EOXY2LP.mjs';
45
- export { DataTableWithToolbar } from './chunk-FX2IBA4W.mjs';
46
- export { Table } from './chunk-PJ7NS7NX.mjs';
45
+ export { DataTableWithToolbar } from './chunk-LLHUBM6E.mjs';
46
+ export { Table } from './chunk-KBTFBEPE.mjs';
47
47
  export { Select } from './chunk-MDZDPGRK.mjs';
48
48
  export { Pagination } from './chunk-NZLOLMT2.mjs';
49
49
  export { DatePicker } from './chunk-ZFHTSHXS.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expcat/tigercat-react",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "React components for Tigercat UI library",
5
5
  "license": "MIT",
6
6
  "author": "Yizhe Wang",
@@ -42,7 +42,7 @@
42
42
  "access": "public"
43
43
  },
44
44
  "dependencies": {
45
- "@expcat/tigercat-core": "0.4.2"
45
+ "@expcat/tigercat-core": "0.4.3"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^25.0.3",