pixelize-design-library 2.4.2-beta.46 → 2.4.2-beta.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -3
- package/COMPONENT-GOTCHAS.md +76 -7
- package/dist/Components/Common/chipTriggerSize.d.ts +10 -0
- package/dist/Components/Common/chipTriggerSize.js +15 -0
- package/dist/Components/Dropdown/DropDown.js +10 -8
- package/dist/Components/SearchSelect/SearchSelect.js +66 -20
- package/dist/Components/SearchSelect/SearchSelectProps.d.ts +5 -1
- package/dist/Components/SearchSelect/searchSelectSize.d.ts +0 -5
- package/dist/Components/SearchSelect/searchSelectSize.js +0 -12
- package/dist/Components/Select/SelectNative.d.ts +2 -0
- package/dist/Components/Select/SelectPopup.js +104 -43
- package/dist/Components/Select/SelectProps.d.ts +4 -0
- package/dist/Components/Select/optionRowInk.d.ts +4 -0
- package/dist/Components/Select/optionRowInk.js +12 -1
- package/dist/Components/SelectSearch/SelectSearch.js +8 -4
- package/dist/Components/SelectV2/SelectV2.d.ts +2 -9
- package/dist/Components/SelectV2/SelectV2.js +2 -10
- package/dist/Components/Switch/Switch.d.ts +1 -1
- package/dist/Components/Switch/Switch.js +4 -2
- package/dist/Components/Table/Table.js +6 -7
- package/dist/Components/Table/TableProps.d.ts +9 -1
- package/dist/Components/Table/components/Pagination.js +8 -5
- package/dist/Components/Table/components/TableBody.d.ts +2 -1
- package/dist/Components/Table/components/TableBody.js +82 -15
- package/dist/Components/Table/components/TableHeader.d.ts +1 -1
- package/dist/Components/Table/components/TableHeader.js +8 -9
- package/dist/Components/Table/components/rowMetrics.d.ts +0 -1
- package/dist/Components/Table/components/rowMetrics.js +1 -2
- package/dist/Components/Table/filters/CompactSelect.js +6 -3
- package/dist/Components/Table/hooks/useTable.d.ts +5 -1
- package/dist/Components/Table/hooks/useTable.js +43 -7
- package/dist/Theme/chakra/Menu.styles.d.ts +6 -0
- package/dist/Theme/chakra/Menu.styles.js +8 -0
- package/dist/Theme/chakra/componentStyles.d.ts +6 -0
- package/dist/Theme/tokens/builders/outlineRung.d.ts +2 -0
- package/dist/Theme/tokens/builders/outlineRung.js +14 -1
- package/dist/Theme/tokens/builders/rowStates.js +3 -4
- package/dist/Theme/tokens/primitives/optionRowSizes.d.ts +20 -0
- package/dist/Theme/tokens/primitives/optionRowSizes.js +29 -0
- package/dist/esm/Components/Common/chipTriggerSize.js +11 -0
- package/dist/esm/Components/Dropdown/DropDown.js +10 -8
- package/dist/esm/Components/SearchSelect/SearchSelect.js +66 -20
- package/dist/esm/Components/SearchSelect/searchSelectSize.js +0 -12
- package/dist/esm/Components/Select/SelectPopup.js +105 -44
- package/dist/esm/Components/Select/optionRowInk.js +9 -0
- package/dist/esm/Components/SelectSearch/SelectSearch.js +9 -5
- package/dist/esm/Components/SelectV2/SelectV2.js +2 -9
- package/dist/esm/Components/Switch/Switch.js +4 -2
- package/dist/esm/Components/Table/Table.js +6 -7
- package/dist/esm/Components/Table/components/Pagination.js +8 -5
- package/dist/esm/Components/Table/components/TableBody.js +81 -16
- package/dist/esm/Components/Table/components/TableHeader.js +8 -9
- package/dist/esm/Components/Table/components/rowMetrics.js +0 -1
- package/dist/esm/Components/Table/filters/CompactSelect.js +7 -4
- package/dist/esm/Components/Table/hooks/useTable.js +44 -8
- package/dist/esm/Theme/chakra/Menu.styles.js +8 -0
- package/dist/esm/Theme/tokens/builders/outlineRung.js +12 -0
- package/dist/esm/Theme/tokens/builders/rowStates.js +4 -5
- package/dist/esm/Theme/tokens/primitives/optionRowSizes.js +25 -0
- package/dist/esm/index.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +9 -4
- package/package.json +1 -1
|
@@ -185,7 +185,7 @@ export type TableHeaderProps = {
|
|
|
185
185
|
/** Legacy hex fill seed per value; used only when `statusPalette` lacks that value. */
|
|
186
186
|
statusColors?: Record<string, string>;
|
|
187
187
|
columnType?: TableColumnType;
|
|
188
|
-
/** Horizontal alignment for both the header label and the body cells. Defaults "start". */
|
|
188
|
+
/** Horizontal alignment for both the header label and the body cells. Defaults "start", except a full-bleed status cell, which centres until this is set. */
|
|
189
189
|
align?: TableColumnAlign;
|
|
190
190
|
/** Custom cell renderer; a column with `node` never fires onRowClick. */
|
|
191
191
|
node?: (data: DataObject) => JSX.Element | string | number | undefined;
|
|
@@ -214,6 +214,9 @@ export type TableHeaderPageProps = Pick<TableProps, "columns" | "isCheckbox" | "
|
|
|
214
214
|
handleHeaderClick?: (header: string, search: boolean) => void;
|
|
215
215
|
headerRefs: React.MutableRefObject<(HTMLTableCellElement | null)[]>;
|
|
216
216
|
columnWidths: number[];
|
|
217
|
+
/** Measures the select-all cell so frozen columns can butt against its real width. */
|
|
218
|
+
slotRef: React.Ref<HTMLTableCellElement>;
|
|
219
|
+
slotWidth: number;
|
|
217
220
|
columnsSort: ColumnSortingProps[];
|
|
218
221
|
handleCheckbox: (selection: string | number) => void;
|
|
219
222
|
checked: boolean | "indeterminate";
|
|
@@ -226,7 +229,11 @@ export type TableHeaderPageProps = Pick<TableProps, "columns" | "isCheckbox" | "
|
|
|
226
229
|
/** Props for the TableBody subcomponent; renders flat rows or grouped Monday-style board rows. */
|
|
227
230
|
export type TableBodyPageProps = Pick<TableProps, "columns" | "isCheckbox" | "data" | "freezedBgColor" | "freezedTextColor" | "noBorders" | "isLoading" | "loadingSkeletonRows" | "onRowClick" | "isActionFreeze" | "density" | "stripe" | "emptyState"> & {
|
|
228
231
|
startRow: number;
|
|
232
|
+
/** Page size; a change swaps the rendered rows without moving startRow, so scroll resets. */
|
|
233
|
+
rowsPerPage: number;
|
|
229
234
|
columnWidths: number[];
|
|
235
|
+
/** Rendered width of the select-all cell; frozen columns start after it. */
|
|
236
|
+
slotWidth: number;
|
|
230
237
|
handleCheckbox: (selection: string | number) => void;
|
|
231
238
|
selections: (string | number)[];
|
|
232
239
|
isContent: boolean;
|
|
@@ -262,6 +269,7 @@ export type ColumnHeaderProps = Pick<TableProps, "isCheckbox" | "noBorders"> & P
|
|
|
262
269
|
header: TableHeaderProps;
|
|
263
270
|
index: number;
|
|
264
271
|
columnWidths: number[];
|
|
272
|
+
slotWidth: number;
|
|
265
273
|
headerRefs: MutableRefObject<(HTMLTableCellElement | null)[]>;
|
|
266
274
|
columnsSearch: Record<string, string>;
|
|
267
275
|
setColumnsSearch: Dispatch<SetStateAction<Record<string, string>>>;
|
|
@@ -45,6 +45,8 @@ const useTable_1 = require("../hooks/useTable");
|
|
|
45
45
|
const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
|
|
46
46
|
const ToolTip_1 = __importDefault(require("../../ToolTip/ToolTip"));
|
|
47
47
|
const lucide_react_1 = require("lucide-react");
|
|
48
|
+
const STEP_SIZE = "1.5rem";
|
|
49
|
+
const STEP_ICON = 16;
|
|
48
50
|
const Pagination = react_1.default.memo(({ paginationText, handlePageSizeChange, rowsPerPage, currentPage, pages, setCurrentPage, dataLength, isServerPagination, paginationSelectOptions, }) => {
|
|
49
51
|
const computedOptions = (0, react_1.useMemo)(() => {
|
|
50
52
|
if (paginationSelectOptions && paginationSelectOptions.length) {
|
|
@@ -56,10 +58,11 @@ const Pagination = react_1.default.memo(({ paginationText, handlePageSizeChange,
|
|
|
56
58
|
return [...sizes].sort((a, b) => a - b);
|
|
57
59
|
}, [paginationSelectOptions, dataLength, rowsPerPage]);
|
|
58
60
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
const isLeftDisabled =
|
|
62
|
-
const isRightDisabled = dataLength === 0 || currentPage >=
|
|
63
|
-
|
|
61
|
+
const lastPage = Math.max(0, pages - 1);
|
|
62
|
+
// Stepping back is how a user escapes an empty page, so it survives an empty result.
|
|
63
|
+
const isLeftDisabled = currentPage === 0;
|
|
64
|
+
const isRightDisabled = dataLength === 0 || currentPage >= lastPage;
|
|
65
|
+
const step = (label, ariaLabel, icon, isDisabled, onClick) => ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: label, placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": ariaLabel, icon: icon, variant: "ghost", size: "xs", minW: STEP_SIZE, h: STEP_SIZE, rounded: "full", color: isDisabled ? theme.colors.textMuted : theme.colors.text[500], isDisabled: isDisabled, onClick: onClick, _hover: isDisabled ? {} : { color: theme.colors.accentText } }) }));
|
|
66
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "flex-end", align: "center", flexWrap: "nowrap", gap: "0.75rem", children: [(!isServerPagination || paginationSelectOptions) && ((0, jsx_runtime_1.jsx)(Select_1.default, { native: false, isSearchable: false, "aria-label": "Rows per page", onChange: (option) => option && handlePageSizeChange(Number(option.id)), value: rowsPerPage, size: "xs", width: "3.75rem", isDisabled: dataLength === 0, options: computedOptions.map((size) => ({ id: size, label: String(size) })) })), (dataLength > 0 || currentPage > 0) && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "0.125rem", children: [step("First", "first-page", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsLeft, { size: STEP_ICON }), isLeftDisabled, () => setCurrentPage(0)), step("Previous", "previous-page", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: STEP_ICON }), isLeftDisabled, () => setCurrentPage((page) => Math.max(0, page - 1))), (0, jsx_runtime_1.jsx)(react_2.Text, { px: "0.375rem", fontSize: "0.75rem", lineHeight: STEP_SIZE, whiteSpace: "nowrap", color: theme.colors.text[500], sx: { fontVariantNumeric: "tabular-nums" }, children: paginationText }), step("Next", "next-page", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: STEP_ICON }), isRightDisabled, () => setCurrentPage((page) => Math.min(lastPage, page + 1))), step("Last", "last-page", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsRight, { size: STEP_ICON }), isRightDisabled, () => setCurrentPage(lastPage))] }))] }));
|
|
64
67
|
});
|
|
65
68
|
exports.default = Pagination;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { TableBodyPageProps } from "../TableProps";
|
|
2
|
-
declare const
|
|
2
|
+
export declare const findFirstVisibleIndex: (offsets: number[], total: number, target: number) => number;
|
|
3
|
+
declare const TableBody: ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWidths, slotWidth, freezedBgColor, freezedTextColor, noBorders, handleCheckbox, selections, isLoading, onRowClick, isContent, isLink, isActionFreeze, loadingSkeletonRows, scrollContainerRef, density, stripe, accentColors, groups, onAddItem, emptyState, }: TableBodyPageProps) => import("react/jsx-runtime").JSX.Element;
|
|
3
4
|
export default TableBody;
|
|
@@ -36,6 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.findFirstVisibleIndex = void 0;
|
|
39
40
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
40
41
|
const react_1 = require("@chakra-ui/react");
|
|
41
42
|
const react_2 = __importStar(require("react"));
|
|
@@ -56,10 +57,31 @@ const getRowId = (row) => row.id;
|
|
|
56
57
|
const getRowContent = (row) => typeof row.content === "function"
|
|
57
58
|
? row.content
|
|
58
59
|
: undefined;
|
|
60
|
+
// Smallest index i in [0, total] where offsets[i+1] > target; offsets is sorted.
|
|
61
|
+
const findFirstVisibleIndex = (offsets, total, target) => {
|
|
62
|
+
let lo = 0;
|
|
63
|
+
let hi = total;
|
|
64
|
+
while (lo < hi) {
|
|
65
|
+
const mid = (lo + hi) >>> 1;
|
|
66
|
+
if (offsets[mid + 1] <= target) {
|
|
67
|
+
lo = mid + 1;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
hi = mid;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return lo;
|
|
74
|
+
};
|
|
75
|
+
exports.findFirstVisibleIndex = findFirstVisibleIndex;
|
|
59
76
|
// Monday-style status cell: the whole cell is filled with the status color and
|
|
60
77
|
// the label is centered in whichever of white/black clears AA against that fill —
|
|
61
78
|
// the fill can be a consumer hex we can't know in advance is light or dark.
|
|
62
|
-
const
|
|
79
|
+
const BLEED_JUSTIFY = {
|
|
80
|
+
start: "flex-start",
|
|
81
|
+
center: "center",
|
|
82
|
+
end: "flex-end",
|
|
83
|
+
};
|
|
84
|
+
const StatusCell = ({ value, onSolid, align, }) => ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", justifyContent: BLEED_JUSTIFY[align !== null && align !== void 0 ? align : "center"], w: "100%", h: "100%", px: "0.5rem", fontSize: "0.75rem", fontWeight: 600, color: onSolid, textAlign: align !== null && align !== void 0 ? align : "center", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: value }));
|
|
63
85
|
// Studio's status cell: a contained chip on the tone's soft rung. Same tone pair
|
|
64
86
|
// the group header already uses, so an override hex behaves identically in both.
|
|
65
87
|
const StatusPill = ({ value, soft, ink, radius, }) => ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "inline-flex", alignItems: "center", maxW: "100%", px: "0.5rem", py: "0.125rem", borderRadius: radius, bg: soft, color: ink, fontSize: "0.75rem", fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: value }));
|
|
@@ -148,13 +170,13 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
|
|
|
148
170
|
const bleedBg = statusColor === null || statusColor === void 0 ? void 0 : statusColor.soft;
|
|
149
171
|
const bleedInk = statusColor === null || statusColor === void 0 ? void 0 : statusColor.text;
|
|
150
172
|
const canHover = !isBleed && !((cellStyles === null || cellStyles === void 0 ? void 0 : cellStyles[header.id]) || rowStyle);
|
|
151
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? leftOffsets[headerIndex] : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? bleedBg : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : restBg, textAlign: isBleed ? undefined : header.align, textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
|
|
173
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? `${leftOffsets[headerIndex]}px` : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? bleedBg : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : restBg, textAlign: isBleed ? undefined : header.align, textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
|
|
152
174
|
? "none"
|
|
153
175
|
: `0.063rem solid ${isFrozen || isChecked
|
|
154
176
|
? variant.row.frozenRuleColor
|
|
155
177
|
: variant.row.ruleColor}`, className: `columns ${isFrozen ? "sticky-columns" : "scrollable-columns"}`, boxSizing: "border-box", color: isBleed ? bleedInk : variant.cells.ink, "data-hoverable": canHover ? "true" : "false", _hover: variant.row.hoverScope === "row" || !canHover
|
|
156
178
|
? EMPTY_HOVER
|
|
157
|
-
: hoverStyle, children: isBleed ? ((0, jsx_runtime_1.jsx)(StatusCell, { value: (0, table_1.normalizeTableCellValue)(row[header.id]), onSolid: bleedInk })) : isStatus && statusColor ? ((0, jsx_runtime_1.jsx)(StatusPill, { value: (0, table_1.normalizeTableCellValue)(row[header.id]), soft: statusColor.soft, ink: (0, pillInk_1.resolvePillInk)(statusColor.text, statusColor.soft, theme.colors.background[50]), radius: variant.cells.pillRadius })) : ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "block", overflow: "hidden", whiteSpace: "normal", overflowWrap: "break-word", children: (0, table_1.normalizeTableCellValue)(header.node ? header.node(row) : row[header.id]) })) }, headerIndex + 1));
|
|
179
|
+
: hoverStyle, children: isBleed ? ((0, jsx_runtime_1.jsx)(StatusCell, { value: (0, table_1.normalizeTableCellValue)(row[header.id]), onSolid: bleedInk, align: header.align })) : isStatus && statusColor ? ((0, jsx_runtime_1.jsx)(StatusPill, { value: (0, table_1.normalizeTableCellValue)(row[header.id]), soft: statusColor.soft, ink: (0, pillInk_1.resolvePillInk)(statusColor.text, statusColor.soft, theme.colors.background[50]), radius: variant.cells.pillRadius })) : ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "block", overflow: "hidden", whiteSpace: "normal", overflowWrap: "break-word", children: (0, table_1.normalizeTableCellValue)(header.node ? header.node(row) : row[header.id]) })) }, headerIndex + 1));
|
|
158
180
|
}), isLink && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: 2, p: 0, fontSize: 14, background: isChecked ? (isActionFreeze ? selectedFrozenBg : selectedBg) : isActionFreeze ? frozenCellBg : restBg, color: freezedTextColor, position: isActionFreeze ? "sticky" : "relative", borderBottom: borderStyle, boxSizing: "border-box", right: 0, zIndex: 1, className: `columns sticky-columns${isActionFreeze ? "-right" : ""}`, children: (row.onLink || row.onEdit || row.onDelete) ? ((0, jsx_runtime_1.jsx)(TableActions_1.default, { row: row })) : null }))] }), rowContent && isExpanded && ((0, jsx_runtime_1.jsx)(react_1.Tr, { ref: expandedRowRef, children: (0, jsx_runtime_1.jsx)(react_1.Td, { colSpan: columns.length +
|
|
159
181
|
(isCheckbox ? 1 : 0) +
|
|
160
182
|
(isContent ? 1 : 0) +
|
|
@@ -169,7 +191,7 @@ const TableEmpty = ({ emptyState }) => {
|
|
|
169
191
|
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: emptyState });
|
|
170
192
|
return ((0, jsx_runtime_1.jsx)(EmptyState_1.default, { size: "sm", minH: `${rowMetrics_1.EMPTY_STATE_HEIGHT}px`, title: structured === null || structured === void 0 ? void 0 : structured.title, description: structured === null || structured === void 0 ? void 0 : structured.description, icon: icon }));
|
|
171
193
|
};
|
|
172
|
-
const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedBgColor, freezedTextColor, noBorders, handleCheckbox, selections, isLoading, onRowClick, isContent, isLink, isActionFreeze, loadingSkeletonRows, scrollContainerRef, density, stripe = false, accentColors, groups, onAddItem, emptyState, }) => {
|
|
194
|
+
const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWidths, slotWidth, freezedBgColor, freezedTextColor, noBorders, handleCheckbox, selections, isLoading, onRowClick, isContent, isLink, isActionFreeze, loadingSkeletonRows, scrollContainerRef, density, stripe = false, accentColors, groups, onAddItem, emptyState, }) => {
|
|
173
195
|
var _a;
|
|
174
196
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
175
197
|
const variant = (0, TableVariantContext_1.useTableVariant)();
|
|
@@ -218,7 +240,15 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
218
240
|
const el = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
219
241
|
if (!el || !(shouldVirtualize || groupVirtualize))
|
|
220
242
|
return;
|
|
221
|
-
|
|
243
|
+
let rafId = null;
|
|
244
|
+
const onScroll = () => {
|
|
245
|
+
if (rafId != null)
|
|
246
|
+
return;
|
|
247
|
+
rafId = requestAnimationFrame(() => {
|
|
248
|
+
rafId = null;
|
|
249
|
+
setScrollTop(el.scrollTop);
|
|
250
|
+
});
|
|
251
|
+
};
|
|
222
252
|
const measure = () => setViewportH(el.clientHeight);
|
|
223
253
|
measure();
|
|
224
254
|
setScrollTop(el.scrollTop);
|
|
@@ -227,23 +257,30 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
227
257
|
return () => {
|
|
228
258
|
el.removeEventListener("scroll", onScroll);
|
|
229
259
|
window.removeEventListener("resize", measure);
|
|
260
|
+
if (rafId != null)
|
|
261
|
+
cancelAnimationFrame(rafId);
|
|
230
262
|
};
|
|
231
263
|
}, [scrollContainerRef, shouldVirtualize, groupVirtualize, data.length, groupRowCount]);
|
|
232
|
-
//
|
|
264
|
+
// Reset only on a real page change, never merely from the virtualization
|
|
265
|
+
// threshold flipping or rows being appended (infinite scroll/load-more).
|
|
266
|
+
const sliceKey = `${startRow}|${rowsPerPage}`;
|
|
267
|
+
const prevSliceKeyRef = (0, react_2.useRef)(sliceKey);
|
|
233
268
|
(0, react_2.useEffect)(() => {
|
|
234
|
-
|
|
269
|
+
const changed = prevSliceKeyRef.current !== sliceKey;
|
|
270
|
+
prevSliceKeyRef.current = sliceKey;
|
|
271
|
+
if (!changed)
|
|
235
272
|
return;
|
|
236
273
|
const el = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
237
274
|
if (el)
|
|
238
275
|
el.scrollTop = 0;
|
|
239
276
|
setScrollTop(0);
|
|
240
|
-
}, [
|
|
277
|
+
}, [sliceKey, scrollContainerRef]);
|
|
241
278
|
const total = data.length;
|
|
242
279
|
// Prefix-sum offsets using measured heights (exact for rendered rows) and
|
|
243
280
|
// estimates for not-yet-measured rows (ROW_HEIGHT, + ESTIMATED_EXPAND if expanded).
|
|
244
281
|
// Independent of scrollTop, so scrolling reuses it instead of rebuilding it.
|
|
245
282
|
const offsets = (0, react_2.useMemo)(() => {
|
|
246
|
-
if (!shouldVirtualize)
|
|
283
|
+
if (!shouldVirtualize || groups)
|
|
247
284
|
return null;
|
|
248
285
|
const acc = new Array(total + 1);
|
|
249
286
|
acc[0] = 0;
|
|
@@ -256,7 +293,7 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
256
293
|
acc[i + 1] = acc[i] + h;
|
|
257
294
|
}
|
|
258
295
|
return acc;
|
|
259
|
-
}, [shouldVirtualize, total, data, measuredHeights, expandedRows, startRow, ROW_HEIGHT, ESTIMATED_EXPAND]);
|
|
296
|
+
}, [shouldVirtualize, groups, total, data, measuredHeights, expandedRows, startRow, ROW_HEIGHT, ESTIMATED_EXPAND]);
|
|
260
297
|
let firstIndex = 0;
|
|
261
298
|
let lastIndex = total;
|
|
262
299
|
let topPad = 0;
|
|
@@ -266,9 +303,7 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
266
303
|
const totalH = offsets[total];
|
|
267
304
|
const top = scrollTop - OVERSCAN * ROW_HEIGHT;
|
|
268
305
|
const bottom = scrollTop + vh + OVERSCAN * ROW_HEIGHT;
|
|
269
|
-
firstIndex = 0;
|
|
270
|
-
while (firstIndex < total && offsets[firstIndex + 1] <= top)
|
|
271
|
-
firstIndex++;
|
|
306
|
+
firstIndex = (0, exports.findFirstVisibleIndex)(offsets, total, top);
|
|
272
307
|
lastIndex = firstIndex;
|
|
273
308
|
while (lastIndex < total && offsets[lastIndex] < bottom)
|
|
274
309
|
lastIndex++;
|
|
@@ -303,9 +338,9 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
303
338
|
(isContent ? 1 : 0) +
|
|
304
339
|
(isLink ? 1 : 0), [columns, isCheckbox, isContent, isLink]);
|
|
305
340
|
const leftOffsets = (0, react_2.useMemo)(() => {
|
|
306
|
-
const checkboxOffset = isCheckbox ?
|
|
341
|
+
const checkboxOffset = isCheckbox ? slotWidth : 0;
|
|
307
342
|
return columnWidths.map((_, idx) => columnWidths.slice(0, idx).reduce((sum, w) => sum + w, 0) + checkboxOffset);
|
|
308
|
-
}, [columnWidths, isCheckbox]);
|
|
343
|
+
}, [columnWidths, isCheckbox, slotWidth]);
|
|
309
344
|
const borderStyle = (0, react_2.useMemo)(() => noBorders ? "none" : `0.063rem solid ${variant.row.ruleColor}`, [noBorders, variant.row.ruleColor]);
|
|
310
345
|
// Selected-row tint applied per-cell (NOT a blanket `& td` override) so status
|
|
311
346
|
// cells keep their solid color + white text instead of white-on-tint.
|
|
@@ -342,6 +377,38 @@ const TableBody = ({ data, isCheckbox, columns, startRow, columnWidths, freezedB
|
|
|
342
377
|
}
|
|
343
378
|
return { heights, offsets, totalH: acc };
|
|
344
379
|
}, [groupItems, groupVirtualize, rowHeight]);
|
|
380
|
+
// Clamp scrollTop back when a shorter data set leaves it past the new content height.
|
|
381
|
+
(0, react_2.useEffect)(() => {
|
|
382
|
+
const totalH = shouldVirtualize && offsets ? offsets[total] : groupVirtualize && groupMetrics ? groupMetrics.totalH : null;
|
|
383
|
+
if (totalH == null)
|
|
384
|
+
return;
|
|
385
|
+
const maxScrollTop = Math.max(0, totalH - viewportH);
|
|
386
|
+
if (scrollTop > maxScrollTop) {
|
|
387
|
+
const el = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
388
|
+
if (el)
|
|
389
|
+
el.scrollTop = maxScrollTop;
|
|
390
|
+
setScrollTop(maxScrollTop);
|
|
391
|
+
}
|
|
392
|
+
}, [shouldVirtualize, offsets, total, groupVirtualize, groupMetrics, viewportH, scrollTop, scrollContainerRef]);
|
|
393
|
+
// Prune measured heights for rows no longer in data so the map stays bounded.
|
|
394
|
+
(0, react_2.useEffect)(() => {
|
|
395
|
+
setMeasuredHeights((prev) => {
|
|
396
|
+
if (prev.size === 0)
|
|
397
|
+
return prev;
|
|
398
|
+
const ids = new Set(data.map(getRowId));
|
|
399
|
+
let changed = false;
|
|
400
|
+
const next = new Map();
|
|
401
|
+
prev.forEach((h, id) => {
|
|
402
|
+
if (ids.has(id)) {
|
|
403
|
+
next.set(id, h);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
changed = true;
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
return changed ? next : prev;
|
|
410
|
+
});
|
|
411
|
+
}, [data]);
|
|
345
412
|
if (isLoading && data.length === 0) {
|
|
346
413
|
return ((0, jsx_runtime_1.jsx)(TableLoading_1.TableBodyLoading, { noOfColumns: totalVisibleColumns, borderColor: theme.colors.boxborder[200], rowsCount: typeof loadingSkeletonRows === "number" ? loadingSkeletonRows : 4, rowHeight: rowHeight }));
|
|
347
414
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { TableHeaderPageProps } from "../TableProps";
|
|
3
|
-
declare const _default: React.MemoExoticComponent<({ columns, isCheckbox, handleSort, headerRefs, columnWidths, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }: TableHeaderPageProps) => import("react/jsx-runtime").JSX.Element>;
|
|
3
|
+
declare const _default: React.MemoExoticComponent<({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }: TableHeaderPageProps) => import("react/jsx-runtime").JSX.Element>;
|
|
4
4
|
export default _default;
|
|
@@ -13,24 +13,23 @@ const TableFilters_1 = __importDefault(require("../filters/TableFilters"));
|
|
|
13
13
|
const lucide_react_1 = require("lucide-react");
|
|
14
14
|
const Checkbox_1 = __importDefault(require("../../Checkbox/Checkbox"));
|
|
15
15
|
const TableVariantContext_1 = require("../variants/TableVariantContext");
|
|
16
|
-
const rowMetrics_1 = require("./rowMetrics");
|
|
17
16
|
const motion_1 = require("../../../Theme/tokens/primitives/motion");
|
|
18
17
|
const motion_2 = require("../../../Theme/chakra/motion");
|
|
19
18
|
const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
|
|
20
19
|
const LABEL_JUSTIFY = { start: "space-between", center: "center", end: "flex-start" };
|
|
21
|
-
const TableHeader = ({ columns, isCheckbox, handleSort, headerRefs, columnWidths, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }) => {
|
|
20
|
+
const TableHeader = ({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }) => {
|
|
22
21
|
const [openFilterId, setOpenFilterId] = (0, react_2.useState)(null);
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Tr, { pr: 0, "aria-rowindex": 1, children: [isContent && (0, jsx_runtime_1.jsx)(ContentSpacerCell, { noBorders: noBorders }), isCheckbox && ((0, jsx_runtime_1.jsx)(SelectAllCell, { freezedTextColor: freezedTextColor, noBorders: noBorders, isSelecting: isSelecting, isLoading: isLoading, checked: checked, handleCheckbox: handleCheckbox })), columns.map((header, index) => {
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Tr, { pr: 0, "aria-rowindex": 1, children: [isContent && (0, jsx_runtime_1.jsx)(ContentSpacerCell, { noBorders: noBorders }), isCheckbox && ((0, jsx_runtime_1.jsx)(SelectAllCell, { slotRef: slotRef, freezedTextColor: freezedTextColor, noBorders: noBorders, isSelecting: isSelecting, isLoading: isLoading, checked: checked, handleCheckbox: handleCheckbox })), columns.map((header, index) => {
|
|
24
23
|
if (header === null || header === void 0 ? void 0 : header.isHidden)
|
|
25
24
|
return null;
|
|
26
|
-
return ((0, jsx_runtime_1.jsx)(ColumnHeader, { header: header, index: index, columnWidths: columnWidths, handleSort: handleSort, isCheckbox: isCheckbox, noBorders: noBorders, columnsSort: columnsSort, headerRefs: headerRefs, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch, openFilterId: openFilterId, setOpenFilterId: setOpenFilterId }, header.label));
|
|
25
|
+
return ((0, jsx_runtime_1.jsx)(ColumnHeader, { header: header, index: index, columnWidths: columnWidths, slotWidth: slotWidth, handleSort: handleSort, isCheckbox: isCheckbox, noBorders: noBorders, columnsSort: columnsSort, headerRefs: headerRefs, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch, openFilterId: openFilterId, setOpenFilterId: setOpenFilterId }, header.label));
|
|
27
26
|
}), isLink && (0, jsx_runtime_1.jsx)(ViewSpacerCell, { noBorders: noBorders, isActionFreeze: isActionFreeze })] }));
|
|
28
27
|
};
|
|
29
28
|
exports.default = (0, react_2.memo)(TableHeader);
|
|
30
|
-
const SelectAllCell = (0, react_2.memo)(({ freezedTextColor, noBorders, isSelecting, isLoading, checked, handleCheckbox, }) => {
|
|
29
|
+
const SelectAllCell = (0, react_2.memo)(({ slotRef, freezedTextColor, noBorders, isSelecting, isLoading, checked, handleCheckbox, }) => {
|
|
31
30
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
32
31
|
const variant = (0, TableVariantContext_1.useTableVariant)();
|
|
33
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Th, { scope: "col", w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: 14, fontWeight: 600, color: freezedTextColor, textTransform: "capitalize", backgroundColor: variant.header.bg, position: "sticky", className: `columns sticky-columns`, left: "0px", zIndex: 9, borderBottom: noBorders ? "none" : `0.063rem solid ${variant.header.ruleColor}`, children: (0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", justifyContent: "center", children: isSelecting ? ((0, jsx_runtime_1.jsx)(react_1.Spinner, { size: "sm", color: theme.colors.accentText })) : ((0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": "Select all rows", variant: "outline", onChange: () => handleCheckbox(0), isChecked: isLoading ? false : checked === true, isIndeterminate: checked === "indeterminate" })) }) }));
|
|
32
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Th, { ref: slotRef, scope: "col", w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: 14, fontWeight: 600, color: freezedTextColor, textTransform: "capitalize", backgroundColor: variant.header.bg, position: "sticky", className: `columns sticky-columns`, left: "0px", zIndex: 9, borderBottom: noBorders ? "none" : `0.063rem solid ${variant.header.ruleColor}`, children: (0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", justifyContent: "center", children: isSelecting ? ((0, jsx_runtime_1.jsx)(react_1.Spinner, { size: "sm", color: theme.colors.accentText })) : ((0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": "Select all rows", variant: "outline", onChange: () => handleCheckbox(0), isChecked: isLoading ? false : checked === true, isIndeterminate: checked === "indeterminate" })) }) }));
|
|
34
33
|
});
|
|
35
34
|
const ContentSpacerCell = (0, react_2.memo)(({ noBorders }) => {
|
|
36
35
|
const variant = (0, TableVariantContext_1.useTableVariant)();
|
|
@@ -48,7 +47,7 @@ const SortingIcon = (0, react_2.memo)(({ label, sortState, isVisible, handleSort
|
|
|
48
47
|
color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, variant.header.bg),
|
|
49
48
|
}, children: [sortState === "none" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { size: 14 }), sortState === "asc" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronUp, { size: 14 }), sortState === "desc" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14 })] }));
|
|
50
49
|
});
|
|
51
|
-
const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, isCheckbox, noBorders, columnsSort, headerRefs, columnsSearch, setColumnsSearch, handleSort, openFilterId, setOpenFilterId, }) => {
|
|
50
|
+
const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, slotWidth, isCheckbox, noBorders, columnsSort, headerRefs, columnsSearch, setColumnsSearch, handleSort, openFilterId, setOpenFilterId, }) => {
|
|
52
51
|
var _a, _b;
|
|
53
52
|
const [isHovered, setIsHovered] = (0, react_2.useState)(false);
|
|
54
53
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -56,7 +55,7 @@ const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, isCheckbo
|
|
|
56
55
|
const isFrozen = header.isFreeze;
|
|
57
56
|
const align = (_a = header.align) !== null && _a !== void 0 ? _a : "start";
|
|
58
57
|
const leftOffset = isFrozen
|
|
59
|
-
? (0, table_1.calculateLeftOffset)(columnWidths, index) + (isCheckbox ?
|
|
58
|
+
? (0, table_1.calculateLeftOffset)(columnWidths, index) + (isCheckbox ? slotWidth : 0)
|
|
60
59
|
: undefined;
|
|
61
60
|
const isSorting = header.isSort
|
|
62
61
|
? columnsSort.find((o) => o.column === header.id)
|
|
@@ -95,7 +94,7 @@ const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, isCheckbo
|
|
|
95
94
|
isSortActive ||
|
|
96
95
|
openFilterId === header.id ||
|
|
97
96
|
!!columnsSearch[header.id];
|
|
98
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Th, { scope: "col", ref: (el) => (headerRefs.current[index] = el), "aria-sort": ariaSort, textAlign: align, textTransform: variant.header.textTransform, fontSize: variant.header.fontSize, fontWeight: variant.header.fontWeight, letterSpacing: variant.header.letterSpacing, position: isFrozen ? "sticky" : undefined, left: isFrozen ? leftOffset : undefined, minWidth: 120, backgroundColor: variant.header.bg, maxWidth: 500, zIndex: isFrozen ? 2 : 1, py: 2, pr: align === "end" ? undefined : 0, overflow: "hidden", borderTop: "none", borderBottom: noBorders ? "none" : `0.063rem solid ${variant.header.ruleColor}`, borderRight: noBorders || !variant.header.showColumnRule
|
|
97
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Th, { scope: "col", ref: (el) => (headerRefs.current[index] = el), "aria-sort": ariaSort, textAlign: align, textTransform: variant.header.textTransform, fontSize: variant.header.fontSize, fontWeight: variant.header.fontWeight, letterSpacing: variant.header.letterSpacing, position: isFrozen ? "sticky" : undefined, left: isFrozen ? `${leftOffset}px` : undefined, minWidth: 120, backgroundColor: variant.header.bg, maxWidth: 500, zIndex: isFrozen ? 2 : 1, py: 2, pr: align === "end" ? undefined : 0, overflow: "hidden", borderTop: "none", borderBottom: noBorders ? "none" : `0.063rem solid ${variant.header.ruleColor}`, borderRight: noBorders || !variant.header.showColumnRule
|
|
99
98
|
? "none"
|
|
100
99
|
: `0.063rem solid ${variant.header.ruleColor}`, className: `columns ${isFrozen ? "sticky-columns" : "scrollable-columns"}`, height: variant.header.height, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", color: variant.header.ink, lineHeight: "1.25rem", justifyContent: LABEL_JUSTIFY[align], flexDirection: align === "end" ? "row-reverse" : "row", gap: align === "end" ? 1 : undefined, alignItems: "center", position: "relative", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { textAlign: align, textOverflow: "ellipsis", whiteSpace: "nowrap", display: "inline-block", overflow: "hidden", children: header.label }), (0, jsx_runtime_1.jsxs)(react_1.Box, { display: "inline-flex", alignItems: "center", opacity: showActions ? 1 : 0, transition: (0, motion_1.transitionFor)(["opacity"], "base"), sx: (0, motion_2.reducedMotionSx)(), _focusWithin: { opacity: 1 }, children: [header.isSort && ((0, jsx_runtime_1.jsx)(SortingIcon, { label: String(header.label), sortState: (_b = isSorting === null || isSorting === void 0 ? void 0 : isSorting.direction) !== null && _b !== void 0 ? _b : "none", isVisible: isHovered || isSortActive, handleSortClick: () => {
|
|
101
100
|
let direction = "asc";
|
|
@@ -6,6 +6,5 @@ export declare const DENSITY_ROWS: Record<TableDensity, {
|
|
|
6
6
|
export declare const TOOLBAR_HEIGHT = 45;
|
|
7
7
|
export declare const GROUP_HEADER_HEIGHT = 42;
|
|
8
8
|
export declare const EMPTY_STATE_HEIGHT = 200;
|
|
9
|
-
export declare const CHECKBOX_SLOT_OFFSET = 50;
|
|
10
9
|
export declare const rowHeightFor: (density: TableDensity | undefined) => number;
|
|
11
10
|
export declare const pxOf: (length: string) => number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pxOf = exports.rowHeightFor = exports.
|
|
3
|
+
exports.pxOf = exports.rowHeightFor = exports.EMPTY_STATE_HEIGHT = exports.GROUP_HEADER_HEIGHT = exports.TOOLBAR_HEIGHT = exports.DENSITY_ROWS = void 0;
|
|
4
4
|
exports.DENSITY_ROWS = {
|
|
5
5
|
compact: { height: 32, py: "0.125rem" },
|
|
6
6
|
normal: { height: 40, py: "0.5rem" },
|
|
@@ -9,7 +9,6 @@ exports.DENSITY_ROWS = {
|
|
|
9
9
|
exports.TOOLBAR_HEIGHT = 45;
|
|
10
10
|
exports.GROUP_HEADER_HEIGHT = 42;
|
|
11
11
|
exports.EMPTY_STATE_HEIGHT = 200;
|
|
12
|
-
exports.CHECKBOX_SLOT_OFFSET = 50;
|
|
13
12
|
const rowHeightFor = (density) => exports.DENSITY_ROWS[density !== null && density !== void 0 ? density : "normal"].height;
|
|
14
13
|
exports.rowHeightFor = rowHeightFor;
|
|
15
14
|
const pxOf = (length) => parseFloat(length);
|
|
@@ -6,10 +6,13 @@ const react_2 = require("@chakra-ui/react");
|
|
|
6
6
|
const lucide_react_1 = require("lucide-react");
|
|
7
7
|
const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
|
|
8
8
|
const rowStates_1 = require("../../../Theme/tokens/builders/rowStates");
|
|
9
|
+
const optionRowSizes_1 = require("../../../Theme/tokens/primitives/optionRowSizes");
|
|
10
|
+
const optionRowInk_1 = require("../../Select/optionRowInk");
|
|
9
11
|
const useExclusiveOverlay_1 = require("../../../Hooks/useExclusiveOverlay");
|
|
10
12
|
const CompactSelect = ({ options, value, placeholder = "Select", height = "22px", onSelect, size = "xs" }) => {
|
|
11
13
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
12
14
|
const rowBackgrounds = (0, react_1.useMemo)(() => (0, rowStates_1.listRowBackgrounds)(theme.colors), [theme.colors]);
|
|
15
|
+
const spec = (0, optionRowSizes_1.optionRowSpec)("xs");
|
|
13
16
|
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
14
17
|
const requestExclusiveOpen = (0, useExclusiveOverlay_1.useExclusiveOverlay)(isOpen, () => setIsOpen(false));
|
|
15
18
|
const openDropdown = () => {
|
|
@@ -63,15 +66,15 @@ const CompactSelect = ({ options, value, placeholder = "Select", height = "22px"
|
|
|
63
66
|
: isActive
|
|
64
67
|
? rowBackgrounds.active
|
|
65
68
|
: theme.colors.transparent;
|
|
66
|
-
return ((0, jsx_runtime_1.
|
|
69
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", role: "option", "aria-selected": selected, tabIndex: isActive ? 0 : -1, ref: (el) => {
|
|
67
70
|
optionRefs.current[i] = el;
|
|
68
|
-
}, w:
|
|
71
|
+
}, w: `calc(100% - 2 * ${spec.mx})`, minH: spec.minH, textAlign: "left", border: "none", fontFamily: "inherit", display: "flex", alignItems: "center", gap: spec.gap, mx: spec.mx, px: spec.px, py: spec.py, borderRadius: optionRowSizes_1.OPTION_ROW_RADIUS, cursor: "pointer", color: (0, optionRowInk_1.optionRowInk)(theme.colors, selected), fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(selected), _hover: {
|
|
69
72
|
bg: selected ? rowBackgrounds.selectedActive : rowBackgrounds.active,
|
|
70
73
|
}, bg: rowBg, onClick: () => {
|
|
71
74
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt);
|
|
72
75
|
setIsOpen(false);
|
|
73
76
|
setQuery("");
|
|
74
|
-
}, children: (0, jsx_runtime_1.jsx)(react_2.Text, {
|
|
77
|
+
}, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { flex: 1, minW: 0, isTruncated: true, children: opt.label }), selected && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: theme.colors.accentText, flexShrink: 0 }))] }, opt.id));
|
|
75
78
|
}), filtered.length === 0 && ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 2, py: 2, children: (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "0.75rem", color: theme.colors.textMuted, children: "No results" }) }))] })] }) }) }) })] }));
|
|
76
79
|
};
|
|
77
80
|
exports.default = CompactSelect;
|
|
@@ -12,17 +12,21 @@ type UseTableProps = {
|
|
|
12
12
|
totalRecords: number;
|
|
13
13
|
onNoOfRowsPerPageChange?: (noOfRows: number) => void;
|
|
14
14
|
defaultVisibleColumns?: number;
|
|
15
|
+
columnsSearch: Record<string, string>;
|
|
15
16
|
};
|
|
16
17
|
export declare const DEFAULT_PAGE_SIZE = 20;
|
|
17
|
-
declare const useTable: ({ data, isPagination, selections, onSelection, tablePreferences, savePreferences, noOfRowsPerPage, isServerPagination, totalRecords, columns, onNoOfRowsPerPageChange, defaultVisibleColumns, }: UseTableProps) => {
|
|
18
|
+
declare const useTable: ({ data, isPagination, selections, onSelection, tablePreferences, savePreferences, noOfRowsPerPage, isServerPagination, totalRecords, columns, onNoOfRowsPerPageChange, defaultVisibleColumns, columnsSearch, }: UseTableProps) => {
|
|
18
19
|
tableData: DataObject[];
|
|
19
20
|
isContent: boolean;
|
|
20
21
|
isLink: boolean;
|
|
21
22
|
headerRefs: import("react").MutableRefObject<(HTMLTableCellElement | null)[]>;
|
|
22
23
|
columnWidths: number[];
|
|
24
|
+
slotRef: (node: HTMLTableCellElement | null) => void;
|
|
25
|
+
slotWidth: number;
|
|
23
26
|
handleSort: (field: string | number, sort: "asc" | "desc" | "none") => void;
|
|
24
27
|
handleCheckbox: (id: string | number) => void;
|
|
25
28
|
filteredData: DataObject[];
|
|
29
|
+
searchedData: DataObject[];
|
|
26
30
|
startRow: number;
|
|
27
31
|
endRow: number;
|
|
28
32
|
selection: (string | number)[];
|
|
@@ -18,10 +18,25 @@ const mergeColumnWithPreference = (pref, originalCol) => {
|
|
|
18
18
|
}
|
|
19
19
|
return next;
|
|
20
20
|
};
|
|
21
|
-
const useTable = ({ data, isPagination, selections, onSelection, tablePreferences, savePreferences, noOfRowsPerPage, isServerPagination, totalRecords, columns, onNoOfRowsPerPageChange, defaultVisibleColumns, }) => {
|
|
21
|
+
const useTable = ({ data, isPagination, selections, onSelection, tablePreferences, savePreferences, noOfRowsPerPage, isServerPagination, totalRecords, columns, onNoOfRowsPerPageChange, defaultVisibleColumns, columnsSearch, }) => {
|
|
22
22
|
var _a, _b;
|
|
23
23
|
const headerRefs = (0, react_1.useRef)([]);
|
|
24
|
+
const slotObserver = (0, react_1.useRef)(null);
|
|
24
25
|
const [columnWidths, setColumnWidths] = (0, react_1.useState)([]);
|
|
26
|
+
const [slotWidth, setSlotWidth] = (0, react_1.useState)(0);
|
|
27
|
+
// Frozen columns butt against the select-all cell, so its width is watched, not assumed.
|
|
28
|
+
const slotRef = (0, react_1.useCallback)((node) => {
|
|
29
|
+
var _a;
|
|
30
|
+
(_a = slotObserver.current) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
31
|
+
slotObserver.current = null;
|
|
32
|
+
if (!node) {
|
|
33
|
+
setSlotWidth(0);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const observer = new ResizeObserver(() => setSlotWidth(node.offsetWidth));
|
|
37
|
+
observer.observe(node);
|
|
38
|
+
slotObserver.current = observer;
|
|
39
|
+
}, []);
|
|
25
40
|
const [selection, setSelection] = (0, react_1.useState)(selections !== null && selections !== void 0 ? selections : []);
|
|
26
41
|
const [columnsSort, setColumnsSort] = (0, react_1.useState)([]);
|
|
27
42
|
const [currentPage, setCurrentPage] = (0, react_1.useState)(0);
|
|
@@ -83,27 +98,45 @@ const useTable = ({ data, isPagination, selections, onSelection, tablePreference
|
|
|
83
98
|
if (!isServerPagination)
|
|
84
99
|
setCurrentPage(0);
|
|
85
100
|
}, [tableData.length, isServerPagination]);
|
|
101
|
+
const hasColumnSearch = (0, react_1.useMemo)(() => Object.values(columnsSearch).some((value) => value.trim() !== ""), [columnsSearch]);
|
|
102
|
+
// Column search runs before the page slice, or it would only ever see one page.
|
|
103
|
+
const searchedData = (0, react_1.useMemo)(() => (hasColumnSearch ? (0, table_1.searchAndSortData)(tableData, columnsSearch) : tableData), [hasColumnSearch, columnsSearch, tableData]);
|
|
86
104
|
const pages = (0, react_1.useMemo)(() => {
|
|
87
105
|
if (isServerPagination) {
|
|
88
106
|
return Math.ceil(totalRecords / (rowsPerPage || 1));
|
|
89
107
|
}
|
|
90
|
-
return isPagination ? Math.ceil(
|
|
108
|
+
return isPagination ? Math.ceil(searchedData.length / rowsPerPage) : 0;
|
|
91
109
|
}, [
|
|
92
110
|
isPagination,
|
|
93
111
|
rowsPerPage,
|
|
94
|
-
|
|
112
|
+
searchedData.length,
|
|
95
113
|
totalRecords,
|
|
96
114
|
isServerPagination,
|
|
97
115
|
]);
|
|
98
116
|
const startRow = (0, react_1.useMemo)(() => (!isPagination ? 0 : currentPage * rowsPerPage), [currentPage, isPagination, rowsPerPage]);
|
|
99
|
-
const endRow = (0, react_1.useMemo)(() => (!isPagination ?
|
|
117
|
+
const endRow = (0, react_1.useMemo)(() => (!isPagination ? searchedData.length : startRow + rowsPerPage), [isPagination, rowsPerPage, startRow, searchedData.length]);
|
|
100
118
|
const filteredData = (0, react_1.useMemo)(() => {
|
|
101
119
|
if (isServerPagination) {
|
|
102
|
-
return
|
|
120
|
+
return searchedData;
|
|
103
121
|
}
|
|
104
|
-
const sortedData = (0, table_1.SortMultiColumnData)(
|
|
122
|
+
const sortedData = (0, table_1.SortMultiColumnData)(searchedData, columnsSort);
|
|
105
123
|
return sortedData.slice(startRow, endRow);
|
|
106
|
-
}, [columnsSort, startRow, endRow,
|
|
124
|
+
}, [columnsSort, startRow, endRow, searchedData, isServerPagination]);
|
|
125
|
+
const searchKey = (0, react_1.useMemo)(() => JSON.stringify(columnsSearch), [columnsSearch]);
|
|
126
|
+
const prevSearchKey = (0, react_1.useRef)(searchKey);
|
|
127
|
+
(0, react_1.useEffect)(() => {
|
|
128
|
+
if (prevSearchKey.current === searchKey)
|
|
129
|
+
return;
|
|
130
|
+
prevSearchKey.current = searchKey;
|
|
131
|
+
setCurrentPage(0);
|
|
132
|
+
}, [searchKey]);
|
|
133
|
+
// A narrower result set can strand the user on a page that no longer exists.
|
|
134
|
+
(0, react_1.useEffect)(() => {
|
|
135
|
+
if (isServerPagination || !isPagination)
|
|
136
|
+
return;
|
|
137
|
+
const lastPage = Math.max(0, pages - 1);
|
|
138
|
+
setCurrentPage((page) => Math.min(page, lastPage));
|
|
139
|
+
}, [pages, isServerPagination, isPagination]);
|
|
107
140
|
const handlePageSizeChange = (size) => {
|
|
108
141
|
const value = Number(size);
|
|
109
142
|
setRowsPerPage(value !== 0 ? value : defaultPageSize);
|
|
@@ -198,9 +231,12 @@ const useTable = ({ data, isPagination, selections, onSelection, tablePreference
|
|
|
198
231
|
isLink,
|
|
199
232
|
headerRefs,
|
|
200
233
|
columnWidths,
|
|
234
|
+
slotRef,
|
|
235
|
+
slotWidth,
|
|
201
236
|
handleSort,
|
|
202
237
|
handleCheckbox,
|
|
203
238
|
filteredData,
|
|
239
|
+
searchedData,
|
|
204
240
|
startRow,
|
|
205
241
|
endRow,
|
|
206
242
|
selection,
|
|
@@ -4,7 +4,9 @@ exports.Menu = void 0;
|
|
|
4
4
|
const react_1 = require("@chakra-ui/react");
|
|
5
5
|
const anatomy_1 = require("@chakra-ui/anatomy");
|
|
6
6
|
const rowStates_1 = require("../tokens/builders/rowStates");
|
|
7
|
+
const optionRowSizes_1 = require("../tokens/primitives/optionRowSizes");
|
|
7
8
|
const paletteFromTheme_1 = require("./paletteFromTheme");
|
|
9
|
+
const itemRowSpec = optionRowSizes_1.OPTION_ROW_SIZES.sm;
|
|
8
10
|
const { defineMultiStyleConfig, definePartsStyle } = (0, react_1.createMultiStyleConfigHelpers)(anatomy_1.menuAnatomy.keys);
|
|
9
11
|
const $bg = (0, react_1.cssVar)("menu-bg");
|
|
10
12
|
// NOTE: fixes Chakra's MenuList/MenuItem both hardcoding --menu-bg to white via dead _dark — item needs its own var too, or hover snaps back to white.
|
|
@@ -24,6 +26,12 @@ const baseStyle = definePartsStyle(({ theme }) => {
|
|
|
24
26
|
borderColor: colors.boxborder[200],
|
|
25
27
|
},
|
|
26
28
|
item: {
|
|
29
|
+
minH: itemRowSpec.minH,
|
|
30
|
+
px: itemRowSpec.px,
|
|
31
|
+
py: itemRowSpec.py,
|
|
32
|
+
mx: itemRowSpec.mx,
|
|
33
|
+
fontSize: itemRowSpec.fontSize,
|
|
34
|
+
borderRadius: optionRowSizes_1.OPTION_ROW_RADIUS,
|
|
27
35
|
bg: "transparent",
|
|
28
36
|
_focus: { [$itemBg.variable]: hoverBg, bg: $itemBg.reference },
|
|
29
37
|
_hover: { [$itemBg.variable]: hoverBg, bg: $itemBg.reference },
|
|
@@ -176,6 +176,12 @@ export declare const componentStyles: {
|
|
|
176
176
|
borderColor: string;
|
|
177
177
|
};
|
|
178
178
|
item: {
|
|
179
|
+
minH: string;
|
|
180
|
+
px: string;
|
|
181
|
+
py: string;
|
|
182
|
+
mx: string;
|
|
183
|
+
fontSize: string;
|
|
184
|
+
borderRadius: string;
|
|
179
185
|
bg: string;
|
|
180
186
|
_focus: {
|
|
181
187
|
[x: string]: string;
|
|
@@ -4,6 +4,8 @@ export declare const AA_NON_TEXT = 3;
|
|
|
4
4
|
export declare const CHROME_BORDER = 1.5;
|
|
5
5
|
export declare const CHROME_RULE = 1.31;
|
|
6
6
|
export declare function ruleInk(hex: string, surfaces: readonly string[], target: number): string;
|
|
7
|
+
export declare const STACKED_STATE_STEP = 1.08;
|
|
8
|
+
export declare function tintStep(seed: string, backdrop: string, target: number): string;
|
|
7
9
|
export declare function liftToContrast(hex: string, backdrop: string, target?: number): string;
|
|
8
10
|
export declare function softenToContrast(hex: string, backdrop: string, target: number): string;
|
|
9
11
|
export declare function withOutlineRung(palette: PaletteProps): PaletteProps;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CHROME_RULE = exports.CHROME_BORDER = exports.AA_NON_TEXT = exports.MIN_PERCEPTIBLE_STEP = void 0;
|
|
3
|
+
exports.STACKED_STATE_STEP = exports.CHROME_RULE = exports.CHROME_BORDER = exports.AA_NON_TEXT = exports.MIN_PERCEPTIBLE_STEP = void 0;
|
|
4
4
|
exports.ruleInk = ruleInk;
|
|
5
|
+
exports.tintStep = tintStep;
|
|
5
6
|
exports.liftToContrast = liftToContrast;
|
|
6
7
|
exports.softenToContrast = softenToContrast;
|
|
7
8
|
exports.withOutlineRung = withOutlineRung;
|
|
@@ -20,6 +21,18 @@ function ruleInk(hex, surfaces, target) {
|
|
|
20
21
|
? softenToContrast(hex, loudest, target)
|
|
21
22
|
: hex;
|
|
22
23
|
}
|
|
24
|
+
exports.STACKED_STATE_STEP = 1.08;
|
|
25
|
+
// NOTE: walks out from the backdrop, so it settles a too-loud seed down as readily as it lifts a faint one.
|
|
26
|
+
function tintStep(seed, backdrop, target) {
|
|
27
|
+
const { s } = (0, color_1.hexToHsl)(seed);
|
|
28
|
+
const away = (0, color_1.relativeLuminance)(backdrop) < 0.5 ? 1 : -1;
|
|
29
|
+
for (let l = (0, color_1.hexToHsl)(backdrop).l; l >= 0 && l <= 100; l += away) {
|
|
30
|
+
const next = (0, color_1.withLightness)(seed, l, s);
|
|
31
|
+
if ((0, color_1.contrastRatio)(next, backdrop) >= target)
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
return (0, color_1.withLightness)(seed, away > 0 ? 100 : 0, s);
|
|
35
|
+
}
|
|
23
36
|
function liftToContrast(hex, backdrop, target = exports.AA_NON_TEXT) {
|
|
24
37
|
if ((0, color_1.contrastRatio)(hex, backdrop) >= target)
|
|
25
38
|
return hex;
|