@stokr/components-library 2.3.65-beta.8 → 2.3.65-beta.9
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.
|
@@ -18,6 +18,31 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
18
18
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
19
19
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
20
20
|
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); }
|
|
21
|
+
// Interactive elements that should NOT trigger row click
|
|
22
|
+
const INTERACTIVE_ELEMENTS = ['button', 'a', 'input', 'select', 'textarea', 'label'];
|
|
23
|
+
|
|
24
|
+
// Check if an element or its parents are interactive
|
|
25
|
+
const isInteractiveElement = element => {
|
|
26
|
+
let current = element;
|
|
27
|
+
while (current && current.tagName !== 'TR') {
|
|
28
|
+
var _current$tagName, _current$getAttribute, _current, _current$dataset;
|
|
29
|
+
const tagName = (_current$tagName = current.tagName) === null || _current$tagName === void 0 ? void 0 : _current$tagName.toLowerCase();
|
|
30
|
+
if (INTERACTIVE_ELEMENTS.includes(tagName)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
// Check for role="button" or other interactive roles
|
|
34
|
+
const role = (_current$getAttribute = (_current = current).getAttribute) === null || _current$getAttribute === void 0 ? void 0 : _current$getAttribute.call(_current, 'role');
|
|
35
|
+
if (role === 'button' || role === 'link') {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
// Check for data-clickable attribute (escape hatch for custom interactive elements)
|
|
39
|
+
if (((_current$dataset = current.dataset) === null || _current$dataset === void 0 ? void 0 : _current$dataset.clickable) === 'true') {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
current = current.parentElement;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
21
46
|
function ReactTable(props) {
|
|
22
47
|
const {
|
|
23
48
|
columns,
|
|
@@ -37,6 +62,19 @@ function ReactTable(props) {
|
|
|
37
62
|
getRowDataCy,
|
|
38
63
|
// Function to generate data-cy attribute: (rowData, rowIndex) => string
|
|
39
64
|
|
|
65
|
+
// Row click handler: (rowData, rowIndex, event) => void
|
|
66
|
+
// Will NOT trigger if clicking on buttons, links, inputs, etc.
|
|
67
|
+
onRowClick,
|
|
68
|
+
// Custom expanded content renderer: (row, toggleExpanded) => ReactNode
|
|
69
|
+
// If provided, this will be used instead of the sub-table
|
|
70
|
+
renderExpandedContent,
|
|
71
|
+
// Header click handler: (column, event) => void
|
|
72
|
+
// Called when a header cell is clicked (useful for sorting/filtering)
|
|
73
|
+
// Won't trigger if clicking on interactive elements inside header
|
|
74
|
+
onHeaderClick,
|
|
75
|
+
// Render custom header content: (column, defaultContent) => ReactNode
|
|
76
|
+
// Allows wrapping/replacing header content (e.g., add sort icons, dropdowns)
|
|
77
|
+
renderHeaderContent,
|
|
40
78
|
//instead of passing the subData, we pass a function that will calculate the subData
|
|
41
79
|
//subData must be part of the data array (an array or whatever)
|
|
42
80
|
//calculateSubData is a function that receives the row and returns the subData
|
|
@@ -75,6 +113,17 @@ function ReactTable(props) {
|
|
|
75
113
|
setInputPageSize(pageSize);
|
|
76
114
|
}, [pageSize]);
|
|
77
115
|
|
|
116
|
+
// Handle row click with interactive element detection
|
|
117
|
+
const handleRowClick = (0, _react.useCallback)((row, rowIndex, event) => {
|
|
118
|
+
if (!onRowClick) return;
|
|
119
|
+
|
|
120
|
+
// Don't trigger if clicking on interactive elements
|
|
121
|
+
if (isInteractiveElement(event.target)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
onRowClick(row.original, rowIndex, event);
|
|
125
|
+
}, [onRowClick]);
|
|
126
|
+
|
|
78
127
|
// Function to render cell content with hover support
|
|
79
128
|
const renderCellContent = (cell, rowIndex, rowData) => {
|
|
80
129
|
if (customRowHoverContent && hoveredRowIndex === rowIndex) {
|
|
@@ -85,21 +134,65 @@ function ReactTable(props) {
|
|
|
85
134
|
}
|
|
86
135
|
return cell.render('Cell');
|
|
87
136
|
};
|
|
137
|
+
|
|
138
|
+
// Determine if row should have expand functionality
|
|
139
|
+
const shouldEnableExpand = withSubTable || renderExpandedContent;
|
|
140
|
+
|
|
141
|
+
// Handle header click with interactive element detection
|
|
142
|
+
const handleHeaderClick = (0, _react.useCallback)((column, event) => {
|
|
143
|
+
// Check for column-level click handler first
|
|
144
|
+
if (column.onHeaderClick) {
|
|
145
|
+
// Don't trigger if clicking on interactive elements
|
|
146
|
+
if (!isInteractiveElement(event.target)) {
|
|
147
|
+
column.onHeaderClick(column, event);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Fall back to global onHeaderClick
|
|
153
|
+
if (!onHeaderClick) return;
|
|
154
|
+
|
|
155
|
+
// Don't trigger if clicking on interactive elements inside header
|
|
156
|
+
if (isInteractiveElement(event.target)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
onHeaderClick(column, event);
|
|
160
|
+
}, [onHeaderClick]);
|
|
161
|
+
|
|
162
|
+
// Render header content with optional custom rendering
|
|
163
|
+
const renderHeader = column => {
|
|
164
|
+
const defaultContent = column.render('Header');
|
|
165
|
+
|
|
166
|
+
// If renderHeaderContent is provided, use it to wrap/modify the header
|
|
167
|
+
if (renderHeaderContent) {
|
|
168
|
+
return renderHeaderContent(column, defaultContent);
|
|
169
|
+
}
|
|
170
|
+
return defaultContent;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Check if header should be clickable
|
|
174
|
+
const isHeaderClickable = column => {
|
|
175
|
+
return column.onHeaderClick || onHeaderClick;
|
|
176
|
+
};
|
|
88
177
|
return /*#__PURE__*/_react.default.createElement(_Table.Styles, null, /*#__PURE__*/_react.default.createElement(_Table.TableWrap, {
|
|
89
178
|
style: tableWrapStyles
|
|
90
179
|
}, /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable, _extends({}, getTableProps(), {
|
|
91
180
|
customTableStyles: customTableStyles
|
|
92
181
|
}), /*#__PURE__*/_react.default.createElement("thead", null, headerGroups.map(headerGroup => /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Tr, headerGroup.getHeaderGroupProps(), headerGroup.headers.map(column => {
|
|
93
182
|
const cellStyles = customThStyles ? customThStyles(column) : {};
|
|
183
|
+
const clickable = isHeaderClickable(column);
|
|
94
184
|
return /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Th, _extends({}, column.getHeaderProps({
|
|
95
185
|
className: column.collapse ? 'collapse' : '',
|
|
96
|
-
style: _objectSpread({}, cellStyles)
|
|
186
|
+
style: _objectSpread(_objectSpread({}, cellStyles), clickable ? {
|
|
187
|
+
cursor: 'pointer'
|
|
188
|
+
} : {})
|
|
97
189
|
}), {
|
|
98
190
|
blue: blue,
|
|
99
191
|
width: column.width,
|
|
100
192
|
minWidth: column.minWidth,
|
|
101
|
-
maxWidth: column.maxWidth
|
|
102
|
-
|
|
193
|
+
maxWidth: column.maxWidth,
|
|
194
|
+
onClick: clickable ? e => handleHeaderClick(column, e) : undefined
|
|
195
|
+
}), renderHeader(column));
|
|
103
196
|
})))), /*#__PURE__*/_react.default.createElement("tbody", getTableBodyProps(), page.map((row, i) => {
|
|
104
197
|
prepareRow(row);
|
|
105
198
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, {
|
|
@@ -112,10 +205,17 @@ function ReactTable(props) {
|
|
|
112
205
|
rowIndex: i,
|
|
113
206
|
rowData: row.original,
|
|
114
207
|
onMouseEnter: () => setHoveredRowIndex(i),
|
|
115
|
-
onMouseLeave: () => setHoveredRowIndex(null)
|
|
208
|
+
onMouseLeave: () => setHoveredRowIndex(null),
|
|
209
|
+
onClick: e => handleRowClick(row, i, e),
|
|
210
|
+
style: onRowClick ? {
|
|
211
|
+
cursor: 'pointer'
|
|
212
|
+
} : undefined
|
|
116
213
|
}), row.cells.map(cell => {
|
|
117
214
|
const cellStyles = customTdStyles ? customTdStyles(i, row.original, cell.column) : {};
|
|
118
|
-
|
|
215
|
+
|
|
216
|
+
// Only apply expand toggle props if expansion is enabled
|
|
217
|
+
const expandProps = shouldEnableExpand ? cell.row.getToggleRowExpandedProps() : {};
|
|
218
|
+
return /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Td, _extends({}, expandProps, {
|
|
119
219
|
title: ""
|
|
120
220
|
}, cell.getCellProps({
|
|
121
221
|
className: cell.column.collapse ? 'collapse' : '',
|
|
@@ -126,7 +226,12 @@ function ReactTable(props) {
|
|
|
126
226
|
minWidth: cell.column.minWidth,
|
|
127
227
|
maxWidth: cell.column.maxWidth
|
|
128
228
|
}), renderCellContent(cell, i, row.original));
|
|
129
|
-
})),
|
|
229
|
+
})), renderExpandedContent && row.isExpanded && /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Tr, {
|
|
230
|
+
key: "".concat(row.id, "-expanded")
|
|
231
|
+
}, /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Td, {
|
|
232
|
+
colSpan: visibleColumns.length,
|
|
233
|
+
subTable: true
|
|
234
|
+
}, renderExpandedContent(row, row.toggleRowExpanded))), withSubTable && !renderExpandedContent && row.isExpanded && /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Tr, {
|
|
130
235
|
key: "".concat(row.id, "-").concat(i)
|
|
131
236
|
}, /*#__PURE__*/_react.default.createElement(_Table.StyledReactTable.Td, {
|
|
132
237
|
colSpan: visibleColumns.length,
|
|
@@ -160,7 +265,18 @@ ReactTable.propTypes = {
|
|
|
160
265
|
customRowHoverContent: _propTypes.default.func,
|
|
161
266
|
customRowStyles: _propTypes.default.func,
|
|
162
267
|
customTableStyles: _propTypes.default.func,
|
|
163
|
-
|
|
268
|
+
tableWrapStyles: _propTypes.default.object,
|
|
269
|
+
customTdStyles: _propTypes.default.func,
|
|
270
|
+
customThStyles: _propTypes.default.func,
|
|
271
|
+
getRowDataCy: _propTypes.default.func,
|
|
272
|
+
// (rowData, rowIndex) => string
|
|
273
|
+
onRowClick: _propTypes.default.func,
|
|
274
|
+
// (rowData, rowIndex, event) => void
|
|
275
|
+
renderExpandedContent: _propTypes.default.func,
|
|
276
|
+
// (row, toggleExpanded) => ReactNode
|
|
277
|
+
onHeaderClick: _propTypes.default.func,
|
|
278
|
+
// (column, event) => void
|
|
279
|
+
renderHeaderContent: _propTypes.default.func // (column, defaultContent) => ReactNode
|
|
164
280
|
};
|
|
165
281
|
ReactTable.defaultProps = {
|
|
166
282
|
blue: false,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = exports.WrapperWithSubTable = exports.WithoutPagination = exports.WithSubTable = exports.WithStatusBasedHover = exports.WithRowSpecificHover = exports.WithRowHover = exports.WithHoverStylesAndContent = exports.WithHoverContent = exports.WithFixedColumnWidths = exports.WithCustomStyling = exports.DefaultWrapper = exports.Default = exports.CustomStyledTable = exports.BoxStyleTable = exports.BlueWrapper = exports.BlueTable = void 0;
|
|
6
|
+
exports.default = exports.WrapperWithSubTable = exports.WithoutPagination = exports.WithSubTable = exports.WithStatusBasedHover = exports.WithRowSpecificHover = exports.WithRowHover = exports.WithRowClick = exports.WithHoverStylesAndContent = exports.WithHoverContent = exports.WithFixedColumnWidths = exports.WithCustomStyling = exports.SortableHeaders = exports.RowClickWithExpandedContent = exports.RowClickWithButtons = exports.PerColumnHeaderClick = exports.HeaderClick = exports.FilterableHeaders = exports.ExpandedWithRichContent = exports.DefaultWrapper = exports.Default = exports.CustomStyledTable = exports.CustomExpandedContent = exports.BoxStyleTable = exports.BlueWrapper = exports.BlueTable = void 0;
|
|
7
7
|
var _react = _interopRequireDefault(require("react"));
|
|
8
8
|
var _ReactTable = require("./ReactTable");
|
|
9
9
|
var _ReactTableWrapper = require("./ReactTableWrapper");
|
|
@@ -403,4 +403,511 @@ CustomStyledTable.args = _objectSpread(_objectSpread({}, Default.args), {}, {
|
|
|
403
403
|
textTransform: 'uppercase',
|
|
404
404
|
letterSpacing: '0.5px'
|
|
405
405
|
})
|
|
406
|
-
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// ============================================
|
|
409
|
+
// NEW FEATURE STORIES: onRowClick & renderExpandedContent
|
|
410
|
+
// ============================================
|
|
411
|
+
|
|
412
|
+
// Row Click Handler - Basic
|
|
413
|
+
const WithRowClick = exports.WithRowClick = Template.bind({});
|
|
414
|
+
WithRowClick.args = _objectSpread(_objectSpread({}, Default.args), {}, {
|
|
415
|
+
onRowClick: (rowData, rowIndex, event) => {
|
|
416
|
+
alert("Clicked row ".concat(rowIndex + 1, ": ").concat(rowData.name, " (").concat(rowData.status, ")"));
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
WithRowClick.parameters = {
|
|
420
|
+
docs: {
|
|
421
|
+
description: {
|
|
422
|
+
story: 'Click anywhere on a row to trigger an action. Buttons and links inside cells will NOT trigger the row click.'
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// Row Click with Buttons Inside - Demonstrates click isolation
|
|
428
|
+
const columnsWithActions = [...columns.slice(0, 3), {
|
|
429
|
+
Header: 'Actions',
|
|
430
|
+
accessor: 'actions',
|
|
431
|
+
width: '40%',
|
|
432
|
+
Cell: _ref => {
|
|
433
|
+
let {
|
|
434
|
+
row
|
|
435
|
+
} = _ref;
|
|
436
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
437
|
+
style: {
|
|
438
|
+
display: 'flex',
|
|
439
|
+
gap: '8px'
|
|
440
|
+
}
|
|
441
|
+
}, /*#__PURE__*/_react.default.createElement("button", {
|
|
442
|
+
style: {
|
|
443
|
+
padding: '6px 12px',
|
|
444
|
+
backgroundColor: '#0050ca',
|
|
445
|
+
color: 'white',
|
|
446
|
+
border: 'none',
|
|
447
|
+
borderRadius: '4px',
|
|
448
|
+
cursor: 'pointer'
|
|
449
|
+
},
|
|
450
|
+
onClick: () => alert("Edit button clicked for ".concat(row.original.name))
|
|
451
|
+
}, "Edit"), /*#__PURE__*/_react.default.createElement("button", {
|
|
452
|
+
style: {
|
|
453
|
+
padding: '6px 12px',
|
|
454
|
+
backgroundColor: '#dc3545',
|
|
455
|
+
color: 'white',
|
|
456
|
+
border: 'none',
|
|
457
|
+
borderRadius: '4px',
|
|
458
|
+
cursor: 'pointer'
|
|
459
|
+
},
|
|
460
|
+
onClick: () => alert("Delete button clicked for ".concat(row.original.name))
|
|
461
|
+
}, "Delete"));
|
|
462
|
+
}
|
|
463
|
+
}];
|
|
464
|
+
const RowClickWithButtons = exports.RowClickWithButtons = Template.bind({});
|
|
465
|
+
RowClickWithButtons.args = {
|
|
466
|
+
columns: columnsWithActions,
|
|
467
|
+
data: data,
|
|
468
|
+
noPagination: false,
|
|
469
|
+
onRowClick: (rowData, rowIndex) => {
|
|
470
|
+
alert("Row clicked: ".concat(rowData.name));
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
RowClickWithButtons.parameters = {
|
|
474
|
+
docs: {
|
|
475
|
+
description: {
|
|
476
|
+
story: 'Demonstrates that clicking buttons inside cells does NOT trigger onRowClick. Only clicking on non-interactive areas triggers the row click.'
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// Custom Expanded Content - Simple
|
|
482
|
+
const CustomExpandedContent = exports.CustomExpandedContent = Template.bind({});
|
|
483
|
+
CustomExpandedContent.args = _objectSpread(_objectSpread({}, Default.args), {}, {
|
|
484
|
+
renderExpandedContent: (row, toggleExpanded) => {
|
|
485
|
+
var _row$original$subData;
|
|
486
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
487
|
+
style: {
|
|
488
|
+
padding: '20px',
|
|
489
|
+
backgroundColor: '#f8f9fa',
|
|
490
|
+
borderRadius: '8px'
|
|
491
|
+
}
|
|
492
|
+
}, /*#__PURE__*/_react.default.createElement("h4", {
|
|
493
|
+
style: {
|
|
494
|
+
margin: '0 0 12px 0'
|
|
495
|
+
}
|
|
496
|
+
}, "Details for ", row.original.name), /*#__PURE__*/_react.default.createElement("p", {
|
|
497
|
+
style: {
|
|
498
|
+
margin: '0 0 8px 0'
|
|
499
|
+
}
|
|
500
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "ID:"), " ", row.original.id), /*#__PURE__*/_react.default.createElement("p", {
|
|
501
|
+
style: {
|
|
502
|
+
margin: '0 0 8px 0'
|
|
503
|
+
}
|
|
504
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "Status:"), " ", row.original.status), /*#__PURE__*/_react.default.createElement("p", {
|
|
505
|
+
style: {
|
|
506
|
+
margin: '0 0 16px 0'
|
|
507
|
+
}
|
|
508
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "Sub-items:"), " ", ((_row$original$subData = row.original.subData) === null || _row$original$subData === void 0 ? void 0 : _row$original$subData.length) || 0), /*#__PURE__*/_react.default.createElement("button", {
|
|
509
|
+
style: {
|
|
510
|
+
padding: '8px 16px',
|
|
511
|
+
backgroundColor: '#6c757d',
|
|
512
|
+
color: 'white',
|
|
513
|
+
border: 'none',
|
|
514
|
+
borderRadius: '4px',
|
|
515
|
+
cursor: 'pointer'
|
|
516
|
+
},
|
|
517
|
+
onClick: () => toggleExpanded()
|
|
518
|
+
}, "Collapse"));
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
CustomExpandedContent.parameters = {
|
|
522
|
+
docs: {
|
|
523
|
+
description: {
|
|
524
|
+
story: 'Click on a row to expand and show custom content instead of a sub-table. The toggleExpanded function allows you to collapse the row programmatically.'
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// Custom Expanded Content - Rich Component
|
|
530
|
+
const ExpandedWithRichContent = exports.ExpandedWithRichContent = Template.bind({});
|
|
531
|
+
ExpandedWithRichContent.args = _objectSpread(_objectSpread({}, Default.args), {}, {
|
|
532
|
+
renderExpandedContent: row => {
|
|
533
|
+
var _row$original$subData2;
|
|
534
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
535
|
+
style: {
|
|
536
|
+
padding: '24px'
|
|
537
|
+
}
|
|
538
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
539
|
+
style: {
|
|
540
|
+
display: 'grid',
|
|
541
|
+
gridTemplateColumns: '1fr 1fr',
|
|
542
|
+
gap: '24px'
|
|
543
|
+
}
|
|
544
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
545
|
+
style: {
|
|
546
|
+
padding: '16px',
|
|
547
|
+
backgroundColor: '#fff',
|
|
548
|
+
border: '1px solid #e1e1e1',
|
|
549
|
+
borderRadius: '8px'
|
|
550
|
+
}
|
|
551
|
+
}, /*#__PURE__*/_react.default.createElement("h4", {
|
|
552
|
+
style: {
|
|
553
|
+
margin: '0 0 16px 0',
|
|
554
|
+
color: '#0050ca'
|
|
555
|
+
}
|
|
556
|
+
}, "User Information"), /*#__PURE__*/_react.default.createElement("div", {
|
|
557
|
+
style: {
|
|
558
|
+
display: 'flex',
|
|
559
|
+
flexDirection: 'column',
|
|
560
|
+
gap: '8px'
|
|
561
|
+
}
|
|
562
|
+
}, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("strong", null, "Name:"), " ", row.original.name), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("strong", null, "ID:"), " #", row.original.id), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("strong", null, "Status:"), ' ', /*#__PURE__*/_react.default.createElement("span", {
|
|
563
|
+
style: {
|
|
564
|
+
padding: '2px 8px',
|
|
565
|
+
borderRadius: '12px',
|
|
566
|
+
backgroundColor: row.original.status === 'Active' ? '#d4edda' : row.original.status === 'Inactive' ? '#f8d7da' : '#fff3cd',
|
|
567
|
+
color: row.original.status === 'Active' ? '#155724' : row.original.status === 'Inactive' ? '#721c24' : '#856404',
|
|
568
|
+
fontSize: '12px'
|
|
569
|
+
}
|
|
570
|
+
}, row.original.status)))), /*#__PURE__*/_react.default.createElement("div", {
|
|
571
|
+
style: {
|
|
572
|
+
padding: '16px',
|
|
573
|
+
backgroundColor: '#fff',
|
|
574
|
+
border: '1px solid #e1e1e1',
|
|
575
|
+
borderRadius: '8px'
|
|
576
|
+
}
|
|
577
|
+
}, /*#__PURE__*/_react.default.createElement("h4", {
|
|
578
|
+
style: {
|
|
579
|
+
margin: '0 0 16px 0',
|
|
580
|
+
color: '#0050ca'
|
|
581
|
+
}
|
|
582
|
+
}, "Sub Items"), ((_row$original$subData2 = row.original.subData) === null || _row$original$subData2 === void 0 ? void 0 : _row$original$subData2.length) > 0 ? /*#__PURE__*/_react.default.createElement("ul", {
|
|
583
|
+
style: {
|
|
584
|
+
margin: 0,
|
|
585
|
+
paddingLeft: '20px'
|
|
586
|
+
}
|
|
587
|
+
}, row.original.subData.map(item => /*#__PURE__*/_react.default.createElement("li", {
|
|
588
|
+
key: item.detailId,
|
|
589
|
+
style: {
|
|
590
|
+
marginBottom: '8px'
|
|
591
|
+
}
|
|
592
|
+
}, item.detailName, " (ID: ", item.detailId, ")"))) : /*#__PURE__*/_react.default.createElement("p", {
|
|
593
|
+
style: {
|
|
594
|
+
margin: 0,
|
|
595
|
+
color: '#6c757d',
|
|
596
|
+
fontStyle: 'italic'
|
|
597
|
+
}
|
|
598
|
+
}, "No sub-items"))), /*#__PURE__*/_react.default.createElement("div", {
|
|
599
|
+
style: {
|
|
600
|
+
marginTop: '16px',
|
|
601
|
+
display: 'flex',
|
|
602
|
+
gap: '8px',
|
|
603
|
+
justifyContent: 'flex-end'
|
|
604
|
+
}
|
|
605
|
+
}, /*#__PURE__*/_react.default.createElement("button", {
|
|
606
|
+
style: {
|
|
607
|
+
padding: '8px 16px',
|
|
608
|
+
backgroundColor: '#0050ca',
|
|
609
|
+
color: 'white',
|
|
610
|
+
border: 'none',
|
|
611
|
+
borderRadius: '4px',
|
|
612
|
+
cursor: 'pointer'
|
|
613
|
+
},
|
|
614
|
+
onClick: () => alert("Edit ".concat(row.original.name))
|
|
615
|
+
}, "Edit User"), /*#__PURE__*/_react.default.createElement("button", {
|
|
616
|
+
style: {
|
|
617
|
+
padding: '8px 16px',
|
|
618
|
+
backgroundColor: 'transparent',
|
|
619
|
+
color: '#0050ca',
|
|
620
|
+
border: '1px solid #0050ca',
|
|
621
|
+
borderRadius: '4px',
|
|
622
|
+
cursor: 'pointer'
|
|
623
|
+
},
|
|
624
|
+
onClick: () => alert("View full profile for ".concat(row.original.name))
|
|
625
|
+
}, "View Profile")));
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
ExpandedWithRichContent.parameters = {
|
|
629
|
+
docs: {
|
|
630
|
+
description: {
|
|
631
|
+
story: 'A more complex example showing a rich expanded content with multiple panels, styled badges, and action buttons.'
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// Combined: Row Click + Custom Expanded Content
|
|
637
|
+
const RowClickWithExpandedContent = exports.RowClickWithExpandedContent = Template.bind({});
|
|
638
|
+
RowClickWithExpandedContent.args = {
|
|
639
|
+
columns: columnsWithActions,
|
|
640
|
+
data: data,
|
|
641
|
+
noPagination: false,
|
|
642
|
+
onRowClick: (rowData, rowIndex) => {
|
|
643
|
+
console.log('Row clicked (but not triggering anything in this demo)');
|
|
644
|
+
},
|
|
645
|
+
renderExpandedContent: (row, toggleExpanded) => /*#__PURE__*/_react.default.createElement("div", {
|
|
646
|
+
style: {
|
|
647
|
+
padding: '20px',
|
|
648
|
+
backgroundColor: '#e3f2fd',
|
|
649
|
+
borderLeft: '4px solid #0050ca'
|
|
650
|
+
}
|
|
651
|
+
}, /*#__PURE__*/_react.default.createElement("p", {
|
|
652
|
+
style: {
|
|
653
|
+
margin: '0 0 12px 0'
|
|
654
|
+
}
|
|
655
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "Expanded details for:"), " ", row.original.name), /*#__PURE__*/_react.default.createElement("p", {
|
|
656
|
+
style: {
|
|
657
|
+
margin: 0,
|
|
658
|
+
color: '#666'
|
|
659
|
+
}
|
|
660
|
+
}, "Click anywhere on the row to expand/collapse. Buttons work independently."))
|
|
661
|
+
};
|
|
662
|
+
RowClickWithExpandedContent.parameters = {
|
|
663
|
+
docs: {
|
|
664
|
+
description: {
|
|
665
|
+
story: 'Combined example: rows are clickable AND expandable. The onRowClick and renderExpandedContent work together. Buttons inside cells remain independent.'
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
// ============================================
|
|
671
|
+
// HEADER CLICK STORIES: onHeaderClick & renderHeaderContent
|
|
672
|
+
// ============================================
|
|
673
|
+
|
|
674
|
+
// Basic Header Click - shows alert
|
|
675
|
+
const HeaderClick = exports.HeaderClick = Template.bind({});
|
|
676
|
+
HeaderClick.args = _objectSpread(_objectSpread({}, Default.args), {}, {
|
|
677
|
+
onHeaderClick: (column, event) => {
|
|
678
|
+
alert("Header clicked: ".concat(column.id || column.Header));
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
HeaderClick.parameters = {
|
|
682
|
+
docs: {
|
|
683
|
+
description: {
|
|
684
|
+
story: 'Click on any column header to trigger an action. Useful for implementing custom sorting or filtering.'
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
// Header Click with Sort State (External Control)
|
|
690
|
+
const SortableTableDemo = () => {
|
|
691
|
+
const [sortConfig, setSortConfig] = _react.default.useState({
|
|
692
|
+
key: null,
|
|
693
|
+
direction: 'asc'
|
|
694
|
+
});
|
|
695
|
+
const [tableData, setTableData] = _react.default.useState(data);
|
|
696
|
+
const handleHeaderClick = column => {
|
|
697
|
+
// Skip non-sortable columns (like actions)
|
|
698
|
+
if (column.id === 'dropdown' || column.id === 'actions') return;
|
|
699
|
+
let direction = 'asc';
|
|
700
|
+
if (sortConfig.key === column.id && sortConfig.direction === 'asc') {
|
|
701
|
+
direction = 'desc';
|
|
702
|
+
}
|
|
703
|
+
setSortConfig({
|
|
704
|
+
key: column.id,
|
|
705
|
+
direction
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// Sort the data
|
|
709
|
+
const sorted = [...data].sort((a, b) => {
|
|
710
|
+
const aVal = a[column.id];
|
|
711
|
+
const bVal = b[column.id];
|
|
712
|
+
if (aVal < bVal) return direction === 'asc' ? -1 : 1;
|
|
713
|
+
if (aVal > bVal) return direction === 'asc' ? 1 : -1;
|
|
714
|
+
return 0;
|
|
715
|
+
});
|
|
716
|
+
setTableData(sorted);
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
// Add sort indicators to headers
|
|
720
|
+
const renderHeaderContent = (column, defaultContent) => {
|
|
721
|
+
// Skip non-sortable columns
|
|
722
|
+
if (column.id === 'dropdown' || column.id === 'actions') {
|
|
723
|
+
return defaultContent;
|
|
724
|
+
}
|
|
725
|
+
const isSorted = sortConfig.key === column.id;
|
|
726
|
+
const arrow = isSorted ? sortConfig.direction === 'asc' ? ' ↑' : ' ↓' : '';
|
|
727
|
+
return /*#__PURE__*/_react.default.createElement("span", {
|
|
728
|
+
style: {
|
|
729
|
+
display: 'flex',
|
|
730
|
+
alignItems: 'center',
|
|
731
|
+
gap: '4px'
|
|
732
|
+
}
|
|
733
|
+
}, defaultContent, /*#__PURE__*/_react.default.createElement("span", {
|
|
734
|
+
style: {
|
|
735
|
+
opacity: isSorted ? 1 : 0.3
|
|
736
|
+
}
|
|
737
|
+
}, isSorted ? arrow : ' ↕'));
|
|
738
|
+
};
|
|
739
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_global.default, null), /*#__PURE__*/_react.default.createElement("div", {
|
|
740
|
+
style: {
|
|
741
|
+
marginBottom: '16px'
|
|
742
|
+
}
|
|
743
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "Current sort:"), ' ', sortConfig.key ? "".concat(sortConfig.key, " (").concat(sortConfig.direction, ")") : 'None'), /*#__PURE__*/_react.default.createElement(_ReactTable.ReactTable, {
|
|
744
|
+
columns: columns,
|
|
745
|
+
data: tableData,
|
|
746
|
+
noPagination: false,
|
|
747
|
+
onHeaderClick: handleHeaderClick,
|
|
748
|
+
renderHeaderContent: renderHeaderContent
|
|
749
|
+
}));
|
|
750
|
+
};
|
|
751
|
+
const SortableHeaders = exports.SortableHeaders = {
|
|
752
|
+
render: () => /*#__PURE__*/_react.default.createElement(SortableTableDemo, null),
|
|
753
|
+
parameters: {
|
|
754
|
+
docs: {
|
|
755
|
+
description: {
|
|
756
|
+
story: 'External sorting controlled by parent component. Click headers to sort. Uses onHeaderClick for the action and renderHeaderContent for the sort indicators.'
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
// Header with Custom Dropdown Filter
|
|
763
|
+
const FilterableTableDemo = () => {
|
|
764
|
+
const [filters, setFilters] = _react.default.useState({});
|
|
765
|
+
const [activeDropdown, setActiveDropdown] = _react.default.useState(null);
|
|
766
|
+
const [tableData, setTableData] = _react.default.useState(data);
|
|
767
|
+
|
|
768
|
+
// Get unique values for a column
|
|
769
|
+
const getUniqueValues = columnId => {
|
|
770
|
+
return [...new Set(data.map(row => row[columnId]))];
|
|
771
|
+
};
|
|
772
|
+
const handleFilter = (columnId, value) => {
|
|
773
|
+
const newFilters = _objectSpread({}, filters);
|
|
774
|
+
if (value === 'all') {
|
|
775
|
+
delete newFilters[columnId];
|
|
776
|
+
} else {
|
|
777
|
+
newFilters[columnId] = value;
|
|
778
|
+
}
|
|
779
|
+
setFilters(newFilters);
|
|
780
|
+
setActiveDropdown(null);
|
|
781
|
+
|
|
782
|
+
// Apply filters
|
|
783
|
+
let filtered = [...data];
|
|
784
|
+
Object.keys(newFilters).forEach(key => {
|
|
785
|
+
filtered = filtered.filter(row => row[key] === newFilters[key]);
|
|
786
|
+
});
|
|
787
|
+
setTableData(filtered);
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// Custom header with filter dropdown
|
|
791
|
+
const renderHeaderContent = (column, defaultContent) => {
|
|
792
|
+
// Only add filter to specific columns
|
|
793
|
+
if (!['status'].includes(column.id)) {
|
|
794
|
+
return defaultContent;
|
|
795
|
+
}
|
|
796
|
+
const isActive = activeDropdown === column.id;
|
|
797
|
+
const hasFilter = filters[column.id];
|
|
798
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
799
|
+
style: {
|
|
800
|
+
position: 'relative'
|
|
801
|
+
}
|
|
802
|
+
}, /*#__PURE__*/_react.default.createElement("span", {
|
|
803
|
+
style: {
|
|
804
|
+
display: 'flex',
|
|
805
|
+
alignItems: 'center',
|
|
806
|
+
gap: '8px'
|
|
807
|
+
},
|
|
808
|
+
"data-clickable": "true",
|
|
809
|
+
onClick: e => {
|
|
810
|
+
e.stopPropagation();
|
|
811
|
+
setActiveDropdown(isActive ? null : column.id);
|
|
812
|
+
}
|
|
813
|
+
}, defaultContent, /*#__PURE__*/_react.default.createElement("span", {
|
|
814
|
+
style: {
|
|
815
|
+
fontSize: '10px',
|
|
816
|
+
padding: '2px 6px',
|
|
817
|
+
borderRadius: '4px',
|
|
818
|
+
backgroundColor: hasFilter ? '#0050ca' : '#e1e1e1',
|
|
819
|
+
color: hasFilter ? 'white' : '#666'
|
|
820
|
+
}
|
|
821
|
+
}, hasFilter ? '✓' : '▼')), isActive && /*#__PURE__*/_react.default.createElement("div", {
|
|
822
|
+
style: {
|
|
823
|
+
position: 'absolute',
|
|
824
|
+
top: '100%',
|
|
825
|
+
left: 0,
|
|
826
|
+
marginTop: '4px',
|
|
827
|
+
backgroundColor: 'white',
|
|
828
|
+
border: '1px solid #e1e1e1',
|
|
829
|
+
borderRadius: '4px',
|
|
830
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
|
|
831
|
+
zIndex: 100,
|
|
832
|
+
minWidth: '120px'
|
|
833
|
+
}
|
|
834
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
835
|
+
style: {
|
|
836
|
+
padding: '8px 12px',
|
|
837
|
+
cursor: 'pointer',
|
|
838
|
+
borderBottom: '1px solid #e1e1e1'
|
|
839
|
+
},
|
|
840
|
+
onClick: () => handleFilter(column.id, 'all')
|
|
841
|
+
}, "All"), getUniqueValues(column.id).map(value => /*#__PURE__*/_react.default.createElement("div", {
|
|
842
|
+
key: value,
|
|
843
|
+
style: {
|
|
844
|
+
padding: '8px 12px',
|
|
845
|
+
cursor: 'pointer',
|
|
846
|
+
backgroundColor: filters[column.id] === value ? '#f0f8ff' : 'transparent'
|
|
847
|
+
},
|
|
848
|
+
onClick: () => handleFilter(column.id, value)
|
|
849
|
+
}, value))));
|
|
850
|
+
};
|
|
851
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_global.default, null), /*#__PURE__*/_react.default.createElement("div", {
|
|
852
|
+
style: {
|
|
853
|
+
marginBottom: '16px'
|
|
854
|
+
}
|
|
855
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, "Active filters:"), ' ', Object.keys(filters).length > 0 ? Object.entries(filters).map(_ref2 => {
|
|
856
|
+
let [k, v] = _ref2;
|
|
857
|
+
return "".concat(k, ": ").concat(v);
|
|
858
|
+
}).join(', ') : 'None'), /*#__PURE__*/_react.default.createElement(_ReactTable.ReactTable, {
|
|
859
|
+
columns: columns,
|
|
860
|
+
data: tableData,
|
|
861
|
+
noPagination: false,
|
|
862
|
+
renderHeaderContent: renderHeaderContent
|
|
863
|
+
}));
|
|
864
|
+
};
|
|
865
|
+
const FilterableHeaders = exports.FilterableHeaders = {
|
|
866
|
+
render: () => /*#__PURE__*/_react.default.createElement(FilterableTableDemo, null),
|
|
867
|
+
parameters: {
|
|
868
|
+
docs: {
|
|
869
|
+
description: {
|
|
870
|
+
story: 'Custom filter dropdown in the "Status" header. Click the dropdown icon to filter. Uses renderHeaderContent to add the dropdown UI.'
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
// Per-Column Header Click Handler
|
|
877
|
+
const columnsWithColumnClick = [{
|
|
878
|
+
Header: 'ID (Click me!)',
|
|
879
|
+
accessor: 'id',
|
|
880
|
+
width: '15%',
|
|
881
|
+
onHeaderClick: column => {
|
|
882
|
+
alert('ID column has its own click handler!');
|
|
883
|
+
}
|
|
884
|
+
}, {
|
|
885
|
+
Header: 'Name',
|
|
886
|
+
accessor: 'name',
|
|
887
|
+
width: '30%'
|
|
888
|
+
}, {
|
|
889
|
+
Header: 'Status',
|
|
890
|
+
accessor: 'status',
|
|
891
|
+
width: '20%'
|
|
892
|
+
}, {
|
|
893
|
+
Header: 'Actions (No click)',
|
|
894
|
+
accessor: 'dropdown',
|
|
895
|
+
width: '35%'
|
|
896
|
+
// No onHeaderClick - won't trigger global onHeaderClick either
|
|
897
|
+
}];
|
|
898
|
+
const PerColumnHeaderClick = exports.PerColumnHeaderClick = Template.bind({});
|
|
899
|
+
PerColumnHeaderClick.args = {
|
|
900
|
+
columns: columnsWithColumnClick,
|
|
901
|
+
data: data,
|
|
902
|
+
noPagination: false,
|
|
903
|
+
onHeaderClick: column => {
|
|
904
|
+
alert("Global header click: ".concat(column.id));
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
PerColumnHeaderClick.parameters = {
|
|
908
|
+
docs: {
|
|
909
|
+
description: {
|
|
910
|
+
story: 'Columns can have their own onHeaderClick handlers. The "ID" column has a custom handler. Other columns use the global onHeaderClick. The "Actions" column has neither.'
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
};
|