pixelize-design-library 2.3.1-beta.3 → 2.3.1-beta.4

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.
@@ -20,7 +20,21 @@
20
20
  "Bash(git mv *)",
21
21
  "Bash(git rm *)",
22
22
  "Bash(node -e \"console.log\\(require\\('@emotion/react/package.json'\\).version\\)\")",
23
- "Bash(node -e \"console.log\\('jodit-react', require\\('jodit-react/package.json'\\).version\\); try{console.log\\('jodit', require\\('jodit/package.json'\\).version\\)}catch\\(e\\){}\")"
23
+ "Bash(node -e \"console.log\\('jodit-react', require\\('jodit-react/package.json'\\).version\\); try{console.log\\('jodit', require\\('jodit/package.json'\\).version\\)}catch\\(e\\){}\")",
24
+ "Bash(node -e \"console.log\\('playwright', require\\('playwright/package.json'\\).version\\)\")",
25
+ "Bash(node -e \"console.log\\('puppeteer', require\\('puppeteer/package.json'\\).version\\)\")",
26
+ "Bash(node -e \"console.log\\('ws', require\\('ws/package.json'\\).version\\)\")",
27
+ "Bash(node -e \"console.log\\('node', process.version\\)\")",
28
+ "Bash(grep -E \"\\\\.tsx?$\")",
29
+ "Bash(node -e \"console.log\\(require.resolve\\('@chakra-ui/styled-system'\\)\\)\")",
30
+ "Bash(node -e \"const p=require.resolve\\('@chakra-ui/react'\\);console.log\\(p\\)\")",
31
+ "Bash(sed -n '31,45p' src/Pages/table.tsx)",
32
+ "Bash(perl -0pi -e 's/\\\\n\\\\s*content: \\\\\\(\\\\\\) => <>Hello<\\\\/>,?//' src/Pages/table.tsx)",
33
+ "Bash(cd /Users/mahesh/Applications/Pixelize/CRM/Micro-Components *)"
34
+ ],
35
+ "additionalDirectories": [
36
+ "/private/tmp",
37
+ "/tmp"
24
38
  ]
25
39
  }
26
40
  }
@@ -43,32 +43,35 @@ var useCustomTheme_1 = require("../../Theme/useCustomTheme");
43
43
  var AccountRow_1 = __importDefault(require("./AccountRow"));
44
44
  var excludeKeys = ["id", "details"];
45
45
  var AccountCard = react_1.default.memo(function (_a) {
46
- var _b, _c, _d, _e, _f, _g, _h;
47
- var account = _a.account, onDelete = _a.onDelete, onOpen = _a.onOpen, _j = _a.isExpanded, isExpanded = _j === void 0 ? false : _j, onToggleExpand = _a.onToggleExpand, _k = _a.isDeletable, isDeletable = _k === void 0 ? true : _k;
46
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
47
+ var account = _a.account, onDelete = _a.onDelete, onOpen = _a.onOpen, _s = _a.isExpanded, isExpanded = _s === void 0 ? false : _s, onToggleExpand = _a.onToggleExpand, _t = _a.isDeletable, isDeletable = _t === void 0 ? true : _t;
48
48
  var colors = (0, useCustomTheme_1.useCustomTheme)().colors;
49
49
  var keys = (0, react_1.useMemo)(function () { return Object.keys(account).filter(function (key) { return typeof account[key] === "string" && !excludeKeys.includes(key); }); }, [account]);
50
50
  var visibleKeys = isExpanded ? keys : keys.slice(0, 4);
51
51
  var handleToggle = function () {
52
52
  onToggleExpand === null || onToggleExpand === void 0 ? void 0 : onToggleExpand();
53
53
  };
54
- return (react_1.default.createElement(react_2.Box, { width: "100%", borderRadius: "0.25rem", borderWidth: "0.063rem", background: (_b = colors === null || colors === void 0 ? void 0 : colors.background) === null || _b === void 0 ? void 0 : _b[200], border: "0.1rem solid ".concat((_c = colors.gray) === null || _c === void 0 ? void 0 : _c[200]), p: 2, boxSizing: "border-box", minHeight: isExpanded ? "180px" : "80px", transition: "border-color 0.15s ease", _hover: {
55
- borderColor: (_d = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _d === void 0 ? void 0 : _d[200],
54
+ return (react_1.default.createElement(react_2.Box, { role: "group", width: "100%", borderRadius: "0.625rem", background: (_b = colors === null || colors === void 0 ? void 0 : colors.white) !== null && _b !== void 0 ? _b : "#fff", border: "0.063rem solid ".concat((_d = (_c = colors === null || colors === void 0 ? void 0 : colors.boxborder) === null || _c === void 0 ? void 0 : _c[200]) !== null && _d !== void 0 ? _d : (_e = colors.gray) === null || _e === void 0 ? void 0 : _e[200]), boxShadow: "0 0.063rem 0.125rem rgba(0,0,0,0.04)", p: 3, boxSizing: "border-box", minHeight: isExpanded ? "180px" : "80px", transition: "border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease", _hover: {
55
+ borderColor: (_f = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _f === void 0 ? void 0 : _f[300],
56
+ boxShadow: "0 0.25rem 0.75rem rgba(0,0,0,0.08)",
57
+ transform: "translateY(-0.063rem)",
56
58
  } },
57
- react_1.default.createElement(react_2.VStack, { align: "start", spacing: 0.5, fontSize: "0.875rem", color: (_e = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _e === void 0 ? void 0 : _e[700] },
59
+ react_1.default.createElement(react_2.VStack, { align: "stretch", spacing: 1, fontSize: "0.875rem", color: (_g = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _g === void 0 ? void 0 : _g[700] },
58
60
  visibleKeys.map(function (key) { return (react_1.default.createElement(AccountRow_1.default, { key: key, label: key.replace(/\b\w/g, function (c) { return c.toUpperCase(); }), value: account[key] })); }),
59
61
  react_1.default.createElement(react_2.Collapse, { in: isExpanded && account.details !== undefined, animateOpacity: true },
60
- react_1.default.createElement(react_2.Text, { pt: 2 }, account.details)),
62
+ react_1.default.createElement(react_2.Text, { pt: 2, fontSize: "0.8125rem", color: (_h = colors === null || colors === void 0 ? void 0 : colors.text) === null || _h === void 0 ? void 0 : _h[600] }, account.details)),
61
63
  react_1.default.createElement(react_2.Flex, { justify: "space-between", w: "full", pt: 2, alignItems: "center" },
62
- keys.length > 4 && (react_1.default.createElement(react_2.Text, { color: (_f = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _f === void 0 ? void 0 : _f[500], fontSize: "sm", fontWeight: "medium", cursor: "pointer", onClick: handleToggle, display: "flex", alignItems: "center", gap: 2 },
64
+ keys.length > 4 ? (react_1.default.createElement(react_2.Text, { color: (_j = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _j === void 0 ? void 0 : _j[600], fontSize: "0.75rem", fontWeight: 600, cursor: "pointer", onClick: handleToggle, display: "flex", alignItems: "center", gap: 1, _hover: { color: (_k = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _k === void 0 ? void 0 : _k[700] } },
63
65
  "Show ",
64
66
  isExpanded ? "less" : "more",
65
67
  " ",
66
- isExpanded ? react_1.default.createElement(lucide_react_1.ChevronUp, { size: 14 }) : react_1.default.createElement(lucide_react_1.ChevronDown, { size: 14 }))),
67
- react_1.default.createElement(react_2.Spacer, null),
68
- react_1.default.createElement(react_2.HStack, { spacing: 2 },
69
- isDeletable && (react_1.default.createElement(react_2.Tooltip, { label: "Delete" },
70
- react_1.default.createElement(lucide_react_1.Trash2, { size: 16, color: (_g = colors === null || colors === void 0 ? void 0 : colors.red) === null || _g === void 0 ? void 0 : _g[600], onClick: function () { return onDelete === null || onDelete === void 0 ? void 0 : onDelete(account); }, cursor: "pointer", "aria-label": "Delete" }))),
71
- react_1.default.createElement(react_2.Tooltip, { label: "Open" },
72
- react_1.default.createElement(lucide_react_1.ExternalLink, { size: 16, color: (_h = colors === null || colors === void 0 ? void 0 : colors.blue) === null || _h === void 0 ? void 0 : _h[600], onClick: function () { return onOpen === null || onOpen === void 0 ? void 0 : onOpen(account); }, cursor: "pointer", "aria-label": "Open" })))))));
68
+ isExpanded ? react_1.default.createElement(lucide_react_1.ChevronUp, { size: 13 }) : react_1.default.createElement(lucide_react_1.ChevronDown, { size: 13 }))) : (react_1.default.createElement(react_2.Spacer, null)),
69
+ react_1.default.createElement(react_2.HStack, { spacing: 1, opacity: 0, transition: "opacity 0.15s ease", _groupHover: { opacity: 1 } },
70
+ isDeletable && (react_1.default.createElement(react_2.Tooltip, { label: "Delete", hasArrow: true },
71
+ react_1.default.createElement(react_2.Flex, { align: "center", justify: "center", boxSize: "1.625rem", borderRadius: "0.375rem", cursor: "pointer", color: (_l = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _l === void 0 ? void 0 : _l[500], transition: "background 0.15s ease, color 0.15s ease", _hover: { bg: (_m = colors === null || colors === void 0 ? void 0 : colors.red) === null || _m === void 0 ? void 0 : _m[50], color: (_o = colors === null || colors === void 0 ? void 0 : colors.red) === null || _o === void 0 ? void 0 : _o[600] }, onClick: function () { return onDelete === null || onDelete === void 0 ? void 0 : onDelete(account); }, "aria-label": "Delete" },
72
+ react_1.default.createElement(lucide_react_1.Trash2, { size: 15 })))),
73
+ react_1.default.createElement(react_2.Tooltip, { label: "Open", hasArrow: true },
74
+ react_1.default.createElement(react_2.Flex, { align: "center", justify: "center", boxSize: "1.625rem", borderRadius: "0.375rem", cursor: "pointer", color: (_p = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _p === void 0 ? void 0 : _p[500], transition: "background 0.15s ease, color 0.15s ease", _hover: { bg: (_q = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _q === void 0 ? void 0 : _q[50], color: (_r = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _r === void 0 ? void 0 : _r[600] }, onClick: function () { return onOpen === null || onOpen === void 0 ? void 0 : onOpen(account); }, "aria-label": "Open" },
75
+ react_1.default.createElement(lucide_react_1.ExternalLink, { size: 15 }))))))));
73
76
  });
74
77
  exports.default = AccountCard;
@@ -71,6 +71,9 @@ var Button_1 = __importDefault(require("../Button/Button"));
71
71
  /** Narrow rail width when a column is horizontally collapsed. */
72
72
  var COLLAPSED_KANBAN_COLUMN_WIDTH = "2.75rem";
73
73
  var KANBAN_CARD_GAP = 12;
74
+ // Top buffer above the first card so its border + hover lift aren't clipped by the
75
+ // scroll/virtualized list's top edge.
76
+ var KANBAN_LIST_TOP_PAD = 6;
74
77
  var KanbanRow = react_1.default.memo(function (_a) {
75
78
  var index = _a.index, style = _a.style, data = _a.data;
76
79
  var items = data.items, colId = data.colId, canDrag = data.canDrag, expanded = data.expanded, onDelete = data.onDelete, onOpen = data.onOpen, canDelete = data.canDelete, setSize = data.setSize, toggleExpand = data.toggleExpand;
@@ -79,7 +82,7 @@ var KanbanRow = react_1.default.memo(function (_a) {
79
82
  return react_1.default.createElement("div", { style: style });
80
83
  }
81
84
  return (react_1.default.createElement("div", { style: style },
82
- react_1.default.createElement("div", { style: { paddingBottom: KANBAN_CARD_GAP } },
85
+ react_1.default.createElement("div", { style: { paddingBottom: KANBAN_CARD_GAP, paddingTop: index === 0 ? KANBAN_LIST_TOP_PAD : 0 } },
83
86
  react_1.default.createElement(MeasuredItem_1.default, { index: index, setSize: function (i, h) { return setSize(i, h, colId); } },
84
87
  react_1.default.createElement(dnd_1.Draggable, { draggableId: account.id.toString(), index: index, key: account.id, isDragDisabled: !canDrag }, function (provided) {
85
88
  var _a;
@@ -259,13 +262,14 @@ var KanbanBoard = function (_a) {
259
262
  return prev;
260
263
  return __assign(__assign({}, prev), (_a = {}, _a[key] = size, _a));
261
264
  });
265
+ // Only recompute from the row that changed downward (cheaper than resetting all).
262
266
  if (listRefs.current[colId]) {
263
- listRefs.current[colId].resetAfterIndex(0);
267
+ listRefs.current[colId].resetAfterIndex(index);
264
268
  }
265
269
  }, []);
266
270
  var getItemSize = (0, react_1.useCallback)(function (index, _items, colId) {
267
271
  var key = "".concat(colId, "-").concat(index);
268
- return (sizes[key] || DEFAULT_ITEM_HEIGHT) + KANBAN_CARD_GAP;
272
+ return (sizes[key] || DEFAULT_ITEM_HEIGHT) + KANBAN_CARD_GAP + (index === 0 ? KANBAN_LIST_TOP_PAD : 0);
269
273
  }, [sizes]);
270
274
  // Calculate container height
271
275
  (0, react_1.useEffect)(function () {
@@ -281,8 +285,9 @@ var KanbanBoard = function (_a) {
281
285
  window.removeEventListener("resize", calculateDimensions);
282
286
  };
283
287
  }, [isBoardLoading]);
284
- // toggle expand/collapse
285
- var toggleExpand = function (id, colId, index) {
288
+ // toggle expand/collapse — memoized so it doesn't bust `rowBaseProps`/itemData
289
+ // every render (which would re-render every virtualized row).
290
+ var toggleExpand = (0, react_1.useCallback)(function (id, colId, index) {
286
291
  setExpanded(function (prev) {
287
292
  var _a;
288
293
  var newExpanded = __assign(__assign({}, prev), (_a = {}, _a[id] = !prev[id], _a));
@@ -291,9 +296,9 @@ var KanbanBoard = function (_a) {
291
296
  }
292
297
  return newExpanded;
293
298
  });
294
- };
299
+ }, []);
295
300
  // drag handler
296
- var onDragEnd = function (result) {
301
+ var onDragEnd = (0, react_1.useCallback)(function (result) {
297
302
  var _a, _b;
298
303
  var source = result.source, destination = result.destination, type = result.type;
299
304
  if (!destination)
@@ -344,12 +349,12 @@ var KanbanBoard = function (_a) {
344
349
  toIndex: destination.index,
345
350
  });
346
351
  }
347
- };
348
- var handleColumnDelete = function (colId) {
352
+ }, [columns, onDrag, onColumnReorder]);
353
+ var handleColumnDelete = (0, react_1.useCallback)(function (colId) {
349
354
  var _a, _b;
350
355
  var columnIds = ((_b = (_a = columns[colId]) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.map(function (item) { return item.id; })) || [];
351
356
  onColumnDelete === null || onColumnDelete === void 0 ? void 0 : onColumnDelete(columnIds);
352
- };
357
+ }, [columns, onColumnDelete]);
353
358
  var rowBaseProps = (0, react_1.useMemo)(function () { return ({
354
359
  canDrag: canDrag,
355
360
  expanded: expanded,
@@ -359,6 +364,16 @@ var KanbanBoard = function (_a) {
359
364
  setSize: setSize,
360
365
  toggleExpand: toggleExpand,
361
366
  }); }, [canDrag, expanded, onDelete, onOpen, canDelete, setSize, toggleExpand]);
367
+ // Stable per-column itemData so unrelated board re-renders (e.g. column hover)
368
+ // don't change the reference react-window hands to every row → no row re-renders.
369
+ var itemDataByCol = (0, react_1.useMemo)(function () {
370
+ var map = {};
371
+ for (var _i = 0, _a = Object.entries(columns); _i < _a.length; _i++) {
372
+ var _b = _a[_i], colId = _b[0], column = _b[1];
373
+ map[colId] = __assign(__assign({}, rowBaseProps), { items: column.items, colId: colId });
374
+ }
375
+ return map;
376
+ }, [columns, rowBaseProps]);
362
377
  var renderColumnDroppable = function (colId, column, columnDragHandleProps, isColCollapsed) { return (react_1.default.createElement(dnd_1.Droppable, { droppableId: colId, key: colId, mode: virtualization ? "virtual" : "standard", renderClone: function (provided, _snapshot, rubric) {
363
378
  var _a;
364
379
  var item = column.items[rubric.source.index];
@@ -366,89 +381,89 @@ var KanbanBoard = function (_a) {
366
381
  return toggleExpand(item.id, colId, rubric.source.index);
367
382
  }, isDeletable: canDelete }))));
368
383
  } }, function (provided, snapshot) {
369
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
370
- return (react_1.default.createElement(react_2.Box, __assign({ ref: provided.innerRef }, provided.droppableProps, { width: isColCollapsed ? COLLAPSED_KANBAN_COLUMN_WIDTH : columnWidth, borderRadius: "0.5rem", borderWidth: "0.063rem", background: snapshot.isDraggingOver
384
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10;
385
+ return (react_1.default.createElement(react_2.Box, __assign({ ref: provided.innerRef }, provided.droppableProps, { width: isColCollapsed ? COLLAPSED_KANBAN_COLUMN_WIDTH : columnWidth, borderRadius: "0.75rem", background: snapshot.isDraggingOver
371
386
  ? (_a = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _a === void 0 ? void 0 : _a[50]
372
- : (_b = colors === null || colors === void 0 ? void 0 : colors.background) === null || _b === void 0 ? void 0 : _b[100], border: "".concat(snapshot.isDraggingOver
373
- ? "0.5px dashed " + ((_c = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _c === void 0 ? void 0 : _c[300])
374
- : "0.125rem solid " + ((_d = colors.gray) === null || _d === void 0 ? void 0 : _d[200])), display: "flex", flexDirection: "column", flexShrink: 0, overflow: isColCollapsed ? "visible" : "hidden", height: "".concat(containerHeight - 60, "px"), transition: "width 0.2s ease", onMouseEnter: function () { return setHoveredColumn(colId); }, onMouseLeave: function () { return setHoveredColumn(null); } }),
387
+ : (_b = colors === null || colors === void 0 ? void 0 : colors.background) === null || _b === void 0 ? void 0 : _b[100], border: "0.063rem ".concat(snapshot.isDraggingOver ? "dashed" : "solid", " ").concat(snapshot.isDraggingOver
388
+ ? (_c = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _c === void 0 ? void 0 : _c[300]
389
+ : (_e = (_d = colors === null || colors === void 0 ? void 0 : colors.boxborder) === null || _d === void 0 ? void 0 : _d[200]) !== null && _e !== void 0 ? _e : (_f = colors.gray) === null || _f === void 0 ? void 0 : _f[200]), transition: "background 0.15s ease, border-color 0.15s ease, width 0.2s ease", display: "flex", flexDirection: "column", flexShrink: 0, overflow: isColCollapsed ? "visible" : "hidden", height: "".concat(containerHeight - 60, "px"), onMouseEnter: function () { return setHoveredColumn(colId); }, onMouseLeave: function () { return setHoveredColumn(null); } }),
375
390
  isColCollapsed ? (react_1.default.createElement(react_2.Flex, { direction: "column", align: "stretch", flex: "1", width: "100%", minH: 0, overflow: "visible", position: "relative" },
376
- react_1.default.createElement(react_2.Flex, { as: "header", direction: "column", align: "center", flexShrink: 0, width: "100%", py: 3, px: 1, gap: 3, borderTop: "0.25rem solid", borderTopColor: (_e = column.color) !== null && _e !== void 0 ? _e : (_f = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _f === void 0 ? void 0 : _f[500], bg: (_g = colors === null || colors === void 0 ? void 0 : colors.background) === null || _g === void 0 ? void 0 : _g[100], position: "relative", zIndex: 1 },
391
+ react_1.default.createElement(react_2.Flex, { as: "header", direction: "column", align: "center", flexShrink: 0, width: "100%", py: 3, px: 1, gap: 3, borderTop: "0.25rem solid", borderTopColor: (_g = column.color) !== null && _g !== void 0 ? _g : (_h = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _h === void 0 ? void 0 : _h[500], bg: (_j = colors === null || colors === void 0 ? void 0 : colors.background) === null || _j === void 0 ? void 0 : _j[100], position: "relative", zIndex: 1 },
377
392
  enableColumnReorder && columnDragHandleProps ? (react_1.default.createElement(react_2.Flex, __assign({ align: "center", justify: "center", flexShrink: 0, cursor: "grab" }, columnDragHandleProps),
378
- react_1.default.createElement(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: (_h = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _h === void 0 ? void 0 : _h[400] }))) : null,
379
- enableColumnCollapse && (react_1.default.createElement(react_2.Flex, { flexShrink: 0, w: "100%", justify: "center", bg: (_j = colors === null || colors === void 0 ? void 0 : colors.background) === null || _j === void 0 ? void 0 : _j[100], position: "relative", zIndex: 3 },
393
+ react_1.default.createElement(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: (_k = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _k === void 0 ? void 0 : _k[400] }))) : null,
394
+ enableColumnCollapse && (react_1.default.createElement(react_2.Flex, { flexShrink: 0, w: "100%", justify: "center", bg: (_l = colors === null || colors === void 0 ? void 0 : colors.background) === null || _l === void 0 ? void 0 : _l[100], position: "relative", zIndex: 3 },
380
395
  react_1.default.createElement(react_2.IconButton, { "aria-label": "Expand column", icon: react_1.default.createElement(lucide_react_1.ChevronRight, { size: 14 }), variant: "ghost", size: "xs", minW: "1.5rem", h: "1.75rem", onClick: function () { return toggleColumnCollapsed(colId); } }))),
381
- react_1.default.createElement(react_2.Text, { as: "span", fontWeight: "700", fontSize: "0.75rem", color: (_k = colors === null || colors === void 0 ? void 0 : colors.text) === null || _k === void 0 ? void 0 : _k[700], sx: {
396
+ react_1.default.createElement(react_2.Text, { as: "span", fontWeight: "700", fontSize: "0.75rem", color: (_m = colors === null || colors === void 0 ? void 0 : colors.text) === null || _m === void 0 ? void 0 : _m[700], sx: {
382
397
  writingMode: "vertical-rl",
383
398
  textOrientation: "mixed",
384
399
  }, maxH: "".concat(Math.max(120, containerHeight - 200), "px"), overflow: "hidden", lineHeight: "1.2", title: column.title }, column.title),
385
- react_1.default.createElement(react_2.Badge, { minW: "1.25rem", h: "1.25rem", borderRadius: "999px", border: "1px solid", borderColor: (_l = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _l === void 0 ? void 0 : _l[300], display: "flex", backgroundColor: (_m = colors === null || colors === void 0 ? void 0 : colors.background) === null || _m === void 0 ? void 0 : _m[100], alignItems: "center", justifyContent: "center", color: (_o = colors === null || colors === void 0 ? void 0 : colors.text) === null || _o === void 0 ? void 0 : _o[900], fontWeight: 600, fontSize: "10px" }, (_p = column === null || column === void 0 ? void 0 : column.items) === null || _p === void 0 ? void 0 : _p.length)),
386
- column.customNode ? (react_1.default.createElement(react_2.Box, { flexShrink: 0, minH: COLLAPSED_CUSTOM_NODE_TOP_RESERVE, w: "100%", bg: (_q = colors === null || colors === void 0 ? void 0 : colors.background) === null || _q === void 0 ? void 0 : _q[100], "aria-hidden": true })) : null,
387
- column.customNode ? (react_1.default.createElement(react_2.Box, { as: "section", "aria-label": "Column summary", flex: "1", minH: 0, w: "100%", overflow: "visible", py: 2, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", bg: (_r = colors === null || colors === void 0 ? void 0 : colors.background) === null || _r === void 0 ? void 0 : _r[100], position: "relative", zIndex: 2 },
400
+ react_1.default.createElement(react_2.Badge, { minW: "1.25rem", h: "1.25rem", borderRadius: "999px", border: "1px solid", borderColor: (_o = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _o === void 0 ? void 0 : _o[300], display: "flex", backgroundColor: (_p = colors === null || colors === void 0 ? void 0 : colors.background) === null || _p === void 0 ? void 0 : _p[100], alignItems: "center", justifyContent: "center", color: (_q = colors === null || colors === void 0 ? void 0 : colors.text) === null || _q === void 0 ? void 0 : _q[900], fontWeight: 600, fontSize: "10px" }, (_r = column === null || column === void 0 ? void 0 : column.items) === null || _r === void 0 ? void 0 : _r.length)),
401
+ column.customNode ? (react_1.default.createElement(react_2.Box, { flexShrink: 0, minH: COLLAPSED_CUSTOM_NODE_TOP_RESERVE, w: "100%", bg: (_s = colors === null || colors === void 0 ? void 0 : colors.background) === null || _s === void 0 ? void 0 : _s[100], "aria-hidden": true })) : null,
402
+ column.customNode ? (react_1.default.createElement(react_2.Box, { as: "section", "aria-label": "Column summary", flex: "1", minH: 0, w: "100%", overflow: "visible", py: 2, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", bg: (_t = colors === null || colors === void 0 ? void 0 : colors.background) === null || _t === void 0 ? void 0 : _t[100], position: "relative", zIndex: 2 },
388
403
  react_1.default.createElement(react_2.Box, { position: "relative", transform: "rotate(90deg)", transformOrigin: "center center", marginTop: '1rem' },
389
- react_1.default.createElement(react_2.VStack, { align: "stretch", spacing: 1, minW: "max-content", fontSize: "xs", color: (_s = colors === null || colors === void 0 ? void 0 : colors.text) === null || _s === void 0 ? void 0 : _s[600] }, column.customNode())))) : (react_1.default.createElement(react_2.Box, { flex: "1", minH: 0 })))) : (react_1.default.createElement(react_2.Flex, { width: "95%", h: !isColCollapsed && !!((_t = column.customNode) === null || _t === void 0 ? void 0 : _t.call(column)) ? "auto" : "2.75rem", borderRadius: "0.25rem", borderLeft: "0.188rem solid", borderLeftColor: (_u = column.color) !== null && _u !== void 0 ? _u : (_v = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _v === void 0 ? void 0 : _v[500], background: (_w = colors === null || colors === void 0 ? void 0 : colors.background) === null || _w === void 0 ? void 0 : _w[300], align: "center", px: 2, m: 2, flexShrink: 0, justifyContent: "space-between", position: "relative", gap: 2 },
390
- react_1.default.createElement(react_2.Box, { display: "flex", alignItems: "center", gap: 2 },
391
- enableColumnReorder && columnDragHandleProps ? (react_1.default.createElement(react_2.Flex, __assign({ align: "center", justify: "center", flexShrink: 0, cursor: "grab" }, columnDragHandleProps),
392
- react_1.default.createElement(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: (_x = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _x === void 0 ? void 0 : _x[400] }))) : null,
393
- react_1.default.createElement(react_2.Flex, { direction: "column", gap: 1, mt: !isColCollapsed && !!((_y = column.customNode) === null || _y === void 0 ? void 0 : _y.call(column)) ? "1" : "0" },
394
- react_1.default.createElement(react_2.Text, { as: "span", fontWeight: "600", fontSize: "0.875rem", color: (_z = colors === null || colors === void 0 ? void 0 : colors.text) === null || _z === void 0 ? void 0 : _z[700], noOfLines: 1, flex: "1", minW: 0 },
395
- react_1.default.createElement(OverflowTooltipText_1.default, { placement: "top" }, column.title)),
396
- !!((_0 = column.customNode) === null || _0 === void 0 ? void 0 : _0.call(column)) ? (react_1.default.createElement(react_2.Box, { as: "section", "aria-label": "Column summary", width: "95%", flexShrink: 0, fontSize: "xs", mb: 1, color: (_1 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _1 === void 0 ? void 0 : _1[600] }, column.customNode())) : null)),
404
+ react_1.default.createElement(react_2.VStack, { align: "stretch", spacing: 1, minW: "max-content", fontSize: "xs", color: (_u = colors === null || colors === void 0 ? void 0 : colors.text) === null || _u === void 0 ? void 0 : _u[600] }, column.customNode())))) : (react_1.default.createElement(react_2.Box, { flex: "1", minH: 0 })))) : (react_1.default.createElement(react_2.Flex, { width: "100%", h: !isColCollapsed && !!((_v = column.customNode) === null || _v === void 0 ? void 0 : _v.call(column)) ? "auto" : "2.75rem", align: !isColCollapsed && !!((_w = column.customNode) === null || _w === void 0 ? void 0 : _w.call(column)) ? "flex-start" : "center", px: 3, py: 2, flexShrink: 0, justifyContent: "space-between", position: "relative", gap: 2, borderBottom: "0.063rem solid ".concat((_y = (_x = colors === null || colors === void 0 ? void 0 : colors.boxborder) === null || _x === void 0 ? void 0 : _x[100]) !== null && _y !== void 0 ? _y : (_z = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _z === void 0 ? void 0 : _z[100]) },
405
+ react_1.default.createElement(react_2.Flex, { direction: "column", gap: 1, minW: 0, flex: "1" },
406
+ react_1.default.createElement(react_2.Flex, { align: "center", gap: 2, minW: 0 },
407
+ react_1.default.createElement(react_2.Box, { boxSize: "0.625rem", borderRadius: "full", bg: (_0 = column.color) !== null && _0 !== void 0 ? _0 : (_1 = colors === null || colors === void 0 ? void 0 : colors.primary) === null || _1 === void 0 ? void 0 : _1[500], flexShrink: 0 }),
408
+ enableColumnReorder && columnDragHandleProps ? (react_1.default.createElement(react_2.Flex, __assign({ align: "center", justify: "center", flexShrink: 0, cursor: "grab" }, columnDragHandleProps),
409
+ react_1.default.createElement(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: (_2 = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _2 === void 0 ? void 0 : _2[400] }))) : null,
410
+ react_1.default.createElement(react_2.Text, { as: "span", fontWeight: "600", fontSize: "0.875rem", color: (_3 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _3 === void 0 ? void 0 : _3[700], noOfLines: 1, minW: 0 },
411
+ react_1.default.createElement(OverflowTooltipText_1.default, { placement: "top" }, column.title))),
412
+ !!((_4 = column.customNode) === null || _4 === void 0 ? void 0 : _4.call(column)) ? (react_1.default.createElement(react_2.Box, { as: "section", "aria-label": "Column summary", width: "100%", flexShrink: 0, fontSize: "xs", color: (_5 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _5 === void 0 ? void 0 : _5[600] }, column.customNode())) : null),
397
413
  react_1.default.createElement(react_2.Box, { display: "flex", alignItems: "center", gap: 2 },
398
- react_1.default.createElement(react_2.Badge, { minW: { base: "20px", sm: "22px", md: "24px" }, h: { base: "20px", sm: "22px", md: "24px" }, borderRadius: "999px", border: "1px solid", backgroundColor: (_2 = colors === null || colors === void 0 ? void 0 : colors.background) === null || _2 === void 0 ? void 0 : _2[100], borderColor: (_3 = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _3 === void 0 ? void 0 : _3[300], display: "flex", alignItems: "center", justifyContent: "center", color: (_4 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _4 === void 0 ? void 0 : _4[900], fontWeight: 600, fontSize: { base: "10px", sm: "11px", md: "12px" } }, (_5 = column === null || column === void 0 ? void 0 : column.items) === null || _5 === void 0 ? void 0 : _5.length),
414
+ react_1.default.createElement(react_2.Badge, { minW: "1.5rem", h: "1.5rem", px: 2, borderRadius: "999px", backgroundColor: (_6 = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _6 === void 0 ? void 0 : _6[100], display: "flex", alignItems: "center", justifyContent: "center", color: (_7 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _7 === void 0 ? void 0 : _7[700], fontWeight: 600, fontSize: "0.625rem" }, (_8 = column === null || column === void 0 ? void 0 : column.items) === null || _8 === void 0 ? void 0 : _8.length),
399
415
  enableColumnCollapse && (react_1.default.createElement(react_2.IconButton, { "aria-label": "Collapse column", icon: react_1.default.createElement(lucide_react_1.ChevronLeft, { size: 14 }), variant: "ghost", size: "xs", minW: "1.5rem", h: "1.75rem", flexShrink: 0, onClick: function () { return toggleColumnCollapsed(colId); } })),
400
416
  canDelete &&
401
417
  hoveredColumn === colId &&
402
- column.items.length > 0 && (react_1.default.createElement(react_2.Box, { as: lucide_react_1.Trash2, size: 16, cursor: "pointer", color: (_6 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _6 === void 0 ? void 0 : _6[600], _hover: { color: (_7 = colors === null || colors === void 0 ? void 0 : colors.red) === null || _7 === void 0 ? void 0 : _7[600] }, onClick: function () { return handleColumnDelete(colId); }, transition: "color 0.2s ease", flexShrink: 0 })),
418
+ column.items.length > 0 && (react_1.default.createElement(react_2.Box, { as: lucide_react_1.Trash2, size: 16, cursor: "pointer", color: (_9 = colors === null || colors === void 0 ? void 0 : colors.text) === null || _9 === void 0 ? void 0 : _9[600], _hover: { color: (_10 = colors === null || colors === void 0 ? void 0 : colors.red) === null || _10 === void 0 ? void 0 : _10[600] }, onClick: function () { return handleColumnDelete(colId); }, transition: "color 0.2s ease", flexShrink: 0 })),
403
419
  !(canDelete &&
404
420
  hoveredColumn === colId &&
405
421
  column.items.length > 0) && react_1.default.createElement(react_2.Box, { width: "16px", height: "16px", flexShrink: 0 })))),
406
- !isColCollapsed && (react_1.default.createElement(react_1.default.Fragment, null,
407
- react_1.default.createElement(react_2.Box, { px: 2, flex: "1", overflowY: "auto", width: "100%", sx: {
408
- overflowY: "auto",
409
- overflowX: "hidden",
410
- scrollbarWidth: "thin",
411
- scrollbarColor: "var(--chakra-colors-gray-300) transparent",
412
- "&::-webkit-scrollbar": {
413
- width: "6px !important",
414
- height: "6px !important",
415
- },
416
- "&::-webkit-scrollbar-track": {
417
- background: "gray.100",
418
- borderRadius: "3px",
419
- marginTop: "4px",
420
- marginBottom: "4px",
421
- },
422
- "&::-webkit-scrollbar-thumb": {
423
- background: "gray.300",
424
- borderRadius: "3px",
425
- border: "1px solid",
426
- borderColor: "gray.100",
427
- },
428
- "&::-webkit-scrollbar-thumb:hover": {
429
- background: "gray.400",
430
- },
431
- "&": {
432
- scrollbarGutter: "stable both-edges",
433
- },
434
- cursor: canDrag ? "grab" : "not-allowed",
435
- } },
436
- (noItems === null || noItems === void 0 ? void 0 : noItems.isVisible) && column.items.length === 0 && (react_1.default.createElement(NoItemsTemplate, { column: column, noItems: noItems, colors: colors })),
437
- virtualization ? (react_1.default.createElement(react_window_1.VariableSizeList, { ref: function (el) {
438
- if (el)
439
- listRefs.current[colId] = el;
440
- }, height: containerHeight - 150, itemCount: column.items.length +
441
- (snapshot.isUsingPlaceholder ? 1 : 0), itemSize: function (index) {
442
- return getItemSize(index, column.items, colId);
443
- }, width: "100%", itemData: __assign(__assign({}, rowBaseProps), { items: column.items, colId: colId }) }, KanbanRow)) : (react_1.default.createElement(react_2.Box, null,
444
- column.items.map(function (account, index) { return (react_1.default.createElement("div", { key: account.id, style: { paddingBottom: KANBAN_CARD_GAP } },
445
- react_1.default.createElement(dnd_1.Draggable, { draggableId: account.id.toString(), index: index, key: account.id, isDragDisabled: !canDrag }, function (dragProvided) {
446
- var _a;
447
- return (react_1.default.createElement("div", __assign({ ref: dragProvided.innerRef }, dragProvided.draggableProps, dragProvided.dragHandleProps, { style: dragProvided.draggableProps.style }), (account === null || account === void 0 ? void 0 : account.customNode) ? (_a = account === null || account === void 0 ? void 0 : account.customNode) === null || _a === void 0 ? void 0 : _a.call(account) : (react_1.default.createElement(AccountCard_1.default, { account: account, index: index, onDelete: onDelete, onOpen: onOpen, isExpanded: expanded[account.id], onToggleExpand: function () {
448
- return toggleExpand(account.id, colId, index);
449
- }, isDeletable: canDelete }))));
450
- }))); }),
451
- provided.placeholder)))))));
422
+ !isColCollapsed && (react_1.default.createElement(react_2.Box, { px: 2, flex: "1", overflowY: "auto", width: "100%", sx: {
423
+ overflowY: "auto",
424
+ overflowX: "hidden",
425
+ scrollbarWidth: "thin",
426
+ scrollbarColor: "var(--chakra-colors-gray-300) transparent",
427
+ "&::-webkit-scrollbar": {
428
+ width: "6px !important",
429
+ height: "6px !important",
430
+ },
431
+ "&::-webkit-scrollbar-track": {
432
+ background: "gray.100",
433
+ borderRadius: "3px",
434
+ marginTop: "4px",
435
+ marginBottom: "4px",
436
+ },
437
+ "&::-webkit-scrollbar-thumb": {
438
+ background: "gray.300",
439
+ borderRadius: "3px",
440
+ border: "1px solid",
441
+ borderColor: "gray.100",
442
+ },
443
+ "&::-webkit-scrollbar-thumb:hover": {
444
+ background: "gray.400",
445
+ },
446
+ "&": {
447
+ scrollbarGutter: "stable both-edges",
448
+ },
449
+ cursor: canDrag ? "grab" : "not-allowed",
450
+ } },
451
+ (noItems === null || noItems === void 0 ? void 0 : noItems.isVisible) && column.items.length === 0 && (react_1.default.createElement(NoItemsTemplate, { column: column, noItems: noItems, colors: colors })),
452
+ virtualization ? (react_1.default.createElement(react_window_1.VariableSizeList, { ref: function (el) {
453
+ if (el)
454
+ listRefs.current[colId] = el;
455
+ }, height: containerHeight - 150, itemCount: column.items.length +
456
+ (snapshot.isUsingPlaceholder ? 1 : 0), itemSize: function (index) {
457
+ return getItemSize(index, column.items, colId);
458
+ }, width: "100%", itemData: itemDataByCol[colId] }, KanbanRow)) : (react_1.default.createElement(react_2.Box, null,
459
+ column.items.map(function (account, index) { return (react_1.default.createElement("div", { key: account.id, style: { paddingBottom: KANBAN_CARD_GAP, paddingTop: index === 0 ? KANBAN_LIST_TOP_PAD : 0 } },
460
+ react_1.default.createElement(dnd_1.Draggable, { draggableId: account.id.toString(), index: index, key: account.id, isDragDisabled: !canDrag }, function (dragProvided) {
461
+ var _a;
462
+ return (react_1.default.createElement("div", __assign({ ref: dragProvided.innerRef }, dragProvided.draggableProps, dragProvided.dragHandleProps, { style: dragProvided.draggableProps.style }), (account === null || account === void 0 ? void 0 : account.customNode) ? (_a = account === null || account === void 0 ? void 0 : account.customNode) === null || _a === void 0 ? void 0 : _a.call(account) : (react_1.default.createElement(AccountCard_1.default, { account: account, index: index, onDelete: onDelete, onOpen: onOpen, isExpanded: expanded[account.id], onToggleExpand: function () {
463
+ return toggleExpand(account.id, colId, index);
464
+ }, isDeletable: canDelete }))));
465
+ }))); }),
466
+ provided.placeholder))))));
452
467
  })); };
453
468
  if (!canView)
454
469
  return null;
@@ -90,19 +90,26 @@ var SearchSelect = function (_a) {
90
90
  var _y = (0, react_1.useState)(true), hasMore = _y[0], setHasMore = _y[1];
91
91
  var inputRef = (0, react_1.useRef)(null);
92
92
  var containerRef = (0, react_1.useRef)(null);
93
+ var controlRef = (0, react_1.useRef)(null);
94
+ var _z = (0, react_1.useState)({ top: 0, left: 0, width: 0 }), dropdownPos = _z[0], setDropdownPos = _z[1];
93
95
  var scrollTimeoutRef = (0, react_1.useRef)(null);
94
- var _z = (0, react_1.useState)(false), focused = _z[0], setFocused = _z[1];
95
- var _0 = (0, react_1.useState)(false), customSelectOpen = _0[0], setCustomSelectOpen = _0[1];
96
+ var _0 = (0, react_1.useState)(false), focused = _0[0], setFocused = _0[1];
97
+ var _1 = (0, react_1.useState)(false), customSelectOpen = _1[0], setCustomSelectOpen = _1[1];
96
98
  var customSelectRef = (0, react_1.useRef)(null);
97
- var _1 = (0, react_1.useState)({
99
+ var _2 = (0, react_1.useState)({
98
100
  top: 0,
99
101
  left: 0,
100
102
  width: 0,
101
- }), customSelectPos = _1[0], setCustomSelectPos = _1[1];
103
+ }), customSelectPos = _2[0], setCustomSelectPos = _2[1];
102
104
  var theme = (0, useCustomTheme_1.useCustomTheme)();
103
105
  (0, react_2.useOutsideClick)({
104
106
  ref: containerRef,
105
- handler: function () {
107
+ handler: function (e) {
108
+ // The options dropdown is portaled to <body>, so a click on it is "outside"
109
+ // the container — ignore those so selecting an option doesn't close first.
110
+ var dropdown = document.getElementById("searchselect-dropdown-portal");
111
+ if (dropdown && dropdown.contains(e.target))
112
+ return;
106
113
  setIsOpen(false);
107
114
  },
108
115
  });
@@ -223,10 +230,34 @@ var SearchSelect = function (_a) {
223
230
  });
224
231
  }
225
232
  }, [customSelectOpen]);
233
+ // Keep the portaled options dropdown anchored to the control (on open + while
234
+ // open if the page/modal scrolls or resizes).
235
+ var updateDropdownPos = (0, react_1.useCallback)(function () {
236
+ if (!controlRef.current)
237
+ return;
238
+ var rect = controlRef.current.getBoundingClientRect();
239
+ setDropdownPos({
240
+ top: rect.bottom + window.scrollY,
241
+ left: rect.left + window.scrollX,
242
+ width: rect.width,
243
+ });
244
+ }, []);
245
+ (0, react_1.useEffect)(function () {
246
+ if (!isOpen)
247
+ return;
248
+ updateDropdownPos();
249
+ // `true` (capture) catches scrolling inside any ancestor (e.g. modal body).
250
+ window.addEventListener("scroll", updateDropdownPos, true);
251
+ window.addEventListener("resize", updateDropdownPos);
252
+ return function () {
253
+ window.removeEventListener("scroll", updateDropdownPos, true);
254
+ window.removeEventListener("resize", updateDropdownPos);
255
+ };
256
+ }, [isOpen, updateDropdownPos]);
226
257
  return (react_1.default.createElement(react_2.Box, { ref: containerRef, width: width, position: "relative" },
227
258
  label && (react_1.default.createElement(FormLabel_1.TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation !== null && isInformation !== void 0 ? isInformation : information === null || information === void 0 ? void 0 : information.isInformation, informationMessage: informationMessage !== null && informationMessage !== void 0 ? informationMessage : information === null || information === void 0 ? void 0 : information.informationMessage })),
228
259
  react_1.default.createElement(react_2.InputGroup, { size: size },
229
- react_1.default.createElement(react_2.Box, { as: "div", w: "100%", minH: s.minH, px: s.px, pr: s.pr, position: "relative", display: "flex", alignItems: "center", flexWrap: "wrap", gap: s.gap, border: "0.063rem solid", borderColor: error
260
+ react_1.default.createElement(react_2.Box, { as: "div", ref: controlRef, w: "100%", minH: s.minH, px: s.px, pr: s.pr, position: "relative", display: "flex", alignItems: "center", flexWrap: "wrap", gap: s.gap, border: "0.063rem solid", borderColor: error
230
261
  ? theme.colors.semantic.error[500]
231
262
  : focused
232
263
  ? theme.colors.primary[500]
@@ -275,22 +306,23 @@ var SearchSelect = function (_a) {
275
306
  e.stopPropagation();
276
307
  setIsOpen(function (prev) { return !prev; });
277
308
  }, "aria-label": "toggle-dropdown", display: "flex", alignItems: "center" }, isOpen ? (react_1.default.createElement(lucide_react_1.ChevronUp, { size: s.chevronSize })) : (react_1.default.createElement(lucide_react_1.ChevronDown, { size: s.chevronSize }))))))),
278
- isOpen && (react_1.default.createElement(react_2.Box, { position: "absolute", zIndex: 10, width: "100%", maxH: "20rem", borderWidth: 1, borderRadius: "sm", bg: theme.colors.white, boxShadow: "md", display: "flex", flexDirection: "column" },
279
- isMultiple && isSelectAll && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
280
- react_1.default.createElement(Checkbox_1.default, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }),
281
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, allFilteredSelected ? "Unselect All" : "Select All"))),
282
- react_1.default.createElement(react_2.Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.gray[200] }, isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH },
283
- react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
284
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText))) : !isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.gray[500] }, "No results found")) : (react_1.default.createElement(react_1.default.Fragment, null,
285
- filteredOptions.map(function (option) { return (react_1.default.createElement(react_2.Box, { key: option.id, py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: isSelected(option.id) ? theme.colors.gray[100] : "transparent", _hover: { bg: theme.colors.gray[50] }, onClick: function () { return handleSelect(option); }, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
286
- isMultiple && (react_1.default.createElement(Checkbox_1.default, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })),
287
- option.view ? (react_1.default.createElement(react_1.default.Fragment, null, option.view)) : (react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, option.label)))); }),
288
- ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH },
309
+ isOpen && (react_1.default.createElement(react_2.Portal, null,
310
+ react_1.default.createElement(react_2.Box, { id: "searchselect-dropdown-portal", position: "absolute", top: "".concat(dropdownPos.top, "px"), left: "".concat(dropdownPos.left, "px"), width: "".concat(dropdownPos.width, "px"), zIndex: 1500, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.gray[200], borderRadius: "sm", bg: theme.colors.white, boxShadow: "md", display: "flex", flexDirection: "column" },
311
+ isMultiple && isSelectAll && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
312
+ react_1.default.createElement(Checkbox_1.default, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }),
313
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, allFilteredSelected ? "Unselect All" : "Select All"))),
314
+ react_1.default.createElement(react_2.Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.gray[200] }, isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH },
289
315
  react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
290
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText)))))),
291
- (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.gray[200], bg: theme.colors.white, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: theme.colors.gray[50] } },
292
- addNew.icon || react_1.default.createElement(lucide_react_1.Plus, { size: s.addNewIconSize }),
293
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, addNew.text || "Add New"))))),
316
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText))) : !isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.gray[500] }, "No results found")) : (react_1.default.createElement(react_1.default.Fragment, null,
317
+ filteredOptions.map(function (option) { return (react_1.default.createElement(react_2.Box, { key: option.id, py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: isSelected(option.id) ? theme.colors.gray[100] : "transparent", _hover: { bg: theme.colors.gray[50] }, onClick: function () { return handleSelect(option); }, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
318
+ isMultiple && (react_1.default.createElement(Checkbox_1.default, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })),
319
+ option.view ? (react_1.default.createElement(react_1.default.Fragment, null, option.view)) : (react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, option.label)))); }),
320
+ ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH },
321
+ react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
322
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText)))))),
323
+ (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.gray[200], bg: theme.colors.white, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: theme.colors.gray[50] } },
324
+ addNew.icon || react_1.default.createElement(lucide_react_1.Plus, { size: s.addNewIconSize }),
325
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, addNew.text || "Add New")))))),
294
326
  helperText && !error && react_1.default.createElement(HelperText_1.default, { helperText: helperText }),
295
327
  error && react_1.default.createElement(ErrorMessage_1.default, { errorMessage: errorMessage })));
296
328
  };
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
2
  import { TableProps } from "./TableProps";
3
- export default function Table({ data, columns, onSelection, isLoading, isCheckbox, headerBgColor, freezedBgColor, headerTextColor, freezedTextColor, tableBorderColor, noBorders, isPagination, onRowClick, selections, isActionFreeze, preferences, paginationMode, infiniteScroll, hasMore, isLoadingMore, noOfRowsPerPage, totalRecords, onPagination, isTableSettings, headerActions, onGlobalSearch, onNoOfRowsPerPageChange, paginationSelectOptions, tableMaxHeight, minVisibleRows, maxVisibleRows, autoFitViewport, tableSettings, filterSidebar, loadingSkeletonRows, defaultVisibleColumns, density, stripe, groupBy, groupColors, onAddItem, emptyState, }: TableProps): React.JSX.Element;
3
+ export default function Table({ data, columns, onSelection, isLoading, isCheckbox, headerBgColor, freezedBgColor, headerTextColor, freezedTextColor, tableBorderColor, noBorders, isPagination, onRowClick, selections, isActionFreeze, preferences, paginationMode, infiniteScroll, hasMore, isLoadingMore, groupLoadMore, loadMoreText, loadMorePosition, loadMoreChunkSize, noOfRowsPerPage, totalRecords, onPagination, isTableSettings, headerActions, onGlobalSearch, onNoOfRowsPerPageChange, paginationSelectOptions, tableMaxHeight, minVisibleRows, maxVisibleRows, autoFitViewport, tableSettings, filterSidebar, loadingSkeletonRows, defaultVisibleColumns, density, stripe, groupColors, onAddItem, emptyState, }: TableProps): React.JSX.Element;
@@ -65,33 +65,34 @@ var HeaderActions_1 = __importDefault(require("./components/HeaderActions"));
65
65
  var Divider_1 = __importDefault(require("../Divider/Divider"));
66
66
  var TableSearch_1 = __importDefault(require("./components/TableSearch"));
67
67
  var ActiveFilters_1 = __importDefault(require("./filters/ActiveFilters"));
68
+ var Button_1 = __importDefault(require("../Button/Button"));
68
69
  var lucide_react_1 = require("lucide-react");
69
70
  var MotionBox = (0, framer_motion_1.motion)(react_2.Box);
70
71
  function Table(_a) {
71
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
72
- var data = _a.data, columns = _a.columns, onSelection = _a.onSelection, isLoading = _a.isLoading, _9 = _a.isCheckbox, isCheckbox = _9 === void 0 ? false : _9, headerBgColor = _a.headerBgColor, freezedBgColor = _a.freezedBgColor, headerTextColor = _a.headerTextColor, freezedTextColor = _a.freezedTextColor, tableBorderColor = _a.tableBorderColor, _10 = _a.noBorders, noBorders = _10 === void 0 ? false : _10, _11 = _a.isPagination, isPagination = _11 === void 0 ? true : _11, onRowClick = _a.onRowClick, selections = _a.selections, _12 = _a.isActionFreeze, isActionFreeze = _12 === void 0 ? true : _12, _13 = _a.preferences, preferences = _13 === void 0 ? {
72
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
73
+ var data = _a.data, columns = _a.columns, onSelection = _a.onSelection, isLoading = _a.isLoading, _14 = _a.isCheckbox, isCheckbox = _14 === void 0 ? false : _14, headerBgColor = _a.headerBgColor, freezedBgColor = _a.freezedBgColor, headerTextColor = _a.headerTextColor, freezedTextColor = _a.freezedTextColor, tableBorderColor = _a.tableBorderColor, _15 = _a.noBorders, noBorders = _15 === void 0 ? false : _15, _16 = _a.isPagination, isPagination = _16 === void 0 ? true : _16, onRowClick = _a.onRowClick, selections = _a.selections, _17 = _a.isActionFreeze, isActionFreeze = _17 === void 0 ? true : _17, _18 = _a.preferences, preferences = _18 === void 0 ? {
73
74
  url: "",
74
75
  token: "",
75
76
  key: "",
76
77
  name: "",
77
78
  page: "",
78
79
  orgId: "",
79
- } : _13, _14 = _a.paginationMode, paginationMode = _14 === void 0 ? "client" : _14, _15 = _a.infiniteScroll, infiniteScroll = _15 === void 0 ? false : _15, hasMore = _a.hasMore, _16 = _a.isLoadingMore, isLoadingMore = _16 === void 0 ? false : _16, _17 = _a.noOfRowsPerPage, noOfRowsPerPage = _17 === void 0 ? 50 : _17, _18 = _a.totalRecords, totalRecords = _18 === void 0 ? 0 : _18, onPagination = _a.onPagination, _19 = _a.isTableSettings, isTableSettings = _19 === void 0 ? false : _19, headerActions = _a.headerActions, onGlobalSearch = _a.onGlobalSearch, onNoOfRowsPerPageChange = _a.onNoOfRowsPerPageChange, paginationSelectOptions = _a.paginationSelectOptions, tableMaxHeight = _a.tableMaxHeight, minVisibleRows = _a.minVisibleRows, maxVisibleRows = _a.maxVisibleRows, autoFitViewport = _a.autoFitViewport, tableSettings = _a.tableSettings, filterSidebar = _a.filterSidebar, loadingSkeletonRows = _a.loadingSkeletonRows, defaultVisibleColumns = _a.defaultVisibleColumns, _20 = _a.density, density = _20 === void 0 ? "normal" : _20, stripe = _a.stripe, groupBy = _a.groupBy, groupColors = _a.groupColors, onAddItem = _a.onAddItem, emptyState = _a.emptyState;
80
+ } : _18, _19 = _a.paginationMode, paginationMode = _19 === void 0 ? "client" : _19, _20 = _a.infiniteScroll, infiniteScroll = _20 === void 0 ? false : _20, hasMore = _a.hasMore, _21 = _a.isLoadingMore, isLoadingMore = _21 === void 0 ? false : _21, _22 = _a.groupLoadMore, groupLoadMore = _22 === void 0 ? false : _22, _23 = _a.loadMoreText, loadMoreText = _23 === void 0 ? "Load more" : _23, _24 = _a.loadMorePosition, loadMorePosition = _24 === void 0 ? "top" : _24, loadMoreChunkSize = _a.loadMoreChunkSize, _25 = _a.noOfRowsPerPage, noOfRowsPerPage = _25 === void 0 ? 50 : _25, _26 = _a.totalRecords, totalRecords = _26 === void 0 ? 0 : _26, onPagination = _a.onPagination, _27 = _a.isTableSettings, isTableSettings = _27 === void 0 ? false : _27, headerActions = _a.headerActions, onGlobalSearch = _a.onGlobalSearch, onNoOfRowsPerPageChange = _a.onNoOfRowsPerPageChange, paginationSelectOptions = _a.paginationSelectOptions, tableMaxHeight = _a.tableMaxHeight, minVisibleRows = _a.minVisibleRows, maxVisibleRows = _a.maxVisibleRows, autoFitViewport = _a.autoFitViewport, tableSettings = _a.tableSettings, filterSidebar = _a.filterSidebar, loadingSkeletonRows = _a.loadingSkeletonRows, defaultVisibleColumns = _a.defaultVisibleColumns, _28 = _a.density, density = _28 === void 0 ? "normal" : _28, stripe = _a.stripe, groupColors = _a.groupColors, onAddItem = _a.onAddItem, emptyState = _a.emptyState;
80
81
  var theme = (0, useCustomTheme_1.useCustomTheme)();
81
- var _21 = (0, react_1.useState)({}), columnsSearch = _21[0], setColumnsSearch = _21[1];
82
+ var _29 = (0, react_1.useState)({}), columnsSearch = _29[0], setColumnsSearch = _29[1];
82
83
  var tableContainerRef = (0, react_1.useRef)(null);
83
- var _22 = (0, react_2.useDisclosure)(), isFilterModalOpen = _22.isOpen, onFilterModalOpen = _22.onOpen, onFilterModalClose = _22.onClose;
84
+ var _30 = (0, react_2.useDisclosure)(), isFilterModalOpen = _30.isOpen, onFilterModalOpen = _30.onOpen, onFilterModalClose = _30.onClose;
84
85
  var filterMode = (_b = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.filterMode) !== null && _b !== void 0 ? _b : "sidebar";
85
- var _23 = (0, react_1.useState)(500), viewportAvailableH = _23[0], setViewportAvailableH = _23[1];
86
+ var _31 = (0, react_1.useState)(500), viewportAvailableH = _31[0], setViewportAvailableH = _31[1];
86
87
  var isServerPagination = paginationMode === "server";
87
- var _24 = (0, usePreferences_1.useGetPreferences)({
88
+ var _32 = (0, usePreferences_1.useGetPreferences)({
88
89
  baseUrl: preferences.url,
89
90
  page: preferences.page,
90
91
  key: preferences.key,
91
92
  name: preferences.name,
92
93
  authToken: preferences.token,
93
94
  orgId: preferences.orgId,
94
- }), tablePreferencesData = _24.preferences, loading = _24.loading;
95
+ }), tablePreferencesData = _32.preferences, loading = _32.loading;
95
96
  var savePreferences = (0, usePreferences_1.useSavePreferences)({
96
97
  baseUrl: preferences.url,
97
98
  page: preferences.page,
@@ -109,7 +110,7 @@ function Table(_a) {
109
110
  }
110
111
  return {};
111
112
  }, [tablePreferencesData]);
112
- var _25 = (0, useTable_1.default)({
113
+ var _33 = (0, useTable_1.default)({
113
114
  tableBorderColor: tableBorderColor,
114
115
  data: data,
115
116
  isPagination: isPagination,
@@ -123,26 +124,48 @@ function Table(_a) {
123
124
  isServerPagination: isServerPagination,
124
125
  onNoOfRowsPerPageChange: onNoOfRowsPerPageChange,
125
126
  defaultVisibleColumns: defaultVisibleColumns,
126
- }), tableData = _25.tableData, isContent = _25.isContent, isLink = _25.isLink, headerRefs = _25.headerRefs, columnWidths = _25.columnWidths, handleSort = _25.handleSort, handleCheckbox = _25.handleCheckbox, filteredData = _25.filteredData, startRow = _25.startRow, endRow = _25.endRow, selection = _25.selection, columnsSort = _25.columnsSort, currentPage = _25.currentPage, pages = _25.pages, rowsPerPage = _25.rowsPerPage, handlePageSizeChange = _25.handlePageSizeChange, setCurrentPage = _25.setCurrentPage, columnsList = _25.columnsList, handleColumnPreferences = _25.handleColumnPreferences, isSelecting = _25.isSelecting;
127
- // Density is managed here so the Table Settings tab can change + persist it
128
- // (seeded from the prop, then from saved preferences when they load).
129
- var _26 = (0, react_1.useState)(density), densityState = _26[0], setDensityState = _26[1];
127
+ }), tableData = _33.tableData, isContent = _33.isContent, isLink = _33.isLink, headerRefs = _33.headerRefs, columnWidths = _33.columnWidths, handleSort = _33.handleSort, handleCheckbox = _33.handleCheckbox, filteredData = _33.filteredData, startRow = _33.startRow, endRow = _33.endRow, selection = _33.selection, columnsSort = _33.columnsSort, currentPage = _33.currentPage, pages = _33.pages, rowsPerPage = _33.rowsPerPage, handlePageSizeChange = _33.handlePageSizeChange, setCurrentPage = _33.setCurrentPage, columnsList = _33.columnsList, handleColumnPreferences = _33.handleColumnPreferences, isSelecting = _33.isSelecting;
128
+ // Density + grouping are managed here so the Table Settings tabs can change +
129
+ // persist them (seeded from the prop / saved preferences when they load).
130
+ var _34 = (0, react_1.useState)(density), densityState = _34[0], setDensityState = _34[1];
131
+ // Grouping is chosen by the user in Table Settings > Group and persisted to
132
+ // preferences (`json.groupBy`); there is no `groupBy` prop.
133
+ var _35 = (0, react_1.useState)(undefined), groupByState = _35[0], setGroupByState = _35[1];
130
134
  (0, react_1.useEffect)(function () {
131
135
  if (tablePreferences === null || tablePreferences === void 0 ? void 0 : tablePreferences.density)
132
136
  setDensityState(tablePreferences.density);
133
137
  }, [tablePreferences === null || tablePreferences === void 0 ? void 0 : tablePreferences.density]);
138
+ (0, react_1.useEffect)(function () {
139
+ if (tablePreferences && "groupBy" in tablePreferences) {
140
+ var saved = tablePreferences.groupBy;
141
+ setGroupByState(saved === null || saved === undefined || saved === "" ? undefined : saved);
142
+ }
143
+ }, [tablePreferences === null || tablePreferences === void 0 ? void 0 : tablePreferences.groupBy]);
134
144
  var handleDensityChange = function (d) {
135
145
  setDensityState(d);
136
- savePreferences === null || savePreferences === void 0 ? void 0 : savePreferences(__assign(__assign({}, tablePreferences), { columns: columnsList, density: d }));
146
+ savePreferences === null || savePreferences === void 0 ? void 0 : savePreferences(__assign(__assign({}, tablePreferences), { columns: columnsList, groupBy: groupByState !== null && groupByState !== void 0 ? groupByState : null, density: d }));
147
+ };
148
+ var handleGroupByChange = function (value) {
149
+ setGroupByState(value);
150
+ savePreferences === null || savePreferences === void 0 ? void 0 : savePreferences(__assign(__assign({}, tablePreferences), { columns: columnsList, density: densityState, groupBy: value !== null && value !== void 0 ? value : null }));
137
151
  };
138
152
  var _filteredData = (0, react_1.useMemo)(function () {
139
153
  return (0, table_1.searchAndSortData)(filteredData, columnsSearch);
140
154
  }, [columnsSearch, filteredData]);
141
- // --- Monday-style grouping (client-side). When active, pagination is hidden
142
- // and the body renders colored, collapsible groups over the full dataset. ---
143
- var isGrouped = !!groupBy && !isServerPagination;
155
+ // --- Monday-style grouping. Active whenever the user has picked a group column
156
+ // (in Settings > Group). When active, the numbered pager / infinite scroll are
157
+ // hidden and the body renders colored, collapsible groups over the loaded rows.
158
+ // `groupLoadMore` adds a "Load more" button on top to fetch more into the groups. ---
159
+ var isGrouped = !!groupByState;
144
160
  // Infinite scroll (server mode, not grouped): load more on scroll-near-bottom.
145
161
  var canInfinite = infiniteScroll && !isGrouped;
162
+ // Grouped "Load more": chunked, button-triggered loading that merges into groups.
163
+ var hasMoreEffective = typeof hasMore === "boolean"
164
+ ? hasMore
165
+ : isServerPagination
166
+ ? tableData.length < totalRecords
167
+ : false;
168
+ var canGroupLoadMore = isGrouped && groupLoadMore && hasMoreEffective;
146
169
  var groupPalette = (0, react_1.useMemo)(function () { return (0, table_1.buildTablePalette)(theme); }, [theme]);
147
170
  var groupedSource = (0, react_1.useMemo)(function () {
148
171
  if (!isGrouped)
@@ -152,8 +175,8 @@ function Table(_a) {
152
175
  var renderGroups = (0, react_1.useMemo)(function () {
153
176
  if (!isGrouped)
154
177
  return undefined;
155
- return (0, table_1.groupRows)(groupedSource, groupBy).map(function (g) { return (__assign(__assign({}, g), { color: (0, table_1.pickTableColor)(g.value, groupPalette, groupColors === null || groupColors === void 0 ? void 0 : groupColors[g.value]) })); });
156
- }, [isGrouped, groupedSource, groupBy, groupPalette, groupColors]);
178
+ return (0, table_1.groupRows)(groupedSource, groupByState).map(function (g) { return (__assign(__assign({}, g), { color: (0, table_1.pickTableColor)(g.value, groupPalette, groupColors === null || groupColors === void 0 ? void 0 : groupColors[g.value]) })); });
179
+ }, [isGrouped, groupedSource, groupByState, groupPalette, groupColors]);
157
180
  var onPaginationRef = (0, react_1.useRef)(onPagination);
158
181
  onPaginationRef.current = onPagination;
159
182
  var prevPageRef = (0, react_1.useRef)(currentPage);
@@ -180,6 +203,18 @@ function Table(_a) {
180
203
  prevPageRef.current = currentPage;
181
204
  }
182
205
  }, [currentPage, rowsPerPage]);
206
+ // Grouped "Load more": request the next chunk; parent appends it to `data` and
207
+ // the table re-groups so new rows land in their respective groups.
208
+ var handleGroupLoadMore = function () {
209
+ var _a;
210
+ if (isLoadingMore || isTableLoading || !hasMoreEffective)
211
+ return;
212
+ var chunk = loadMoreChunkSize !== null && loadMoreChunkSize !== void 0 ? loadMoreChunkSize : rowsPerPage;
213
+ var nextPage = Math.floor(tableData.length / (chunk || 1)) + 1;
214
+ var lastRecord = tableData.length > 0 ? tableData[tableData.length - 1] : undefined;
215
+ (_a = onPaginationRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationRef, nextPage, chunk, lastRecord, "next");
216
+ };
217
+ var groupLoadMoreCaption = totalRecords > 0 ? "Showing ".concat(tableData.length, " of ").concat(totalRecords) : undefined;
183
218
  var tablePaginationText = (0, react_1.useMemo)(function () { return isServerPagination
184
219
  ? "".concat(startRow + 1, " - ").concat(Math.min(startRow + rowsPerPage, totalRecords), " of ").concat(totalRecords)
185
220
  : "".concat(startRow + 1, " - ").concat(endRow > tableData.length ? tableData.length : endRow, " of ").concat(tableData.length); }, [startRow, rowsPerPage, totalRecords, endRow, tableData.length]);
@@ -292,17 +327,20 @@ function Table(_a) {
292
327
  react_1.default.createElement(TableSearch_1.default, { onSearch: onGlobalSearch }),
293
328
  isTableSettings && (react_1.default.createElement(react_1.default.Fragment, null,
294
329
  react_1.default.createElement(Divider_1.default, null),
295
- react_1.default.createElement(TableSettings_1.default, { columns: columnsList, onSave: function (cols) { return handleColumnPreferences(cols); }, tableSettings: tableSettings, density: densityState, onDensityChange: handleDensityChange }))),
330
+ react_1.default.createElement(TableSettings_1.default, { columns: columnsList, onSave: function (cols) { return handleColumnPreferences(cols); }, tableSettings: tableSettings, density: densityState, onDensityChange: handleDensityChange, groupBy: groupByState, onGroupByChange: handleGroupByChange }))),
296
331
  headerActions && (react_1.default.createElement(react_1.default.Fragment, null,
297
332
  react_1.default.createElement(Divider_1.default, null),
298
333
  react_1.default.createElement(HeaderActions_1.default, { actions: headerActions, selections: selection }))),
299
334
  react_1.default.createElement(ActiveFilters_1.default, { columns: columnsList, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch }),
300
335
  react_1.default.createElement(react_2.Box, { ml: "auto", display: "flex", alignItems: "center", gap: 2 },
336
+ canGroupLoadMore && loadMorePosition === "top" && (react_1.default.createElement(react_2.Box, { display: "flex", alignItems: "center", gap: 2, flex: "0 0 auto" },
337
+ groupLoadMoreCaption && (react_1.default.createElement(react_2.Box, { fontSize: "0.75rem", color: (_x = (_w = theme.colors) === null || _w === void 0 ? void 0 : _w.text) === null || _x === void 0 ? void 0 : _x[500], whiteSpace: "nowrap" }, groupLoadMoreCaption)),
338
+ react_1.default.createElement(Button_1.default, { size: "xs", variant: "outline", colorScheme: "gray", isLoading: isLoadingMore, loadingText: loadMoreText, onClick: handleGroupLoadMore, label: loadMoreText }))),
301
339
  (isPagination || isServerPagination) && !isGrouped && !canInfinite && !isCompactHeader && (react_1.default.createElement(react_2.Box, { flex: "0 0 auto" },
302
340
  react_1.default.createElement(Pagination_1.default, { columns: columns, currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions, isVisiblity: true }))),
303
341
  (isPagination || isServerPagination) && !isGrouped && !canInfinite && isCompactHeader && tableData.length > 0 && (react_1.default.createElement(react_2.Popover, { placement: "bottom-end" },
304
342
  react_1.default.createElement(react_2.PopoverTrigger, null,
305
- react_1.default.createElement(react_2.IconButton, { "aria-label": "More", size: "sm", variant: "ghost", icon: react_1.default.createElement(lucide_react_1.EllipsisVertical, { size: 18, color: (_x = (_w = theme.colors) === null || _w === void 0 ? void 0 : _w.text) === null || _x === void 0 ? void 0 : _x[500] }) })),
343
+ react_1.default.createElement(react_2.IconButton, { "aria-label": "More", size: "sm", variant: "ghost", icon: react_1.default.createElement(lucide_react_1.EllipsisVertical, { size: 18, color: (_z = (_y = theme.colors) === null || _y === void 0 ? void 0 : _y.text) === null || _z === void 0 ? void 0 : _z[500] }) })),
306
344
  react_1.default.createElement(react_2.PopoverContent, { maxW: "22rem", p: 2, overflow: "hidden" },
307
345
  react_1.default.createElement(react_2.PopoverBody, { p: 0 },
308
346
  react_1.default.createElement(Pagination_1.default, { columns: columns, currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions, isVisiblity: true }))))))),
@@ -349,15 +387,18 @@ function Table(_a) {
349
387
  zIndex: 999,
350
388
  },
351
389
  } },
352
- react_1.default.createElement(react_3.Thead, { position: "sticky", top: 0, zIndex: 4, bg: (_0 = (_z = (_y = theme.colors.table) === null || _y === void 0 ? void 0 : _y.hover) === null || _z === void 0 ? void 0 : _z[200]) !== null && _0 !== void 0 ? _0 : (_1 = theme.colors.secondary) === null || _1 === void 0 ? void 0 : _1[50] },
353
- react_1.default.createElement(TableHeader_1.default, { columns: columnsList, isCheckbox: isCheckbox, headerBgColor: headerBgColor !== null && headerBgColor !== void 0 ? headerBgColor : theme.colors.backgroundColor.muted, headerTextColor: headerTextColor !== null && headerTextColor !== void 0 ? headerTextColor : (_2 = theme.colors) === null || _2 === void 0 ? void 0 : _2.gray[600], freezedBgColor: freezedBgColor !== null && freezedBgColor !== void 0 ? freezedBgColor : theme.colors.backgroundColor.secondary, freezedTextColor: freezedTextColor !== null && freezedTextColor !== void 0 ? freezedTextColor : (_3 = theme.colors) === null || _3 === void 0 ? void 0 : _3.gray[600], handleSort: handleSort, headerRefs: headerRefs, columnWidths: columnWidths, columnsSort: columnsSort, noBorders: noBorders, handleCheckbox: handleCheckbox, isLoading: isTableLoading, checked: tableData.length !== 0 && selection.length === tableData.length
390
+ react_1.default.createElement(react_3.Thead, { position: "sticky", top: 0, zIndex: 4, bg: (_2 = (_1 = (_0 = theme.colors.table) === null || _0 === void 0 ? void 0 : _0.hover) === null || _1 === void 0 ? void 0 : _1[200]) !== null && _2 !== void 0 ? _2 : (_3 = theme.colors.secondary) === null || _3 === void 0 ? void 0 : _3[50] },
391
+ react_1.default.createElement(TableHeader_1.default, { columns: columnsList, isCheckbox: isCheckbox, headerBgColor: headerBgColor !== null && headerBgColor !== void 0 ? headerBgColor : theme.colors.backgroundColor.muted, headerTextColor: headerTextColor !== null && headerTextColor !== void 0 ? headerTextColor : (_4 = theme.colors) === null || _4 === void 0 ? void 0 : _4.gray[600], freezedBgColor: freezedBgColor !== null && freezedBgColor !== void 0 ? freezedBgColor : theme.colors.backgroundColor.secondary, freezedTextColor: freezedTextColor !== null && freezedTextColor !== void 0 ? freezedTextColor : (_5 = theme.colors) === null || _5 === void 0 ? void 0 : _5.gray[600], handleSort: handleSort, headerRefs: headerRefs, columnWidths: columnWidths, columnsSort: columnsSort, noBorders: noBorders, handleCheckbox: handleCheckbox, isLoading: isTableLoading, checked: tableData.length !== 0 && selection.length === tableData.length
354
392
  ? true
355
393
  : selection.length === 0
356
394
  ? false
357
395
  : "indeterminate", isContent: isContent, isLink: isLink, isActionFreeze: isActionFreeze, setColumnsSearch: setColumnsSearch, columnsSearch: columnsSearch, isSelecting: isSelecting })),
358
396
  react_1.default.createElement(react_3.Tbody, null,
359
- react_1.default.createElement(TableBody_1.default, { data: isGrouped ? groupedSource : _filteredData, groups: renderGroups, onAddItem: onAddItem, columns: columnsList, startRow: isGrouped ? 0 : startRow, endRow: endRow, scrollContainerRef: tableContainerRef, isCheckbox: isCheckbox, columnWidths: columnWidths, noBorders: noBorders, freezedBgColor: freezedBgColor !== null && freezedBgColor !== void 0 ? freezedBgColor : theme.colors.backgroundColor.secondary, freezedTextColor: freezedTextColor !== null && freezedTextColor !== void 0 ? freezedTextColor : (_4 = theme.colors) === null || _4 === void 0 ? void 0 : _4.gray[600], handleCheckbox: handleCheckbox, selections: selection, isLoading: isTableLoading, loadingSkeletonRows: loadingSkeletonRows, onRowClick: onRowClick, isContent: isContent, isLink: isLink, isActionFreeze: isActionFreeze, density: densityState, stripe: stripe, emptyState: emptyState }))),
397
+ react_1.default.createElement(TableBody_1.default, { data: isGrouped ? groupedSource : _filteredData, groups: renderGroups, onAddItem: onAddItem, columns: columnsList, startRow: isGrouped ? 0 : startRow, endRow: endRow, scrollContainerRef: tableContainerRef, isCheckbox: isCheckbox, columnWidths: columnWidths, noBorders: noBorders, freezedBgColor: freezedBgColor !== null && freezedBgColor !== void 0 ? freezedBgColor : theme.colors.backgroundColor.secondary, freezedTextColor: freezedTextColor !== null && freezedTextColor !== void 0 ? freezedTextColor : (_6 = theme.colors) === null || _6 === void 0 ? void 0 : _6.gray[600], handleCheckbox: handleCheckbox, selections: selection, isLoading: isTableLoading, loadingSkeletonRows: loadingSkeletonRows, onRowClick: onRowClick, isContent: isContent, isLink: isLink, isActionFreeze: isActionFreeze, density: densityState, stripe: stripe, emptyState: emptyState }))),
360
398
  canInfinite && isLoadingMore && (react_1.default.createElement(react_2.Flex, { justify: "center", align: "center", py: 3, gap: 2 },
361
- react_1.default.createElement(react_2.Spinner, { size: "sm", color: (_6 = (_5 = theme.colors) === null || _5 === void 0 ? void 0 : _5.primary) === null || _6 === void 0 ? void 0 : _6[500] }),
362
- react_1.default.createElement(react_2.Box, { fontSize: "0.75rem", color: (_8 = (_7 = theme.colors) === null || _7 === void 0 ? void 0 : _7.text) === null || _8 === void 0 ? void 0 : _8[500] }, "Loading more\u2026"))))))));
399
+ react_1.default.createElement(react_2.Spinner, { size: "sm", color: (_8 = (_7 = theme.colors) === null || _7 === void 0 ? void 0 : _7.primary) === null || _8 === void 0 ? void 0 : _8[500] }),
400
+ react_1.default.createElement(react_2.Box, { fontSize: "0.75rem", color: (_10 = (_9 = theme.colors) === null || _9 === void 0 ? void 0 : _9.text) === null || _10 === void 0 ? void 0 : _10[500] }, "Loading more\u2026")))),
401
+ canGroupLoadMore && loadMorePosition === "bottom" && (react_1.default.createElement(react_2.Flex, { justify: "center", align: "center", gap: 3, py: 3, borderTop: "0.063rem solid ".concat((_11 = theme.colors.border) === null || _11 === void 0 ? void 0 : _11[500]) },
402
+ groupLoadMoreCaption && (react_1.default.createElement(react_2.Box, { fontSize: "0.75rem", color: (_13 = (_12 = theme.colors) === null || _12 === void 0 ? void 0 : _12.text) === null || _13 === void 0 ? void 0 : _13[500] }, groupLoadMoreCaption)),
403
+ react_1.default.createElement(Button_1.default, { size: "xs", variant: "outline", colorScheme: "gray", isLoading: isLoadingMore, loadingText: loadMoreText, onClick: handleGroupLoadMore, label: loadMoreText })))))));
363
404
  }
@@ -9,7 +9,6 @@ export type TableEmptyState = {
9
9
  export type TableProps = {
10
10
  data: DataObject[];
11
11
  columns: TableHeaderProps[];
12
- groupBy?: string | number;
13
12
  groupColors?: Record<string | number, string>;
14
13
  onAddItem?: (groupValue: string | number) => void;
15
14
  density?: TableDensity;
@@ -36,6 +35,10 @@ export type TableProps = {
36
35
  infiniteScroll?: boolean;
37
36
  hasMore?: boolean;
38
37
  isLoadingMore?: boolean;
38
+ groupLoadMore?: boolean;
39
+ loadMoreText?: string;
40
+ loadMorePosition?: "top" | "bottom";
41
+ loadMoreChunkSize?: number;
39
42
  noOfRowsPerPage?: number;
40
43
  totalRecords?: number;
41
44
  onPagination?: (page: number, noOfRecords: number, record: DataObject | undefined, direction: "next" | "prev" | "first" | "last") => void;
@@ -6,7 +6,7 @@ type TableRowActions = {
6
6
  actions?: () => ReactNode;
7
7
  [key: string]: any;
8
8
  };
9
- declare const TableActions: ({ row }: {
9
+ declare const TableActions: React.MemoExoticComponent<({ row }: {
10
10
  row?: TableRowActions;
11
- }) => React.JSX.Element | null;
11
+ }) => React.JSX.Element | null>;
12
12
  export default TableActions;
@@ -37,7 +37,7 @@ var react_1 = __importStar(require("react"));
37
37
  var react_2 = require("@chakra-ui/react");
38
38
  var lucide_react_1 = require("lucide-react");
39
39
  var useCustomTheme_1 = require("../../../Theme/useCustomTheme");
40
- var TableActions = function (_a) {
40
+ var TableActions = react_1.default.memo(function (_a) {
41
41
  var _b, _c, _d;
42
42
  var row = _a.row;
43
43
  var _e = (0, react_1.useState)(false), isOpen = _e[0], setIsOpen = _e[1];
@@ -76,7 +76,7 @@ var TableActions = function (_a) {
76
76
  react_1.default.createElement("div", { ref: ref },
77
77
  react_1.default.createElement(react_2.PopoverTrigger, null,
78
78
  react_1.default.createElement(react_2.IconButton, { "aria-label": "Actions", color: "black", icon: react_1.default.createElement(lucide_react_1.EllipsisVertical, { size: 17 }), size: "sm", p: 0, variant: "ghost", _hover: { transform: "scale(1.2)" }, onClick: function () { return (isOpen ? handleClose() : handleOpen()); } })),
79
- react_1.default.createElement(react_2.Portal, null,
79
+ isOpen && (react_1.default.createElement(react_2.Portal, null,
80
80
  react_1.default.createElement(react_2.PopoverContent, { w: "auto", minW: "100px", boxShadow: "lg", p: 0, zIndex: 999 },
81
81
  react_1.default.createElement(react_2.PopoverBody, { p: 0, m: 0 },
82
82
  react_1.default.createElement(react_2.VStack, { align: "stretch", spacing: 1, p: 0, m: 0 },
@@ -102,6 +102,7 @@ var TableActions = function (_a) {
102
102
  react_1.default.createElement(lucide_react_1.Trash2, { size: 17 }),
103
103
  " Delete")),
104
104
  row.actions && ((_d = row === null || row === void 0 ? void 0 : row.actions) === null || _d === void 0 ? void 0 : _d.call(row)),
105
- !row.onLink && !row.onEdit && !row.onDelete && (react_1.default.createElement(react_2.Button, { size: "sm", variant: "ghost", isDisabled: true, justifyContent: "center" }, "No actions")))))))));
106
- };
105
+ !row.onLink && !row.onEdit && !row.onDelete && (react_1.default.createElement(react_2.Button, { size: "sm", variant: "ghost", isDisabled: true, justifyContent: "center" }, "No actions"))))))))));
106
+ });
107
+ TableActions.displayName = "TableActions";
107
108
  exports.default = TableActions;
@@ -63,13 +63,44 @@ var EMPTY_SX = {};
63
63
  var EMPTY_HOVER = {};
64
64
  var TableRow = react_2.default.memo(function (_a) {
65
65
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
66
- var row = _a.row, rowIndex = _a.rowIndex, index = _a.index, isChecked = _a.isChecked, isExpanded = _a.isExpanded, isContent = _a.isContent, isLink = _a.isLink, isCheckbox = _a.isCheckbox, isLoading = _a.isLoading, isActionFreeze = _a.isActionFreeze, columns = _a.columns, leftOffsets = _a.leftOffsets, noBorders = _a.noBorders, freezedBgColor = _a.freezedBgColor, freezedTextColor = _a.freezedTextColor, theme = _a.theme, borderStyle = _a.borderStyle, hoverStyle = _a.hoverStyle, rowHeight = _a.rowHeight, cellPy = _a.cellPy, palette = _a.palette, accentColor = _a.accentColor, handleCheckbox = _a.handleCheckbox, onRowClick = _a.onRowClick, toggleRowExpansion = _a.toggleRowExpansion;
66
+ var row = _a.row, rowIndex = _a.rowIndex, index = _a.index, isChecked = _a.isChecked, isExpanded = _a.isExpanded, isContent = _a.isContent, isLink = _a.isLink, isCheckbox = _a.isCheckbox, isLoading = _a.isLoading, isActionFreeze = _a.isActionFreeze, columns = _a.columns, leftOffsets = _a.leftOffsets, noBorders = _a.noBorders, freezedBgColor = _a.freezedBgColor, freezedTextColor = _a.freezedTextColor, theme = _a.theme, borderStyle = _a.borderStyle, hoverStyle = _a.hoverStyle, rowHeight = _a.rowHeight, cellPy = _a.cellPy, palette = _a.palette, accentColor = _a.accentColor, handleCheckbox = _a.handleCheckbox, onRowClick = _a.onRowClick, toggleRowExpansion = _a.toggleRowExpansion, onMeasure = _a.onMeasure;
67
67
  var checkedSx = (0, react_2.useMemo)(function () {
68
68
  var _a, _b, _c;
69
69
  return isChecked ? {
70
70
  "& td": { backgroundColor: (_c = (_b = (_a = theme.colors.primary) === null || _a === void 0 ? void 0 : _a.opacity) === null || _b === void 0 ? void 0 : _b[16]) !== null && _c !== void 0 ? _c : theme.colors.disabled[100] },
71
71
  } : EMPTY_SX;
72
72
  }, [isChecked, (_b = theme.colors.primary) === null || _b === void 0 ? void 0 : _b.opacity, theme.colors.disabled]);
73
+ // Measured-height virtualization: report this row's real height (main + any
74
+ // expanded panel) so the windower can place variable/expandable rows exactly.
75
+ var mainRowRef = (0, react_2.useRef)(null);
76
+ var expandedRowRef = (0, react_2.useRef)(null);
77
+ var hasContent = !!row.content;
78
+ (0, react_2.useLayoutEffect)(function () {
79
+ if (!onMeasure)
80
+ return;
81
+ var measure = function () {
82
+ var _a, _b, _c, _d;
83
+ var main = (_b = (_a = mainRowRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0;
84
+ var exp = isExpanded && hasContent ? (_d = (_c = expandedRowRef.current) === null || _c === void 0 ? void 0 : _c.offsetHeight) !== null && _d !== void 0 ? _d : 0 : 0;
85
+ var h = main + exp;
86
+ if (h > 0)
87
+ onMeasure(row.id, h);
88
+ };
89
+ measure();
90
+ var raf = requestAnimationFrame(measure);
91
+ var ro;
92
+ if (typeof ResizeObserver !== "undefined") {
93
+ ro = new ResizeObserver(measure);
94
+ if (mainRowRef.current)
95
+ ro.observe(mainRowRef.current);
96
+ if (expandedRowRef.current)
97
+ ro.observe(expandedRowRef.current);
98
+ }
99
+ return function () {
100
+ cancelAnimationFrame(raf);
101
+ ro === null || ro === void 0 ? void 0 : ro.disconnect();
102
+ };
103
+ }, [onMeasure, isExpanded, hasContent, row.id]);
73
104
  var handleCellClick = (0, react_2.useCallback)(function (header) {
74
105
  if (!header.node && onRowClick) {
75
106
  onRowClick(row, { label: header.label, id: header.id });
@@ -78,7 +109,7 @@ var TableRow = react_2.default.memo(function (_a) {
78
109
  var firstDataColIndex = columns.findIndex(function (c) { return !c.isHidden; });
79
110
  var accentSx = accentColor ? "inset 3px 0 0 ".concat(accentColor) : undefined;
80
111
  return (react_2.default.createElement(react_2.default.Fragment, null,
81
- react_2.default.createElement(react_1.Tr, { opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: "opacity 0.2s", sx: checkedSx },
112
+ react_2.default.createElement(react_1.Tr, { ref: mainRowRef, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: "opacity 0.2s", sx: checkedSx },
82
113
  isContent && (react_2.default.createElement(react_1.Td, { w: "6", p: 0, fontSize: 14, backgroundColor: (_d = (_c = theme.colors) === null || _c === void 0 ? void 0 : _c.background) === null || _d === void 0 ? void 0 : _d[50], color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: accentSx, boxSizing: "border-box", left: 0, zIndex: 1, className: "columns sticky-columns" }, !!(row === null || row === void 0 ? void 0 : row.content) && (react_2.default.createElement(react_1.IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: (_e = theme.colors) === null || _e === void 0 ? void 0 : _e.gray[600], icon: isExpanded ? (react_2.default.createElement(lucide_react_1.ChevronDown, { fontSize: 16 })) : (react_2.default.createElement(lucide_react_1.ChevronRight, { fontSize: 16 })), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: function () { return toggleRowExpansion(rowIndex); }, variant: "ghost" })))),
83
114
  isCheckbox && (react_2.default.createElement(react_1.Td, { w: "6", fontSize: 14, fontWeight: 600, color: (_g = (_f = theme.colors) === null || _f === void 0 ? void 0 : _f.background) === null || _g === void 0 ? void 0 : _g[50], textTransform: "capitalize", backgroundColor: (_j = (_h = theme.colors) === null || _h === void 0 ? void 0 : _h.background) === null || _j === void 0 ? void 0 : _j[50], position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? accentSx : undefined, boxSizing: "border-box", left: 0, zIndex: 1, className: "columns sticky-columns" },
84
115
  react_2.default.createElement(Checkbox_1.default, { "aria-label": "Select all rows", onChange: function () { return handleCheckbox(row.id); }, isChecked: isChecked }))),
@@ -102,7 +133,7 @@ var TableRow = react_2.default.memo(function (_a) {
102
133
  : hoverStyle }, isStatus && statusColor ? (react_2.default.createElement(StatusCell, { value: (0, table_1.normalizeTableCellValue)(row[header.id]) })) : (react_2.default.createElement(react_1.Box, { display: "block", overflow: "hidden", whiteSpace: "normal", overflowWrap: "break-word" }, (0, table_1.normalizeTableCellValue)(header.node ? header.node(row) : row[header.id])))));
103
134
  }),
104
135
  isLink && (react_2.default.createElement(react_1.Td, { w: 2, p: 0, fontSize: 14, backgroundColor: (_l = (_k = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _k === void 0 ? void 0 : _k.background) === null || _l === void 0 ? void 0 : _l[50], color: freezedTextColor, position: isActionFreeze ? "sticky" : "relative", borderBottom: borderStyle, boxSizing: "border-box", right: 0, zIndex: 1, className: "columns sticky-columns".concat(isActionFreeze ? "-right" : "") }, (row.onLink || row.onEdit || row.onDelete) && (react_2.default.createElement(TableActions_1.default, { row: row }))))),
105
- row.content && isExpanded && (react_2.default.createElement(react_1.Tr, null,
136
+ row.content && isExpanded && (react_2.default.createElement(react_1.Tr, { ref: expandedRowRef },
106
137
  react_2.default.createElement(react_1.Td, { colSpan: columns.length +
107
138
  (isCheckbox ? 1 : 0) +
108
139
  (isContent ? 1 : 0) +
@@ -135,19 +166,32 @@ var TableBody = function (_a) {
135
166
  // remaining height with empty spacer rows. Spacer rows (rather than CSS
136
167
  // transforms) keep the table in normal flow so the sticky header and
137
168
  // `position: sticky` frozen columns keep working.
138
- // Disabled when expandable content rows are present, since those break the
139
- // fixed-height assumption.
169
+ // Expandable `content` rows are supported via measured heights (see
170
+ // `measuredHeights` / `onMeasure` below) — each rendered row reports its real
171
+ // height, so the window places variable/expanded rows exactly.
140
172
  var ROW_HEIGHT = rowHeight;
141
173
  var GROUP_HEADER_H = 42;
142
174
  var OVERSCAN = 6;
143
175
  var VIRTUALIZE_THRESHOLD = 30;
144
- var shouldVirtualize = !isContent && data.length > VIRTUALIZE_THRESHOLD;
176
+ var ESTIMATED_EXPAND = 120; // assumed extra height for an expanded-but-not-yet-measured row
177
+ var shouldVirtualize = data.length > VIRTUALIZE_THRESHOLD;
145
178
  // Grouped mode has no pager, so it virtualizes too (when no expandable rows):
146
179
  // group headers + rows form one flat sequence that we window over.
147
180
  var groupRowCount = groups ? groups.reduce(function (n, g) { return n + g.rows.length; }, 0) : 0;
148
181
  var groupVirtualize = !!groups && !isContent && groupRowCount > VIRTUALIZE_THRESHOLD;
149
182
  var _w = (0, react_2.useState)(0), scrollTop = _w[0], setScrollTop = _w[1];
150
183
  var _x = (0, react_2.useState)(0), viewportH = _x[0], setViewportH = _x[1];
184
+ // Measured row heights keyed by row id (stable across scroll/paging).
185
+ var _y = (0, react_2.useState)(new Map()), measuredHeights = _y[0], setMeasuredHeights = _y[1];
186
+ var reportHeight = (0, react_2.useCallback)(function (id, h) {
187
+ setMeasuredHeights(function (prev) {
188
+ if (prev.get(id) === h)
189
+ return prev;
190
+ var next = new Map(prev);
191
+ next.set(id, h);
192
+ return next;
193
+ });
194
+ }, []);
151
195
  (0, react_2.useEffect)(function () {
152
196
  var el = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
153
197
  if (!el || !(shouldVirtualize || groupVirtualize))
@@ -175,15 +219,37 @@ var TableBody = function (_a) {
175
219
  var total = data.length;
176
220
  var firstIndex = 0;
177
221
  var lastIndex = total;
222
+ var topPad = 0;
223
+ var bottomPad = 0;
178
224
  if (shouldVirtualize) {
179
225
  var vh = viewportH || 500;
180
- firstIndex = Math.max(0, Math.floor(scrollTop / ROW_HEIGHT) - OVERSCAN);
181
- var count = Math.ceil(vh / ROW_HEIGHT) + OVERSCAN * 2;
182
- lastIndex = Math.min(total, firstIndex + count);
226
+ // Prefix-sum offsets using measured heights (exact for rendered rows) and
227
+ // estimates for not-yet-measured rows (ROW_HEIGHT, + ESTIMATED_EXPAND if expanded).
228
+ var offsets = new Array(total + 1);
229
+ offsets[0] = 0;
230
+ for (var i = 0; i < total; i++) {
231
+ var id = data[i].id;
232
+ var measured = measuredHeights.get(id);
233
+ var h = measured != null
234
+ ? measured
235
+ : ROW_HEIGHT + (expandedRows.has(startRow + i) ? ESTIMATED_EXPAND : 0);
236
+ offsets[i + 1] = offsets[i] + h;
237
+ }
238
+ var totalH = offsets[total];
239
+ var top_1 = scrollTop - OVERSCAN * ROW_HEIGHT;
240
+ var bottom = scrollTop + vh + OVERSCAN * ROW_HEIGHT;
241
+ firstIndex = 0;
242
+ while (firstIndex < total && offsets[firstIndex + 1] <= top_1)
243
+ firstIndex++;
244
+ lastIndex = firstIndex;
245
+ while (lastIndex < total && offsets[lastIndex] < bottom)
246
+ lastIndex++;
247
+ if (lastIndex < firstIndex)
248
+ lastIndex = firstIndex;
249
+ topPad = offsets[firstIndex];
250
+ bottomPad = totalH - offsets[lastIndex];
183
251
  }
184
252
  var visibleRows = shouldVirtualize ? data.slice(firstIndex, lastIndex) : data;
185
- var topPad = firstIndex * ROW_HEIGHT;
186
- var bottomPad = (total - lastIndex) * ROW_HEIGHT;
187
253
  var toggleRowExpansion = (0, react_2.useCallback)(function (rowIndex) {
188
254
  setExpandedRows(function (prev) {
189
255
  var newSet = new Set(prev);
@@ -235,8 +301,8 @@ var TableBody = function (_a) {
235
301
  var g = groups_1[_i];
236
302
  items.push({ kind: "header", g: g });
237
303
  if (!collapsedGroups.has(g.value)) {
238
- for (var _y = 0, _z = g.rows; _y < _z.length; _y++) {
239
- var row = _z[_y];
304
+ for (var _z = 0, _0 = g.rows; _z < _0.length; _z++) {
305
+ var row = _0[_z];
240
306
  items.push({ kind: "row", g: g, row: row });
241
307
  }
242
308
  }
@@ -249,16 +315,16 @@ var TableBody = function (_a) {
249
315
  var heights_2 = items.map(function (it) { return (it.kind === "header" ? GROUP_HEADER_H : rowHeight); });
250
316
  var offsets_1 = [];
251
317
  var acc = 0;
252
- for (var _0 = 0, heights_1 = heights_2; _0 < heights_1.length; _0++) {
253
- var h = heights_1[_0];
318
+ for (var _1 = 0, heights_1 = heights_2; _1 < heights_1.length; _1++) {
319
+ var h = heights_1[_1];
254
320
  offsets_1.push(acc);
255
321
  acc += h;
256
322
  }
257
323
  var totalH = acc;
258
324
  var vh = viewportH || 500;
259
- var top_1 = scrollTop - OVERSCAN * rowHeight;
325
+ var top_2 = scrollTop - OVERSCAN * rowHeight;
260
326
  var bottom = scrollTop + vh + OVERSCAN * rowHeight;
261
- firstI_1 = items.findIndex(function (_, i) { return offsets_1[i] + heights_2[i] > top_1; });
327
+ firstI_1 = items.findIndex(function (_, i) { return offsets_1[i] + heights_2[i] > top_2; });
262
328
  if (firstI_1 < 0)
263
329
  firstI_1 = items.length;
264
330
  lastI = items.length;
@@ -295,7 +361,7 @@ var TableBody = function (_a) {
295
361
  var rowIndex = startRow + index;
296
362
  var isExpanded = expandedRows.has(rowIndex);
297
363
  var isChecked = selectionsSet.has(row.id);
298
- return (react_2.default.createElement(TableRow, { key: (_a = row.id) !== null && _a !== void 0 ? _a : rowIndex, row: row, rowIndex: rowIndex, index: index, isChecked: isChecked, isExpanded: isExpanded, isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: accentColors === null || accentColors === void 0 ? void 0 : accentColors[row.id], handleCheckbox: handleCheckbox, onRowClick: onRowClick, toggleRowExpansion: toggleRowExpansion }));
364
+ return (react_2.default.createElement(TableRow, { key: (_a = row.id) !== null && _a !== void 0 ? _a : rowIndex, row: row, rowIndex: rowIndex, index: index, isChecked: isChecked, isExpanded: isExpanded, isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: accentColors === null || accentColors === void 0 ? void 0 : accentColors[row.id], handleCheckbox: handleCheckbox, onRowClick: onRowClick, toggleRowExpansion: toggleRowExpansion, onMeasure: shouldVirtualize ? reportHeight : undefined }));
299
365
  }),
300
366
  shouldVirtualize && bottomPad > 0 && (react_2.default.createElement("tr", { "aria-hidden": "true", style: { height: bottomPad } },
301
367
  react_2.default.createElement("td", { colSpan: totalVisibleColumns, style: { padding: 0, border: "none", height: bottomPad } })))));
@@ -1,10 +1,12 @@
1
1
  import React from "react";
2
2
  import { TableDensity, TableProps } from "../TableProps";
3
- declare const TableSettings: ({ columns, onSave, density, onDensityChange, }: {
3
+ declare const TableSettings: ({ columns, onSave, density, onDensityChange, groupBy, onGroupByChange, }: {
4
4
  columns: TableProps["columns"];
5
5
  onSave: (updatedColumns: TableProps["columns"]) => void;
6
6
  tableSettings?: TableProps["tableSettings"];
7
7
  density?: TableDensity;
8
8
  onDensityChange?: (d: TableDensity) => void;
9
+ groupBy?: string | number;
10
+ onGroupByChange?: (value: string | number | undefined) => void;
9
11
  }) => React.JSX.Element;
10
12
  export default TableSettings;
@@ -43,6 +43,15 @@ var __importStar = (this && this.__importStar) || (function () {
43
43
  return result;
44
44
  };
45
45
  })();
46
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
47
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
48
+ if (ar || !(i in from)) {
49
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
50
+ ar[i] = from[i];
51
+ }
52
+ }
53
+ return to.concat(ar || Array.prototype.slice.call(from));
54
+ };
46
55
  var __importDefault = (this && this.__importDefault) || function (mod) {
47
56
  return (mod && mod.__esModule) ? mod : { "default": mod };
48
57
  };
@@ -62,20 +71,24 @@ var DENSITY_OPTIONS = [
62
71
  ];
63
72
  var TableSettings = function (_a) {
64
73
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
65
- var columns = _a.columns, onSave = _a.onSave, _p = _a.density, density = _p === void 0 ? "normal" : _p, onDensityChange = _a.onDensityChange;
74
+ var columns = _a.columns, onSave = _a.onSave, _p = _a.density, density = _p === void 0 ? "normal" : _p, onDensityChange = _a.onDensityChange, groupBy = _a.groupBy, onGroupByChange = _a.onGroupByChange;
66
75
  var theme = (0, useCustomTheme_1.useCustomTheme)();
67
76
  var childInputMethodsRef = (0, react_2.useRef)({});
68
77
  var _q = (0, react_2.useState)(false), settingsOpen = _q[0], setSettingsOpen = _q[1];
69
78
  var _r = (0, react_2.useState)(0), selectedIndex = _r[0], setSelectedIndex = _r[1];
70
79
  var _s = (0, react_2.useState)(columns), items = _s[0], setItems = _s[1];
80
+ // Group selection is applied on Save (not live), per "click Apply to group".
81
+ var _t = (0, react_2.useState)(groupBy), selectedGroup = _t[0], setSelectedGroup = _t[1];
71
82
  var handleSave = (0, react_2.useCallback)(function () {
72
83
  onSave(items);
84
+ onGroupByChange === null || onGroupByChange === void 0 ? void 0 : onGroupByChange(selectedGroup);
73
85
  setSettingsOpen(false);
74
- }, [onSave, items]);
86
+ }, [onSave, items, onGroupByChange, selectedGroup]);
75
87
  var handleOpen = (0, react_2.useCallback)(function () {
76
88
  setItems(columns);
89
+ setSelectedGroup(groupBy);
77
90
  setSettingsOpen(true);
78
- }, [columns]);
91
+ }, [columns, groupBy]);
79
92
  var tabStyle = {
80
93
  fontSize: "13px",
81
94
  fontWeight: 500,
@@ -102,7 +115,8 @@ var TableSettings = function (_a) {
102
115
  react_2.default.createElement(react_1.Text, { fontWeight: 600, fontSize: "md", mb: 3 }, "Table Settings"),
103
116
  react_2.default.createElement(react_1.TabList, { gap: 0, borderBottom: "1px solid", borderColor: (_l = (_k = theme.colors) === null || _k === void 0 ? void 0 : _k.border) === null || _l === void 0 ? void 0 : _l[200] },
104
117
  react_2.default.createElement(react_1.Tab, __assign({}, tabStyle), "Density"),
105
- react_2.default.createElement(react_1.Tab, __assign({}, tabStyle), "Manage Columns"))),
118
+ react_2.default.createElement(react_1.Tab, __assign({}, tabStyle), "Manage Columns"),
119
+ react_2.default.createElement(react_1.Tab, __assign({}, tabStyle), "Group"))),
106
120
  react_2.default.createElement(react_1.ModalBody, { px: 4, py: 3, flex: "1", overflowY: "auto", sx: {
107
121
  "&::-webkit-scrollbar": { width: "3px", height: "3px" },
108
122
  "&::-webkit-scrollbar-track": { background: theme.colors.gray[100], borderRadius: "2px" },
@@ -133,7 +147,18 @@ var TableSettings = function (_a) {
133
147
  "& .chakra-checkbox__label": { fontSize: "13px !important" },
134
148
  "& [draggable]": { py: "5px !important" },
135
149
  } },
136
- react_2.default.createElement(ManageColumns_1.default, { columns: columns, items: items, setItems: setItems, childInputMethodsRef: childInputMethodsRef })))))),
150
+ react_2.default.createElement(ManageColumns_1.default, { columns: columns, items: items, setItems: setItems, childInputMethodsRef: childInputMethodsRef }))),
151
+ react_2.default.createElement(react_1.TabPanel, { px: 0, py: 1 },
152
+ react_2.default.createElement(react_1.Text, { fontSize: "12px", color: theme.colors.gray[500], mb: 2 }, "Group rows by a column. Click Save to apply."),
153
+ react_2.default.createElement(react_1.Flex, { direction: "column", gap: 2 }, __spreadArray([{ id: undefined, label: "None (no grouping)" }], columns
154
+ .filter(function (c) { return !c.isHidden; })
155
+ .map(function (c) { return ({ id: c.id, label: String(c.label) }); }), true).map(function (opt) {
156
+ var _a, _b;
157
+ var selected = selectedGroup === opt.id;
158
+ return (react_2.default.createElement(react_1.Flex, { as: "button", type: "button", key: String((_a = opt.id) !== null && _a !== void 0 ? _a : "__none__"), align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "0.5rem", border: "1px solid", borderColor: selected ? theme.colors.primary[500] : (_b = theme.colors.boxborder) === null || _b === void 0 ? void 0 : _b[300], bg: selected ? theme.colors.primary.opacity[8] : "transparent", transition: "all 0.15s", _hover: { borderColor: theme.colors.primary[400] }, onClick: function () { return setSelectedGroup(opt.id); } },
159
+ react_2.default.createElement(react_1.Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.primary[500] : theme.colors.gray[400], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, selected && react_2.default.createElement(lucide_react_1.Check, { size: 11, color: theme.colors.primary[500], strokeWidth: 3 })),
160
+ react_2.default.createElement(react_1.Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], textAlign: "left" }, opt.label)));
161
+ })))))),
137
162
  react_2.default.createElement(react_1.ModalFooter, { gap: "0.5rem", borderTop: "1px solid", borderColor: (_o = (_m = theme.colors) === null || _m === void 0 ? void 0 : _m.border) === null || _o === void 0 ? void 0 : _o[200], pt: 3, pb: 3, px: 4 },
138
163
  react_2.default.createElement(Button_1.default, { label: "Close", size: "sm", onClick: function () { return setSettingsOpen(false); }, variant: "outline", colorScheme: "red" }),
139
164
  react_2.default.createElement(Button_1.default, { label: "Save", size: "sm", onClick: handleSave }))))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelize-design-library",
3
- "version": "2.3.1-beta.3",
3
+ "version": "2.3.1-beta.4",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",