hs-uix 1.0.0
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/README.md +80 -0
- package/datatable.d.ts +21 -0
- package/dist/datatable.js +1040 -0
- package/dist/datatable.mjs +1034 -0
- package/dist/form.js +1268 -0
- package/dist/form.mjs +1271 -0
- package/dist/index.js +2272 -0
- package/dist/index.mjs +2304 -0
- package/form.d.ts +17 -0
- package/index.d.ts +38 -0
- package/package.json +69 -0
|
@@ -0,0 +1,1040 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/datatable.js
|
|
30
|
+
var datatable_exports = {};
|
|
31
|
+
__export(datatable_exports, {
|
|
32
|
+
DataTable: () => DataTable
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(datatable_exports);
|
|
35
|
+
|
|
36
|
+
// packages/datatable/src/DataTable.jsx
|
|
37
|
+
var import_react = __toESM(require("react"));
|
|
38
|
+
var import_fuse = __toESM(require("fuse.js"));
|
|
39
|
+
var import_ui_extensions = require("@hubspot/ui-extensions");
|
|
40
|
+
var formatDateChip = (dateObj) => {
|
|
41
|
+
if (!dateObj) return "";
|
|
42
|
+
const { year, month, date } = dateObj;
|
|
43
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
44
|
+
month: "short",
|
|
45
|
+
day: "numeric",
|
|
46
|
+
year: "numeric"
|
|
47
|
+
}).format(new Date(year, month, date));
|
|
48
|
+
};
|
|
49
|
+
var dateToTimestamp = (dateObj) => {
|
|
50
|
+
if (!dateObj) return null;
|
|
51
|
+
return new Date(dateObj.year, dateObj.month, dateObj.date).getTime();
|
|
52
|
+
};
|
|
53
|
+
var NARROW_EDIT_TYPES = /* @__PURE__ */ new Set(["checkbox", "toggle"]);
|
|
54
|
+
var DATE_PATTERN = /^\d{4}[-/]\d{2}[-/]\d{2}/;
|
|
55
|
+
var BOOL_VALUES = /* @__PURE__ */ new Set(["true", "false", "yes", "no", "0", "1"]);
|
|
56
|
+
var SORT_DIRECTIONS = /* @__PURE__ */ new Set(["ascending", "descending", "none"]);
|
|
57
|
+
var normalizeSortState = (columns, sort) => {
|
|
58
|
+
const normalized = {};
|
|
59
|
+
columns.forEach((col) => {
|
|
60
|
+
if (col.sortable) normalized[col.field] = "none";
|
|
61
|
+
});
|
|
62
|
+
if (!sort) return normalized;
|
|
63
|
+
if (sort.field && SORT_DIRECTIONS.has(sort.direction) && sort.field in normalized) {
|
|
64
|
+
normalized[sort.field] = sort.direction;
|
|
65
|
+
return normalized;
|
|
66
|
+
}
|
|
67
|
+
Object.keys(normalized).forEach((field) => {
|
|
68
|
+
const direction = sort[field];
|
|
69
|
+
if (SORT_DIRECTIONS.has(direction)) normalized[field] = direction;
|
|
70
|
+
});
|
|
71
|
+
return normalized;
|
|
72
|
+
};
|
|
73
|
+
var serializeSortState = (sortState) => {
|
|
74
|
+
const activeField = Object.keys(sortState).find((field) => sortState[field] !== "none");
|
|
75
|
+
if (!activeField) return null;
|
|
76
|
+
return { field: activeField, direction: sortState[activeField] };
|
|
77
|
+
};
|
|
78
|
+
var toStableKey = (value) => {
|
|
79
|
+
try {
|
|
80
|
+
return JSON.stringify(value);
|
|
81
|
+
} catch (_error) {
|
|
82
|
+
return String(value);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var computeAutoWidths = (columns, data) => {
|
|
86
|
+
if (!data || data.length === 0) return {};
|
|
87
|
+
const sample = data.slice(0, 50);
|
|
88
|
+
const results = {};
|
|
89
|
+
columns.forEach((col) => {
|
|
90
|
+
if (col.width && col.cellWidth) return;
|
|
91
|
+
const values = sample.map((row) => row[col.field]).filter((v) => v != null);
|
|
92
|
+
const strings = values.map((v) => String(v));
|
|
93
|
+
let widthHint = null;
|
|
94
|
+
let cellWidthHint = null;
|
|
95
|
+
if (col.editable && col.editType && NARROW_EDIT_TYPES.has(col.editType)) {
|
|
96
|
+
cellWidthHint = "min";
|
|
97
|
+
}
|
|
98
|
+
if (strings.length > 0) {
|
|
99
|
+
const lengths = strings.map((s) => s.length);
|
|
100
|
+
const maxLen = Math.max(...lengths);
|
|
101
|
+
const uniqueCount = new Set(strings).size;
|
|
102
|
+
if (values.every((v) => typeof v === "boolean") || strings.every((s) => BOOL_VALUES.has(s.toLowerCase()))) {
|
|
103
|
+
widthHint = widthHint || "min";
|
|
104
|
+
cellWidthHint = cellWidthHint || "min";
|
|
105
|
+
} else if (strings.every((s) => DATE_PATTERN.test(s))) {
|
|
106
|
+
widthHint = widthHint || "min";
|
|
107
|
+
cellWidthHint = cellWidthHint || "auto";
|
|
108
|
+
} else if (values.every((v) => typeof v === "number")) {
|
|
109
|
+
widthHint = widthHint || "auto";
|
|
110
|
+
cellWidthHint = cellWidthHint || "auto";
|
|
111
|
+
} else if (uniqueCount <= 5 && maxLen <= 15) {
|
|
112
|
+
widthHint = widthHint || "min";
|
|
113
|
+
cellWidthHint = cellWidthHint || "auto";
|
|
114
|
+
} else {
|
|
115
|
+
widthHint = widthHint || "auto";
|
|
116
|
+
cellWidthHint = cellWidthHint || "auto";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (col.editable && !NARROW_EDIT_TYPES.has(col.editType) && widthHint === "min") {
|
|
120
|
+
widthHint = "auto";
|
|
121
|
+
}
|
|
122
|
+
results[col.field] = {
|
|
123
|
+
width: widthHint || "auto",
|
|
124
|
+
cellWidth: cellWidthHint || "auto"
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
return results;
|
|
128
|
+
};
|
|
129
|
+
var getEmptyFilterValue = (filter) => {
|
|
130
|
+
const type = filter.type || "select";
|
|
131
|
+
if (type === "multiselect") return [];
|
|
132
|
+
if (type === "dateRange") return { from: null, to: null };
|
|
133
|
+
return "";
|
|
134
|
+
};
|
|
135
|
+
var BOOLEAN_SELECT_OPTIONS = [
|
|
136
|
+
{ label: "Yes", value: true },
|
|
137
|
+
{ label: "No", value: false }
|
|
138
|
+
];
|
|
139
|
+
var resolveEditOptions = (col, data) => {
|
|
140
|
+
if (col.editOptions && col.editOptions.length > 0) return col.editOptions;
|
|
141
|
+
const sample = data.find((row) => row[col.field] != null);
|
|
142
|
+
if (sample && typeof sample[col.field] === "boolean") return BOOLEAN_SELECT_OPTIONS;
|
|
143
|
+
return [];
|
|
144
|
+
};
|
|
145
|
+
var isFilterActive = (filter, value) => {
|
|
146
|
+
const type = filter.type || "select";
|
|
147
|
+
if (type === "multiselect") return Array.isArray(value) && value.length > 0;
|
|
148
|
+
if (type === "dateRange") return value && (value.from || value.to);
|
|
149
|
+
return !!value;
|
|
150
|
+
};
|
|
151
|
+
var DataTable = ({
|
|
152
|
+
// Data
|
|
153
|
+
data,
|
|
154
|
+
columns,
|
|
155
|
+
renderRow,
|
|
156
|
+
// Search
|
|
157
|
+
searchFields = [],
|
|
158
|
+
searchPlaceholder = "Search...",
|
|
159
|
+
fuzzySearch = false,
|
|
160
|
+
// enable fuzzy matching via Fuse.js
|
|
161
|
+
fuzzyOptions,
|
|
162
|
+
// custom Fuse.js options (threshold, distance, etc.)
|
|
163
|
+
// Filters
|
|
164
|
+
filters = [],
|
|
165
|
+
showFilterBadges = true,
|
|
166
|
+
// show active filter chips/badges
|
|
167
|
+
showClearFiltersButton = true,
|
|
168
|
+
// show "Clear all" filters reset button
|
|
169
|
+
// Pagination
|
|
170
|
+
pageSize = 10,
|
|
171
|
+
maxVisiblePageButtons,
|
|
172
|
+
// max page number buttons to show
|
|
173
|
+
showButtonLabels = true,
|
|
174
|
+
// show First/Prev/Next/Last text labels
|
|
175
|
+
showFirstLastButtons,
|
|
176
|
+
// show First/Last page buttons (default: auto when pageCount > 5)
|
|
177
|
+
// Row count
|
|
178
|
+
showRowCount = true,
|
|
179
|
+
// show "X records" / "X of Y records" text
|
|
180
|
+
rowCountBold = false,
|
|
181
|
+
// bold the row count text
|
|
182
|
+
rowCountText,
|
|
183
|
+
// custom formatter: (shownOnPage, totalMatching) => string
|
|
184
|
+
// Table appearance
|
|
185
|
+
bordered = true,
|
|
186
|
+
// show table borders
|
|
187
|
+
flush = true,
|
|
188
|
+
// remove bottom margin
|
|
189
|
+
scrollable = false,
|
|
190
|
+
// allow horizontal overflow with scrollbar
|
|
191
|
+
// Sorting
|
|
192
|
+
defaultSort = {},
|
|
193
|
+
// Grouping
|
|
194
|
+
groupBy,
|
|
195
|
+
// Footer
|
|
196
|
+
footer,
|
|
197
|
+
// Empty state
|
|
198
|
+
emptyTitle,
|
|
199
|
+
emptyMessage,
|
|
200
|
+
// -----------------------------------------------------------------------
|
|
201
|
+
// Server-side mode
|
|
202
|
+
// -----------------------------------------------------------------------
|
|
203
|
+
serverSide = false,
|
|
204
|
+
loading = false,
|
|
205
|
+
// show loading spinner over the table
|
|
206
|
+
error,
|
|
207
|
+
// error message string or boolean — shows ErrorState
|
|
208
|
+
totalCount,
|
|
209
|
+
// server total (server-side only)
|
|
210
|
+
page: externalPage,
|
|
211
|
+
// controlled page (server-side only)
|
|
212
|
+
searchValue,
|
|
213
|
+
// controlled search term (server-side only)
|
|
214
|
+
filterValues: externalFilterValues,
|
|
215
|
+
// controlled filter values (server-side only)
|
|
216
|
+
sort: externalSort,
|
|
217
|
+
// controlled sort state, e.g. { field: "ascending" }
|
|
218
|
+
searchDebounce = 0,
|
|
219
|
+
// ms to debounce onSearchChange callback
|
|
220
|
+
resetPageOnChange = true,
|
|
221
|
+
// auto-reset to page 1 on search/filter/sort change
|
|
222
|
+
onSearchChange,
|
|
223
|
+
// (searchTerm) => void
|
|
224
|
+
onFilterChange,
|
|
225
|
+
// (filterValues) => void
|
|
226
|
+
onSortChange,
|
|
227
|
+
// (field, direction) => void
|
|
228
|
+
onPageChange,
|
|
229
|
+
// (page) => void
|
|
230
|
+
onParamsChange,
|
|
231
|
+
// ({ search, filters, sort, page }) => void
|
|
232
|
+
// -----------------------------------------------------------------------
|
|
233
|
+
// Row selection
|
|
234
|
+
// -----------------------------------------------------------------------
|
|
235
|
+
selectable = false,
|
|
236
|
+
rowIdField = "id",
|
|
237
|
+
// field name used as unique row identifier
|
|
238
|
+
selectedIds: externalSelectedIds,
|
|
239
|
+
// controlled selection — array of row IDs
|
|
240
|
+
onSelectionChange,
|
|
241
|
+
// (selectedIds[]) => void
|
|
242
|
+
onSelectAllRequest,
|
|
243
|
+
// server-side: ({ selectedIds, pageIds, totalCount }) => void
|
|
244
|
+
selectionActions = [],
|
|
245
|
+
// [{ label, onClick(selectedIds[]), icon?, variant? }]
|
|
246
|
+
selectionResetKey,
|
|
247
|
+
// optional key to force clear uncontrolled selection memory
|
|
248
|
+
resetSelectionOnQueryChange = true,
|
|
249
|
+
// clear uncontrolled selection on search/filter/sort changes
|
|
250
|
+
recordLabel,
|
|
251
|
+
// { singular: "Contact", plural: "Contacts" } — defaults to Record/Records
|
|
252
|
+
// -----------------------------------------------------------------------
|
|
253
|
+
// Row actions
|
|
254
|
+
// -----------------------------------------------------------------------
|
|
255
|
+
rowActions,
|
|
256
|
+
// [{ label, onClick(row), icon?, variant? }] or (row) => actions[]
|
|
257
|
+
hideRowActionsWhenSelectionActive = false,
|
|
258
|
+
// hide row action column while selected-row action bar is visible
|
|
259
|
+
// -----------------------------------------------------------------------
|
|
260
|
+
// Inline editing
|
|
261
|
+
// -----------------------------------------------------------------------
|
|
262
|
+
editMode,
|
|
263
|
+
// "discrete" (click-to-edit) | "inline" (always show inputs)
|
|
264
|
+
editingRowId,
|
|
265
|
+
// controlled — row ID currently in full-row edit mode
|
|
266
|
+
onRowEdit,
|
|
267
|
+
// (row, field, newValue) => void
|
|
268
|
+
onRowEditInput,
|
|
269
|
+
// optional live-input callback: (row, field, inputValue) => void
|
|
270
|
+
// -----------------------------------------------------------------------
|
|
271
|
+
// Auto-width
|
|
272
|
+
// -----------------------------------------------------------------------
|
|
273
|
+
autoWidth = true
|
|
274
|
+
// auto-compute column widths from content analysis
|
|
275
|
+
}) => {
|
|
276
|
+
const initialSortState = (0, import_react.useMemo)(() => {
|
|
277
|
+
return normalizeSortState(columns, defaultSort);
|
|
278
|
+
}, [columns, defaultSort]);
|
|
279
|
+
const [internalSearchTerm, setInternalSearchTerm] = (0, import_react.useState)("");
|
|
280
|
+
const [internalFilterValues, setInternalFilterValues] = (0, import_react.useState)(() => {
|
|
281
|
+
const init = {};
|
|
282
|
+
filters.forEach((f) => {
|
|
283
|
+
init[f.name] = getEmptyFilterValue(f);
|
|
284
|
+
});
|
|
285
|
+
return init;
|
|
286
|
+
});
|
|
287
|
+
const [internalSortState, setInternalSortState] = (0, import_react.useState)(initialSortState);
|
|
288
|
+
const [currentPage, setCurrentPage] = (0, import_react.useState)(1);
|
|
289
|
+
const [showMoreFilters, setShowMoreFilters] = (0, import_react.useState)(false);
|
|
290
|
+
const searchTerm = serverSide && searchValue != null ? searchValue : internalSearchTerm;
|
|
291
|
+
const filterValues = serverSide && externalFilterValues != null ? externalFilterValues : internalFilterValues;
|
|
292
|
+
const externalSortState = (0, import_react.useMemo)(
|
|
293
|
+
() => normalizeSortState(columns, externalSort),
|
|
294
|
+
[columns, externalSort]
|
|
295
|
+
);
|
|
296
|
+
const sortState = serverSide && externalSort != null ? externalSortState : internalSortState;
|
|
297
|
+
const activePage = serverSide && externalPage != null ? externalPage : currentPage;
|
|
298
|
+
(0, import_react.useEffect)(() => {
|
|
299
|
+
if (!serverSide) setCurrentPage(1);
|
|
300
|
+
}, [internalSearchTerm, internalFilterValues, internalSortState, serverSide]);
|
|
301
|
+
const debounceRef = (0, import_react.useRef)(null);
|
|
302
|
+
const fireSearchCallback = (0, import_react.useCallback)((term) => {
|
|
303
|
+
if (serverSide && onSearchChange) onSearchChange(term);
|
|
304
|
+
}, [serverSide, onSearchChange]);
|
|
305
|
+
const fireParamsChange = (0, import_react.useCallback)((overrides) => {
|
|
306
|
+
if (!onParamsChange) return;
|
|
307
|
+
const nextSortState = overrides.sort != null ? normalizeSortState(columns, overrides.sort) : sortState;
|
|
308
|
+
onParamsChange({
|
|
309
|
+
search: overrides.search != null ? overrides.search : searchTerm,
|
|
310
|
+
filters: overrides.filters != null ? overrides.filters : filterValues,
|
|
311
|
+
sort: serializeSortState(nextSortState),
|
|
312
|
+
page: overrides.page != null ? overrides.page : activePage
|
|
313
|
+
});
|
|
314
|
+
}, [onParamsChange, columns, searchTerm, filterValues, sortState, activePage]);
|
|
315
|
+
const resetPage = (0, import_react.useCallback)(() => {
|
|
316
|
+
if (resetPageOnChange) {
|
|
317
|
+
setCurrentPage(1);
|
|
318
|
+
if (serverSide && onPageChange) onPageChange(1);
|
|
319
|
+
}
|
|
320
|
+
}, [resetPageOnChange, serverSide, onPageChange]);
|
|
321
|
+
const handleSearchChange = (0, import_react.useCallback)((term) => {
|
|
322
|
+
setInternalSearchTerm(term);
|
|
323
|
+
resetPage();
|
|
324
|
+
if (searchDebounce > 0) {
|
|
325
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
326
|
+
debounceRef.current = setTimeout(() => {
|
|
327
|
+
fireSearchCallback(term);
|
|
328
|
+
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
329
|
+
}, searchDebounce);
|
|
330
|
+
} else {
|
|
331
|
+
fireSearchCallback(term);
|
|
332
|
+
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
333
|
+
}
|
|
334
|
+
}, [searchDebounce, fireSearchCallback, fireParamsChange, resetPage, resetPageOnChange]);
|
|
335
|
+
(0, import_react.useEffect)(() => () => {
|
|
336
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
337
|
+
}, []);
|
|
338
|
+
const handleFilterChange = (0, import_react.useCallback)((name, value) => {
|
|
339
|
+
const next = { ...filterValues, [name]: value };
|
|
340
|
+
setInternalFilterValues(next);
|
|
341
|
+
if (serverSide && onFilterChange) onFilterChange(next);
|
|
342
|
+
resetPage();
|
|
343
|
+
fireParamsChange({ filters: next, page: resetPageOnChange ? 1 : void 0 });
|
|
344
|
+
}, [filterValues, serverSide, onFilterChange, fireParamsChange, resetPage, resetPageOnChange]);
|
|
345
|
+
const handleSortChange = (0, import_react.useCallback)((field) => {
|
|
346
|
+
const current = sortState[field] || "none";
|
|
347
|
+
const nextDirection = current === "none" ? "ascending" : current === "ascending" ? "descending" : "none";
|
|
348
|
+
const reset = {};
|
|
349
|
+
columns.forEach((col) => {
|
|
350
|
+
if (col.sortable) reset[col.field] = "none";
|
|
351
|
+
});
|
|
352
|
+
const next = nextDirection === "none" ? reset : { ...reset, [field]: nextDirection };
|
|
353
|
+
setInternalSortState(next);
|
|
354
|
+
if (serverSide && onSortChange) onSortChange(field, nextDirection);
|
|
355
|
+
resetPage();
|
|
356
|
+
fireParamsChange({ sort: next, page: resetPageOnChange ? 1 : void 0 });
|
|
357
|
+
}, [sortState, columns, serverSide, onSortChange, fireParamsChange, resetPage, resetPageOnChange]);
|
|
358
|
+
const handlePageChange = (0, import_react.useCallback)((page) => {
|
|
359
|
+
setCurrentPage(page);
|
|
360
|
+
if (serverSide && onPageChange) onPageChange(page);
|
|
361
|
+
fireParamsChange({ page });
|
|
362
|
+
}, [serverSide, onPageChange, fireParamsChange]);
|
|
363
|
+
const filteredData = (0, import_react.useMemo)(() => {
|
|
364
|
+
if (serverSide) return data;
|
|
365
|
+
let result = data;
|
|
366
|
+
filters.forEach((filter) => {
|
|
367
|
+
const value = filterValues[filter.name];
|
|
368
|
+
if (!isFilterActive(filter, value)) return;
|
|
369
|
+
const type = filter.type || "select";
|
|
370
|
+
if (filter.filterFn) {
|
|
371
|
+
result = result.filter((row) => filter.filterFn(row, value));
|
|
372
|
+
} else if (type === "multiselect") {
|
|
373
|
+
result = result.filter((row) => value.includes(row[filter.name]));
|
|
374
|
+
} else if (type === "dateRange") {
|
|
375
|
+
const fromTs = dateToTimestamp(value.from);
|
|
376
|
+
const toTs = value.to ? dateToTimestamp(value.to) + 864e5 - 1 : null;
|
|
377
|
+
result = result.filter((row) => {
|
|
378
|
+
const rowTs = new Date(row[filter.name]).getTime();
|
|
379
|
+
if (Number.isNaN(rowTs)) return false;
|
|
380
|
+
if (fromTs && rowTs < fromTs) return false;
|
|
381
|
+
if (toTs && rowTs > toTs) return false;
|
|
382
|
+
return true;
|
|
383
|
+
});
|
|
384
|
+
} else {
|
|
385
|
+
result = result.filter((row) => row[filter.name] === value);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
if (searchTerm && searchFields.length > 0) {
|
|
389
|
+
if (fuzzySearch) {
|
|
390
|
+
const fuse = new import_fuse.default(result, {
|
|
391
|
+
keys: searchFields,
|
|
392
|
+
threshold: 0.4,
|
|
393
|
+
distance: 100,
|
|
394
|
+
ignoreLocation: true,
|
|
395
|
+
...fuzzyOptions
|
|
396
|
+
});
|
|
397
|
+
result = fuse.search(searchTerm).map((r) => r.item);
|
|
398
|
+
} else {
|
|
399
|
+
const term = searchTerm.toLowerCase();
|
|
400
|
+
result = result.filter(
|
|
401
|
+
(row) => searchFields.some((field) => {
|
|
402
|
+
const val = row[field];
|
|
403
|
+
return val && String(val).toLowerCase().includes(term);
|
|
404
|
+
})
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return result;
|
|
409
|
+
}, [data, filterValues, searchTerm, filters, searchFields, serverSide, fuzzySearch, fuzzyOptions]);
|
|
410
|
+
const sortedData = (0, import_react.useMemo)(() => {
|
|
411
|
+
if (serverSide) return filteredData;
|
|
412
|
+
const activeField = Object.keys(sortState).find((k) => sortState[k] !== "none");
|
|
413
|
+
if (!activeField) return filteredData;
|
|
414
|
+
return [...filteredData].sort((a, b) => {
|
|
415
|
+
const dir = sortState[activeField] === "ascending" ? 1 : -1;
|
|
416
|
+
const aVal = a[activeField];
|
|
417
|
+
const bVal = b[activeField];
|
|
418
|
+
if (aVal == null && bVal == null) return 0;
|
|
419
|
+
if (aVal == null) return 1;
|
|
420
|
+
if (bVal == null) return -1;
|
|
421
|
+
if (aVal < bVal) return -dir;
|
|
422
|
+
if (aVal > bVal) return dir;
|
|
423
|
+
return 0;
|
|
424
|
+
});
|
|
425
|
+
}, [filteredData, sortState, serverSide]);
|
|
426
|
+
const groupedData = (0, import_react.useMemo)(() => {
|
|
427
|
+
if (!groupBy) return null;
|
|
428
|
+
const source = serverSide ? data : sortedData;
|
|
429
|
+
const groups = {};
|
|
430
|
+
source.forEach((row) => {
|
|
431
|
+
const key = row[groupBy.field] ?? "--";
|
|
432
|
+
if (!groups[key]) groups[key] = [];
|
|
433
|
+
groups[key].push(row);
|
|
434
|
+
});
|
|
435
|
+
let groupKeys = Object.keys(groups);
|
|
436
|
+
if (groupBy.sort) {
|
|
437
|
+
if (typeof groupBy.sort === "function") {
|
|
438
|
+
groupKeys.sort(groupBy.sort);
|
|
439
|
+
} else {
|
|
440
|
+
const dir = groupBy.sort === "desc" ? -1 : 1;
|
|
441
|
+
groupKeys.sort((a, b) => a < b ? -dir : a > b ? dir : 0);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return groupKeys.map((key) => ({
|
|
445
|
+
key,
|
|
446
|
+
label: groupBy.label ? groupBy.label(key, groups[key]) : key,
|
|
447
|
+
rows: groups[key]
|
|
448
|
+
}));
|
|
449
|
+
}, [sortedData, data, groupBy, serverSide]);
|
|
450
|
+
const [expandedGroups, setExpandedGroups] = (0, import_react.useState)(() => {
|
|
451
|
+
if (!groupBy) return /* @__PURE__ */ new Set();
|
|
452
|
+
const defaultExpanded = groupBy.defaultExpanded !== false;
|
|
453
|
+
if (defaultExpanded && groupedData) {
|
|
454
|
+
return new Set(groupedData.map((g) => g.key));
|
|
455
|
+
}
|
|
456
|
+
return /* @__PURE__ */ new Set();
|
|
457
|
+
});
|
|
458
|
+
(0, import_react.useEffect)(() => {
|
|
459
|
+
if (!groupedData) return;
|
|
460
|
+
const defaultExpanded = (groupBy == null ? void 0 : groupBy.defaultExpanded) !== false;
|
|
461
|
+
if (defaultExpanded) {
|
|
462
|
+
setExpandedGroups((prev) => {
|
|
463
|
+
const next = new Set(prev);
|
|
464
|
+
groupedData.forEach((g) => next.add(g.key));
|
|
465
|
+
return next;
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
}, [groupedData, groupBy]);
|
|
469
|
+
const toggleGroup = (0, import_react.useCallback)((key) => {
|
|
470
|
+
setExpandedGroups((prev) => {
|
|
471
|
+
const next = new Set(prev);
|
|
472
|
+
if (next.has(key)) next.delete(key);
|
|
473
|
+
else next.add(key);
|
|
474
|
+
return next;
|
|
475
|
+
});
|
|
476
|
+
}, []);
|
|
477
|
+
const flatRows = (0, import_react.useMemo)(() => {
|
|
478
|
+
if (!groupedData) return (serverSide ? data : sortedData).map((row) => ({ type: "data", row }));
|
|
479
|
+
const flat = [];
|
|
480
|
+
groupedData.forEach((group) => {
|
|
481
|
+
flat.push({ type: "group-header", group });
|
|
482
|
+
if (expandedGroups.has(group.key)) {
|
|
483
|
+
group.rows.forEach((row) => flat.push({ type: "data", row }));
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
return flat;
|
|
487
|
+
}, [groupedData, sortedData, data, serverSide, expandedGroups]);
|
|
488
|
+
const totalItems = serverSide ? totalCount || data.length : flatRows.length;
|
|
489
|
+
const pageCount = Math.ceil(totalItems / pageSize);
|
|
490
|
+
let displayRows;
|
|
491
|
+
if (serverSide) {
|
|
492
|
+
displayRows = groupBy ? flatRows : data.map((row) => ({ type: "data", row }));
|
|
493
|
+
} else {
|
|
494
|
+
displayRows = flatRows.slice(
|
|
495
|
+
(activePage - 1) * pageSize,
|
|
496
|
+
activePage * pageSize
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
const footerData = serverSide ? data : filteredData;
|
|
500
|
+
const activeChips = (0, import_react.useMemo)(() => {
|
|
501
|
+
const chips = [];
|
|
502
|
+
filters.forEach((filter) => {
|
|
503
|
+
const value = filterValues[filter.name];
|
|
504
|
+
if (!isFilterActive(filter, value)) return;
|
|
505
|
+
const type = filter.type || "select";
|
|
506
|
+
const prefix = filter.chipLabel || filter.placeholder || filter.name;
|
|
507
|
+
if (type === "multiselect") {
|
|
508
|
+
const labels = value.map((v) => {
|
|
509
|
+
var _a;
|
|
510
|
+
return ((_a = filter.options.find((o) => o.value === v)) == null ? void 0 : _a.label) || v;
|
|
511
|
+
}).join(", ");
|
|
512
|
+
chips.push({ key: filter.name, label: `${prefix}: ${labels}` });
|
|
513
|
+
} else if (type === "dateRange") {
|
|
514
|
+
const parts = [];
|
|
515
|
+
if (value.from) parts.push(`from ${formatDateChip(value.from)}`);
|
|
516
|
+
if (value.to) parts.push(`to ${formatDateChip(value.to)}`);
|
|
517
|
+
chips.push({ key: filter.name, label: `${prefix}: ${parts.join(" ")}` });
|
|
518
|
+
} else {
|
|
519
|
+
const option = filter.options.find((o) => o.value === value);
|
|
520
|
+
chips.push({ key: filter.name, label: `${prefix}: ${(option == null ? void 0 : option.label) || value}` });
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
return chips;
|
|
524
|
+
}, [filterValues, filters]);
|
|
525
|
+
const handleFilterRemove = (0, import_react.useCallback)((key) => {
|
|
526
|
+
if (key === "all") {
|
|
527
|
+
const cleared = {};
|
|
528
|
+
filters.forEach((f) => {
|
|
529
|
+
cleared[f.name] = getEmptyFilterValue(f);
|
|
530
|
+
});
|
|
531
|
+
setInternalFilterValues(cleared);
|
|
532
|
+
if (serverSide && onFilterChange) onFilterChange(cleared);
|
|
533
|
+
resetPage();
|
|
534
|
+
fireParamsChange({ filters: cleared, page: resetPageOnChange ? 1 : void 0 });
|
|
535
|
+
} else {
|
|
536
|
+
const filter = filters.find((f) => f.name === key);
|
|
537
|
+
const emptyVal = filter ? getEmptyFilterValue(filter) : "";
|
|
538
|
+
const next = { ...filterValues, [key]: emptyVal };
|
|
539
|
+
setInternalFilterValues(next);
|
|
540
|
+
if (serverSide && onFilterChange) onFilterChange(next);
|
|
541
|
+
resetPage();
|
|
542
|
+
fireParamsChange({ filters: next, page: resetPageOnChange ? 1 : void 0 });
|
|
543
|
+
}
|
|
544
|
+
}, [filters, filterValues, serverSide, onFilterChange, resetPage, fireParamsChange, resetPageOnChange]);
|
|
545
|
+
const displayCount = serverSide ? totalCount || data.length : filteredData.length;
|
|
546
|
+
const totalDataCount = serverSide ? totalCount || data.length : data.length;
|
|
547
|
+
const shownOnPageCount = displayRows.filter((item) => item.type === "data").length;
|
|
548
|
+
const pluralLabel = ((recordLabel == null ? void 0 : recordLabel.plural) || "records").toLowerCase();
|
|
549
|
+
const singularLabel = ((recordLabel == null ? void 0 : recordLabel.singular) || "record").toLowerCase();
|
|
550
|
+
const countLabel = (n) => n === 1 ? singularLabel : pluralLabel;
|
|
551
|
+
const resolvedEmptyTitle = emptyTitle || "No results found";
|
|
552
|
+
const resolvedEmptyMessage = emptyMessage || `No ${pluralLabel} match your search or filter criteria.`;
|
|
553
|
+
const resolvedLoadingLabel = `Loading ${pluralLabel}...`;
|
|
554
|
+
const recordCountLabel = rowCountText ? rowCountText(shownOnPageCount, displayCount) : displayCount === totalDataCount ? `${totalDataCount} ${countLabel(totalDataCount)}` : `${displayCount} of ${totalDataCount} ${countLabel(totalDataCount)}`;
|
|
555
|
+
const [internalSelectedIds, setInternalSelectedIds] = (0, import_react.useState)(/* @__PURE__ */ new Set());
|
|
556
|
+
const selectionResetRef = (0, import_react.useRef)("");
|
|
557
|
+
(0, import_react.useEffect)(() => {
|
|
558
|
+
if (externalSelectedIds != null) {
|
|
559
|
+
setInternalSelectedIds(new Set(externalSelectedIds));
|
|
560
|
+
}
|
|
561
|
+
}, [externalSelectedIds]);
|
|
562
|
+
const selectionQueryKey = (0, import_react.useMemo)(() => {
|
|
563
|
+
if (!resetSelectionOnQueryChange) return "";
|
|
564
|
+
return toStableKey({
|
|
565
|
+
search: searchTerm,
|
|
566
|
+
filters: filterValues,
|
|
567
|
+
sort: serializeSortState(sortState)
|
|
568
|
+
});
|
|
569
|
+
}, [searchTerm, filterValues, sortState, resetSelectionOnQueryChange]);
|
|
570
|
+
const combinedSelectionResetKey = (0, import_react.useMemo)(
|
|
571
|
+
() => `${selectionQueryKey}::${selectionResetKey == null ? "" : toStableKey(selectionResetKey)}`,
|
|
572
|
+
[selectionQueryKey, selectionResetKey]
|
|
573
|
+
);
|
|
574
|
+
(0, import_react.useEffect)(() => {
|
|
575
|
+
if (!selectable || externalSelectedIds != null) {
|
|
576
|
+
selectionResetRef.current = combinedSelectionResetKey;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (selectionResetRef.current && selectionResetRef.current !== combinedSelectionResetKey) {
|
|
580
|
+
setInternalSelectedIds(/* @__PURE__ */ new Set());
|
|
581
|
+
}
|
|
582
|
+
selectionResetRef.current = combinedSelectionResetKey;
|
|
583
|
+
}, [combinedSelectionResetKey, selectable, externalSelectedIds]);
|
|
584
|
+
const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
|
|
585
|
+
const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
|
|
586
|
+
const applySelection = (0, import_react.useCallback)((nextSet) => {
|
|
587
|
+
if (externalSelectedIds == null) {
|
|
588
|
+
setInternalSelectedIds(nextSet);
|
|
589
|
+
}
|
|
590
|
+
if (onSelectionChange) onSelectionChange([...nextSet]);
|
|
591
|
+
}, [externalSelectedIds, onSelectionChange]);
|
|
592
|
+
const pageRowIds = (0, import_react.useMemo)(() => {
|
|
593
|
+
if (serverSide) {
|
|
594
|
+
return data.map((row) => row[rowIdField]).filter((id) => id != null);
|
|
595
|
+
}
|
|
596
|
+
return displayRows.filter((r) => r.type === "data").map((r) => r.row[rowIdField]).filter((id) => id != null);
|
|
597
|
+
}, [serverSide, data, displayRows, rowIdField]);
|
|
598
|
+
const allRowIds = (0, import_react.useMemo)(
|
|
599
|
+
() => flatRows.filter((r) => r.type === "data").map((r) => r.row[rowIdField]).filter((id) => id != null),
|
|
600
|
+
[flatRows, rowIdField]
|
|
601
|
+
);
|
|
602
|
+
const handleSelectRow = (0, import_react.useCallback)((rowId, checked) => {
|
|
603
|
+
const next = new Set(selectedIds);
|
|
604
|
+
if (checked) next.add(rowId);
|
|
605
|
+
else next.delete(rowId);
|
|
606
|
+
applySelection(next);
|
|
607
|
+
}, [selectedIds, applySelection]);
|
|
608
|
+
const handleSelectAll = (0, import_react.useCallback)((checked) => {
|
|
609
|
+
const next = new Set(selectedIds);
|
|
610
|
+
pageRowIds.forEach((id) => {
|
|
611
|
+
if (checked) next.add(id);
|
|
612
|
+
else next.delete(id);
|
|
613
|
+
});
|
|
614
|
+
applySelection(next);
|
|
615
|
+
}, [selectedIds, pageRowIds, applySelection]);
|
|
616
|
+
const allVisibleSelected = (0, import_react.useMemo)(() => {
|
|
617
|
+
return pageRowIds.length > 0 && pageRowIds.every((id) => selectedIds.has(id));
|
|
618
|
+
}, [pageRowIds, selectedIds]);
|
|
619
|
+
const handleSelectAllRows = (0, import_react.useCallback)(() => {
|
|
620
|
+
const idsToAdd = serverSide ? pageRowIds : allRowIds;
|
|
621
|
+
const next = new Set(selectedIds);
|
|
622
|
+
idsToAdd.forEach((id) => next.add(id));
|
|
623
|
+
applySelection(next);
|
|
624
|
+
if (serverSide && onSelectAllRequest) {
|
|
625
|
+
onSelectAllRequest({
|
|
626
|
+
selectedIds: [...next],
|
|
627
|
+
pageIds: pageRowIds,
|
|
628
|
+
totalCount: totalCount || data.length
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
}, [serverSide, pageRowIds, allRowIds, selectedIds, applySelection, onSelectAllRequest, totalCount, data.length]);
|
|
632
|
+
const handleDeselectAll = (0, import_react.useCallback)(() => {
|
|
633
|
+
applySelection(/* @__PURE__ */ new Set());
|
|
634
|
+
}, [applySelection]);
|
|
635
|
+
const [editingCell, setEditingCell] = (0, import_react.useState)(null);
|
|
636
|
+
const [editValue, setEditValue] = (0, import_react.useState)(null);
|
|
637
|
+
const [editError, setEditError] = (0, import_react.useState)(null);
|
|
638
|
+
const startEditing = (0, import_react.useCallback)((rowId, field, currentValue) => {
|
|
639
|
+
setEditingCell({ rowId, field });
|
|
640
|
+
setEditValue(currentValue);
|
|
641
|
+
setEditError(null);
|
|
642
|
+
}, []);
|
|
643
|
+
const commitEdit = (0, import_react.useCallback)((row, field, value) => {
|
|
644
|
+
const col = columns.find((c) => c.field === field);
|
|
645
|
+
if (col == null ? void 0 : col.editValidate) {
|
|
646
|
+
const result = col.editValidate(value, row);
|
|
647
|
+
if (result !== true && result !== void 0 && result !== null) {
|
|
648
|
+
setEditError(typeof result === "string" ? result : "Invalid value");
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (onRowEdit) onRowEdit(row, field, value);
|
|
653
|
+
setEditingCell(null);
|
|
654
|
+
setEditValue(null);
|
|
655
|
+
setEditError(null);
|
|
656
|
+
}, [onRowEdit, columns]);
|
|
657
|
+
const renderEditControl = (col, row) => {
|
|
658
|
+
const type = col.editType || "text";
|
|
659
|
+
const rowId = row[rowIdField];
|
|
660
|
+
const fieldName = `edit-${rowId}-${col.field}`;
|
|
661
|
+
const commit = (val) => commitEdit(row, col.field, val);
|
|
662
|
+
const exitEdit = () => {
|
|
663
|
+
if (editError) return;
|
|
664
|
+
setEditingCell(null);
|
|
665
|
+
setEditValue(null);
|
|
666
|
+
};
|
|
667
|
+
const extra = col.editProps || {};
|
|
668
|
+
const validate = col.editValidate;
|
|
669
|
+
const validationProps = validate && editError ? { error: true, validationMessage: editError } : {};
|
|
670
|
+
const onInputValidate = validate ? (val) => {
|
|
671
|
+
const result = validate(val, row);
|
|
672
|
+
if (result !== true && result !== void 0 && result !== null) {
|
|
673
|
+
setEditError(typeof result === "string" ? result : "Invalid value");
|
|
674
|
+
} else {
|
|
675
|
+
setEditError(null);
|
|
676
|
+
}
|
|
677
|
+
} : void 0;
|
|
678
|
+
const handleInput = (val) => {
|
|
679
|
+
setEditValue(val);
|
|
680
|
+
if (onInputValidate) onInputValidate(val);
|
|
681
|
+
if (onRowEditInput) onRowEditInput(row, col.field, val);
|
|
682
|
+
};
|
|
683
|
+
const maybeExitDatetimeEdit = () => {
|
|
684
|
+
if (typeof document === "undefined") return;
|
|
685
|
+
setTimeout(() => {
|
|
686
|
+
var _a, _b;
|
|
687
|
+
const activeName = (_b = (_a = document.activeElement) == null ? void 0 : _a.getAttribute) == null ? void 0 : _b.call(_a, "name");
|
|
688
|
+
if (activeName !== `${fieldName}-date` && activeName !== `${fieldName}-time`) {
|
|
689
|
+
exitEdit();
|
|
690
|
+
}
|
|
691
|
+
}, 0);
|
|
692
|
+
};
|
|
693
|
+
switch (type) {
|
|
694
|
+
case "textarea":
|
|
695
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TextArea, { ...extra, name: fieldName, label: "", value: editValue ?? "", onChange: commit, onBlur: exitEdit, ...validationProps, onInput: handleInput });
|
|
696
|
+
case "number":
|
|
697
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.NumberInput, { ...extra, name: fieldName, label: "", value: editValue, onChange: commit, onBlur: exitEdit, ...validationProps, onInput: handleInput });
|
|
698
|
+
case "currency":
|
|
699
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.CurrencyInput, { currencyCode: "USD", ...extra, name: fieldName, label: "", value: editValue, onChange: commit, onBlur: exitEdit, ...validationProps, onInput: handleInput });
|
|
700
|
+
case "stepper":
|
|
701
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.StepperInput, { ...extra, name: fieldName, label: "", value: editValue, onChange: commit, onBlur: exitEdit, ...validationProps, onInput: handleInput });
|
|
702
|
+
case "select":
|
|
703
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Select, { variant: "transparent", ...extra, name: fieldName, label: "", value: editValue, onChange: commit, options: resolveEditOptions(col, data) });
|
|
704
|
+
case "multiselect":
|
|
705
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.MultiSelect, { ...extra, name: fieldName, label: "", value: editValue || [], onChange: commit, options: resolveEditOptions(col, data) });
|
|
706
|
+
case "date":
|
|
707
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.DateInput, { ...extra, name: fieldName, label: "", value: editValue, onChange: commit });
|
|
708
|
+
case "time":
|
|
709
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TimeInput, { ...extra, name: fieldName, label: "", value: editValue, onChange: commit });
|
|
710
|
+
case "datetime":
|
|
711
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.DateInput, { ...extra, name: `${fieldName}-date`, label: "", value: editValue == null ? void 0 : editValue.date, onChange: (val) => {
|
|
712
|
+
const next = { ...editValue, date: val };
|
|
713
|
+
setEditValue(next);
|
|
714
|
+
if (onRowEdit) onRowEdit(row, col.field, next);
|
|
715
|
+
}, onBlur: maybeExitDatetimeEdit }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label: "", value: editValue == null ? void 0 : editValue.time, onChange: (val) => {
|
|
716
|
+
const next = { ...editValue, time: val };
|
|
717
|
+
setEditValue(next);
|
|
718
|
+
if (onRowEdit) onRowEdit(row, col.field, next);
|
|
719
|
+
}, onBlur: maybeExitDatetimeEdit }));
|
|
720
|
+
case "toggle":
|
|
721
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Toggle, { ...extra, name: fieldName, label: "", checked: !!editValue, onChange: commit });
|
|
722
|
+
case "checkbox":
|
|
723
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Checkbox, { ...extra, name: fieldName, checked: !!editValue, onChange: commit });
|
|
724
|
+
default:
|
|
725
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Input, { ...extra, name: fieldName, label: "", value: editValue ?? "", onChange: commit, onBlur: exitEdit, ...validationProps, onInput: handleInput });
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
const resolvedEditMode = editMode || (columns.some((col) => col.editable) ? "discrete" : null);
|
|
729
|
+
const useColumnRendering = selectable || !!resolvedEditMode || editingRowId != null || showRowActionsColumn || !renderRow;
|
|
730
|
+
const autoWidths = (0, import_react.useMemo)(
|
|
731
|
+
() => autoWidth ? computeAutoWidths(columns, data) : {},
|
|
732
|
+
[columns, data, autoWidth]
|
|
733
|
+
);
|
|
734
|
+
const defaultWidth = scrollable ? "min" : "auto";
|
|
735
|
+
const getHeaderWidth = (col) => {
|
|
736
|
+
var _a;
|
|
737
|
+
return col.width || ((_a = autoWidths[col.field]) == null ? void 0 : _a.width) || defaultWidth;
|
|
738
|
+
};
|
|
739
|
+
const getCellWidth = (col) => {
|
|
740
|
+
var _a;
|
|
741
|
+
return col.cellWidth || col.width || ((_a = autoWidths[col.field]) == null ? void 0 : _a.cellWidth) || defaultWidth;
|
|
742
|
+
};
|
|
743
|
+
const [inlineErrors, setInlineErrors] = (0, import_react.useState)({});
|
|
744
|
+
const renderInlineControl = (col, row) => {
|
|
745
|
+
const type = col.editType || "text";
|
|
746
|
+
const rowId = row[rowIdField];
|
|
747
|
+
const fieldName = `inline-${rowId}-${col.field}`;
|
|
748
|
+
const cellKey = `${rowId}-${col.field}`;
|
|
749
|
+
const value = row[col.field];
|
|
750
|
+
const validate = col.editValidate;
|
|
751
|
+
const fire = (val) => {
|
|
752
|
+
if (validate) {
|
|
753
|
+
const result = validate(val, row);
|
|
754
|
+
if (result !== true && result !== void 0 && result !== null) {
|
|
755
|
+
setInlineErrors((prev) => ({ ...prev, [cellKey]: typeof result === "string" ? result : "Invalid value" }));
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
setInlineErrors((prev) => {
|
|
759
|
+
const next = { ...prev };
|
|
760
|
+
delete next[cellKey];
|
|
761
|
+
return next;
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
if (onRowEdit) onRowEdit(row, col.field, val);
|
|
765
|
+
};
|
|
766
|
+
const extra = col.editProps || {};
|
|
767
|
+
const cellError = inlineErrors[cellKey];
|
|
768
|
+
const validationProps = cellError ? { error: true, validationMessage: cellError } : {};
|
|
769
|
+
const onInputValidate = validate ? (val) => {
|
|
770
|
+
const result = validate(val, row);
|
|
771
|
+
if (result !== true && result !== void 0 && result !== null) {
|
|
772
|
+
setInlineErrors((prev) => ({ ...prev, [cellKey]: typeof result === "string" ? result : "Invalid value" }));
|
|
773
|
+
} else {
|
|
774
|
+
setInlineErrors((prev) => {
|
|
775
|
+
const next = { ...prev };
|
|
776
|
+
delete next[cellKey];
|
|
777
|
+
return next;
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
} : void 0;
|
|
781
|
+
const emitInput = (val) => {
|
|
782
|
+
if (onInputValidate) onInputValidate(val);
|
|
783
|
+
if (onRowEditInput) onRowEditInput(row, col.field, val);
|
|
784
|
+
};
|
|
785
|
+
switch (type) {
|
|
786
|
+
case "textarea":
|
|
787
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TextArea, { ...extra, name: fieldName, label: "", value: value ?? "", onChange: fire, ...validationProps, onInput: emitInput });
|
|
788
|
+
case "number":
|
|
789
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.NumberInput, { ...extra, name: fieldName, label: "", value, onChange: fire, ...validationProps, onInput: emitInput });
|
|
790
|
+
case "currency":
|
|
791
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.CurrencyInput, { currencyCode: "USD", ...extra, name: fieldName, label: "", value, onChange: fire, ...validationProps, onInput: emitInput });
|
|
792
|
+
case "stepper":
|
|
793
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.StepperInput, { ...extra, name: fieldName, label: "", value, onChange: fire, ...validationProps, onInput: emitInput });
|
|
794
|
+
case "select":
|
|
795
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Select, { ...extra, name: fieldName, label: "", value, onChange: fire, options: resolveEditOptions(col, data) });
|
|
796
|
+
case "multiselect":
|
|
797
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.MultiSelect, { ...extra, name: fieldName, label: "", value: value || [], onChange: fire, options: resolveEditOptions(col, data) });
|
|
798
|
+
case "date":
|
|
799
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.DateInput, { ...extra, name: fieldName, label: "", value, onChange: fire });
|
|
800
|
+
case "time":
|
|
801
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TimeInput, { ...extra, name: fieldName, label: "", value, onChange: fire });
|
|
802
|
+
case "datetime":
|
|
803
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.DateInput, { ...extra, name: `${fieldName}-date`, label: "", value: value == null ? void 0 : value.date, onChange: (val) => {
|
|
804
|
+
fire({ ...value, date: val });
|
|
805
|
+
} }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label: "", value: value == null ? void 0 : value.time, onChange: (val) => {
|
|
806
|
+
fire({ ...value, time: val });
|
|
807
|
+
} }));
|
|
808
|
+
case "toggle":
|
|
809
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Toggle, { ...extra, name: fieldName, label: "", checked: !!value, onChange: fire });
|
|
810
|
+
case "checkbox":
|
|
811
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Checkbox, { ...extra, name: fieldName, checked: !!value, onChange: fire });
|
|
812
|
+
default:
|
|
813
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Input, { ...extra, name: fieldName, label: "", value: value ?? "", onChange: fire, ...validationProps, onInput: emitInput });
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
const renderCellContent = (row, col) => {
|
|
817
|
+
const rowId = row[rowIdField];
|
|
818
|
+
if (resolvedEditMode === "inline" && col.editable) {
|
|
819
|
+
return renderInlineControl(col, row);
|
|
820
|
+
}
|
|
821
|
+
if (editingRowId != null && rowId === editingRowId && col.editable) {
|
|
822
|
+
return renderInlineControl(col, row);
|
|
823
|
+
}
|
|
824
|
+
const isEditing = (editingCell == null ? void 0 : editingCell.rowId) === rowId && (editingCell == null ? void 0 : editingCell.field) === col.field;
|
|
825
|
+
if (isEditing && col.editable) return renderEditControl(col, row);
|
|
826
|
+
const rawValue = row[col.field];
|
|
827
|
+
const rawStr = String(rawValue ?? "");
|
|
828
|
+
if (col.truncate && rawStr.length > 0) {
|
|
829
|
+
if (col.truncate === true) {
|
|
830
|
+
const content2 = col.renderCell ? col.renderCell(rawValue, row) : rawStr;
|
|
831
|
+
if (col.editable) {
|
|
832
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { truncate: { tooltipText: rawStr } }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Link, { variant: "dark", onClick: () => startEditing(rowId, col.field, rawValue) }, content2 || "--"));
|
|
833
|
+
}
|
|
834
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { truncate: { tooltipText: rawStr } }, content2);
|
|
835
|
+
}
|
|
836
|
+
const maxLen = col.truncate.maxLength || 100;
|
|
837
|
+
if (rawStr.length > maxLen) {
|
|
838
|
+
const truncatedStr = rawStr.slice(0, maxLen) + "\u2026";
|
|
839
|
+
const truncatedContent = col.renderCell ? col.renderCell(truncatedStr, row) : truncatedStr;
|
|
840
|
+
if (col.editable) {
|
|
841
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Link, { variant: "dark", onClick: () => startEditing(rowId, col.field, rawValue) }, truncatedContent || "--");
|
|
842
|
+
}
|
|
843
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { truncate: { tooltipText: rawStr } }, truncatedContent || "--");
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
const content = col.renderCell ? col.renderCell(rawValue, row) : rawValue;
|
|
847
|
+
const isEmpty = content == null || content === "";
|
|
848
|
+
if (col.editable) {
|
|
849
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
850
|
+
import_ui_extensions.Link,
|
|
851
|
+
{
|
|
852
|
+
variant: "dark",
|
|
853
|
+
onClick: () => startEditing(rowId, col.field, rawValue)
|
|
854
|
+
},
|
|
855
|
+
isEmpty ? "--" : content
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
return isEmpty ? "--" : content;
|
|
859
|
+
};
|
|
860
|
+
const renderFilterControl = (filter) => {
|
|
861
|
+
const type = filter.type || "select";
|
|
862
|
+
if (type === "multiselect") {
|
|
863
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
864
|
+
import_ui_extensions.MultiSelect,
|
|
865
|
+
{
|
|
866
|
+
key: filter.name,
|
|
867
|
+
name: `filter-${filter.name}`,
|
|
868
|
+
label: "",
|
|
869
|
+
placeholder: filter.placeholder || "All",
|
|
870
|
+
value: filterValues[filter.name] || [],
|
|
871
|
+
onChange: (val) => handleFilterChange(filter.name, val),
|
|
872
|
+
options: filter.options
|
|
873
|
+
}
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
if (type === "dateRange") {
|
|
877
|
+
const rangeVal = filterValues[filter.name] || { from: null, to: null };
|
|
878
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { key: filter.name, direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(
|
|
879
|
+
import_ui_extensions.DateInput,
|
|
880
|
+
{
|
|
881
|
+
name: `filter-${filter.name}-from`,
|
|
882
|
+
label: "",
|
|
883
|
+
placeholder: "From",
|
|
884
|
+
format: "medium",
|
|
885
|
+
value: rangeVal.from,
|
|
886
|
+
onChange: (val) => handleFilterChange(filter.name, { ...rangeVal, from: val })
|
|
887
|
+
}
|
|
888
|
+
), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: "dataSync", size: "sm" }), /* @__PURE__ */ import_react.default.createElement(
|
|
889
|
+
import_ui_extensions.DateInput,
|
|
890
|
+
{
|
|
891
|
+
size: "sm",
|
|
892
|
+
name: `filter-${filter.name}-to`,
|
|
893
|
+
label: "",
|
|
894
|
+
placeholder: "To",
|
|
895
|
+
format: "medium",
|
|
896
|
+
value: rangeVal.to,
|
|
897
|
+
onChange: (val) => handleFilterChange(filter.name, { ...rangeVal, to: val })
|
|
898
|
+
}
|
|
899
|
+
));
|
|
900
|
+
}
|
|
901
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
902
|
+
import_ui_extensions.Select,
|
|
903
|
+
{
|
|
904
|
+
key: filter.name,
|
|
905
|
+
name: `filter-${filter.name}`,
|
|
906
|
+
variant: "transparent",
|
|
907
|
+
placeholder: filter.placeholder || "All",
|
|
908
|
+
value: filterValues[filter.name],
|
|
909
|
+
onChange: (val) => handleFilterChange(filter.name, val),
|
|
910
|
+
options: [
|
|
911
|
+
{ label: filter.placeholder || "All", value: "" },
|
|
912
|
+
...filter.options
|
|
913
|
+
]
|
|
914
|
+
}
|
|
915
|
+
);
|
|
916
|
+
};
|
|
917
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
918
|
+
import_ui_extensions.SearchInput,
|
|
919
|
+
{
|
|
920
|
+
name: "datatable-search",
|
|
921
|
+
placeholder: searchPlaceholder,
|
|
922
|
+
value: searchTerm,
|
|
923
|
+
onChange: handleSearchChange
|
|
924
|
+
}
|
|
925
|
+
), filters.slice(0, 2).map(renderFilterControl), filters.length > 2 && /* @__PURE__ */ import_react.default.createElement(
|
|
926
|
+
import_ui_extensions.Button,
|
|
927
|
+
{
|
|
928
|
+
variant: "transparent",
|
|
929
|
+
size: "small",
|
|
930
|
+
onClick: () => setShowMoreFilters((prev) => !prev)
|
|
931
|
+
},
|
|
932
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: "filter", size: "sm" }),
|
|
933
|
+
" Filters"
|
|
934
|
+
)), showMoreFilters && filters.length > 2 && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "end", gap: "sm", wrap: "wrap" }, filters.slice(2).map(renderFilterControl)), activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showFilterBadges && activeChips.map((chip) => /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Tag, { key: chip.key, variant: "default", onDelete: () => handleFilterRemove(chip.key) }, chip.label)), showClearFiltersButton && /* @__PURE__ */ import_react.default.createElement(
|
|
935
|
+
import_ui_extensions.Button,
|
|
936
|
+
{
|
|
937
|
+
variant: "transparent",
|
|
938
|
+
size: "extra-small",
|
|
939
|
+
onClick: () => handleFilterRemove("all")
|
|
940
|
+
},
|
|
941
|
+
"Clear all"
|
|
942
|
+
)))), showRowCount && displayCount > 0 && !(selectable && selectedIds.size > 0) && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), selectable && selectedIds.size > 0 && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "nowrap" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { inline: true, format: { fontWeight: "demibold" } }, selectedIds.size, "\xA0", countLabel(selectedIds.size), "\xA0selected"), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "transparent", size: "extra-small", onClick: handleSelectAllRows }, "Select all ", displayCount, " ", countLabel(displayCount)), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "transparent", size: "extra-small", onClick: handleDeselectAll }, "Deselect all"), selectionActions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
|
|
943
|
+
import_ui_extensions.Button,
|
|
944
|
+
{
|
|
945
|
+
key: i,
|
|
946
|
+
variant: action.variant || "transparent",
|
|
947
|
+
size: "extra-small",
|
|
948
|
+
onClick: () => action.onClick([...selectedIds])
|
|
949
|
+
},
|
|
950
|
+
action.icon && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: action.icon, size: "sm" }),
|
|
951
|
+
" ",
|
|
952
|
+
action.label
|
|
953
|
+
)))), showRowCount && displayCount > 0 && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "center" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), loading ? /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.LoadingSpinner, { label: resolvedLoadingLabel, layout: "centered" }) : error ? /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.ErrorState, { title: typeof error === "string" ? error : "Something went wrong." }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, null, typeof error === "string" ? "Please try again." : "An error occurred while loading data.")) : displayRows.length === 0 ? /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.EmptyState, { title: resolvedEmptyTitle, layout: "vertical" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, null, resolvedEmptyMessage))) : /* @__PURE__ */ import_react.default.createElement(
|
|
954
|
+
import_ui_extensions.Table,
|
|
955
|
+
{
|
|
956
|
+
bordered,
|
|
957
|
+
flush,
|
|
958
|
+
paginated: pageCount > 1,
|
|
959
|
+
page: activePage,
|
|
960
|
+
pageCount,
|
|
961
|
+
onPageChange: handlePageChange,
|
|
962
|
+
showFirstLastButtons: showFirstLastButtons != null ? showFirstLastButtons : pageCount > 5,
|
|
963
|
+
showButtonLabels,
|
|
964
|
+
...maxVisiblePageButtons != null ? { maxVisiblePageButtons } : {}
|
|
965
|
+
},
|
|
966
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHead, null, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableRow, null, selectable && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHeader, { width: "min" }, /* @__PURE__ */ import_react.default.createElement(
|
|
967
|
+
import_ui_extensions.Checkbox,
|
|
968
|
+
{
|
|
969
|
+
name: "datatable-select-all",
|
|
970
|
+
"aria-label": "Select all rows",
|
|
971
|
+
checked: allVisibleSelected,
|
|
972
|
+
onChange: handleSelectAll
|
|
973
|
+
}
|
|
974
|
+
)), columns.map((col) => {
|
|
975
|
+
const headerAlign = resolvedEditMode === "inline" && col.editable ? void 0 : col.align;
|
|
976
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
977
|
+
import_ui_extensions.TableHeader,
|
|
978
|
+
{
|
|
979
|
+
key: col.field,
|
|
980
|
+
width: getHeaderWidth(col),
|
|
981
|
+
align: headerAlign,
|
|
982
|
+
sortDirection: col.sortable ? sortState[col.field] || "none" : "never",
|
|
983
|
+
onSortChange: col.sortable ? () => handleSortChange(col.field) : void 0
|
|
984
|
+
},
|
|
985
|
+
col.label
|
|
986
|
+
);
|
|
987
|
+
}), showRowActionsColumn && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHeader, { width: "min" }))),
|
|
988
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableBody, null, displayRows.map(
|
|
989
|
+
(item, idx) => item.type === "group-header" ? /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableRow, { key: `group-${item.group.key}` }, selectable && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { width: "min" }), columns.map((col, colIdx) => {
|
|
990
|
+
var _a, _b, _c;
|
|
991
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { key: col.field, width: getCellWidth(col), align: colIdx === 0 ? void 0 : col.align }, colIdx === 0 ? /* @__PURE__ */ import_react.default.createElement(
|
|
992
|
+
import_ui_extensions.Link,
|
|
993
|
+
{
|
|
994
|
+
variant: "dark",
|
|
995
|
+
onClick: () => toggleGroup(item.group.key)
|
|
996
|
+
},
|
|
997
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: expandedGroups.has(item.group.key) ? "downCarat" : "right" }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, item.group.label))
|
|
998
|
+
) : ((_a = groupBy.aggregations) == null ? void 0 : _a[col.field]) ? groupBy.aggregations[col.field](item.group.rows, item.group.key) : ((_c = (_b = groupBy.groupValues) == null ? void 0 : _b[item.group.key]) == null ? void 0 : _c[col.field]) ?? "");
|
|
999
|
+
}), showRowActionsColumn && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { width: "min" })) : useColumnRendering ? /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableRow, { key: item.row[rowIdField] ?? idx }, selectable && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { width: "min" }, /* @__PURE__ */ import_react.default.createElement(
|
|
1000
|
+
import_ui_extensions.Checkbox,
|
|
1001
|
+
{
|
|
1002
|
+
name: `select-${item.row[rowIdField]}`,
|
|
1003
|
+
"aria-label": "Select row",
|
|
1004
|
+
checked: selectedIds.has(item.row[rowIdField]),
|
|
1005
|
+
onChange: (checked) => handleSelectRow(item.row[rowIdField], checked)
|
|
1006
|
+
}
|
|
1007
|
+
)), columns.map((col) => {
|
|
1008
|
+
const rowId = item.row[rowIdField];
|
|
1009
|
+
const isDiscreteEditing = resolvedEditMode === "discrete" && (editingCell == null ? void 0 : editingCell.rowId) === rowId && (editingCell == null ? void 0 : editingCell.field) === col.field;
|
|
1010
|
+
const isRowEditing = editingRowId != null && rowId === editingRowId && col.editable;
|
|
1011
|
+
const isShowingInput = isDiscreteEditing || isRowEditing || resolvedEditMode === "inline" && col.editable;
|
|
1012
|
+
const cellAlign = isShowingInput ? void 0 : col.align;
|
|
1013
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { key: col.field, width: isDiscreteEditing || isRowEditing ? "auto" : getCellWidth(col), align: cellAlign }, renderCellContent(item.row, col));
|
|
1014
|
+
}), showRowActionsColumn && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableCell, { width: "min" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, (() => {
|
|
1015
|
+
const resolvedRowActions = typeof rowActions === "function" ? rowActions(item.row) : rowActions;
|
|
1016
|
+
const actions = Array.isArray(resolvedRowActions) ? resolvedRowActions : [];
|
|
1017
|
+
return actions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
|
|
1018
|
+
import_ui_extensions.Button,
|
|
1019
|
+
{
|
|
1020
|
+
key: i,
|
|
1021
|
+
variant: action.variant || "transparent",
|
|
1022
|
+
size: "extra-small",
|
|
1023
|
+
onClick: () => action.onClick(item.row)
|
|
1024
|
+
},
|
|
1025
|
+
action.icon && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: action.icon, size: "sm" }),
|
|
1026
|
+
action.label && ` ${action.label}`
|
|
1027
|
+
));
|
|
1028
|
+
})()))) : renderRow(item.row)
|
|
1029
|
+
)),
|
|
1030
|
+
(footer || columns.some((col) => col.footer)) && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableFooter, null, typeof footer === "function" ? footer(footerData) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableRow, null, selectable && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHeader, { width: "min" }), columns.map((col) => {
|
|
1031
|
+
const footerDef = col.footer;
|
|
1032
|
+
const content = typeof footerDef === "function" ? footerDef(footerData) : footerDef || "";
|
|
1033
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHeader, { key: col.field, align: col.align }, content);
|
|
1034
|
+
}), showRowActionsColumn && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TableHeader, { width: "min" })))
|
|
1035
|
+
));
|
|
1036
|
+
};
|
|
1037
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1038
|
+
0 && (module.exports = {
|
|
1039
|
+
DataTable
|
|
1040
|
+
});
|