hs-uix 1.6.5 → 2.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 +2 -0
- package/common-components.d.ts +152 -0
- package/dist/common-components.js +1385 -77
- package/dist/common-components.mjs +1438 -82
- package/dist/datatable.js +291 -239
- package/dist/datatable.mjs +207 -155
- package/dist/feed.js +939 -0
- package/dist/feed.mjs +927 -0
- package/dist/form.js +115 -93
- package/dist/form.mjs +115 -93
- package/dist/index.js +3529 -1060
- package/dist/index.mjs +3231 -770
- package/dist/kanban.js +286 -225
- package/dist/kanban.mjs +180 -119
- package/dist/utils.js +2906 -2
- package/dist/utils.mjs +2944 -1
- package/feed.d.ts +1 -0
- package/index.d.ts +51 -2
- package/package.json +17 -4
- package/packages/datatable/README.md +1046 -0
- package/packages/datatable/index.d.ts +246 -0
- package/packages/feed/README.md +224 -0
- package/packages/feed/index.d.ts +261 -0
- package/packages/form/README.md +1229 -0
- package/packages/form/index.d.ts +498 -0
- package/packages/kanban/README.md +707 -0
- package/packages/kanban/index.d.ts +367 -0
- package/utils.d.ts +122 -0
package/dist/datatable.mjs
CHANGED
|
@@ -1,6 +1,135 @@
|
|
|
1
1
|
// packages/datatable/src/DataTable.jsx
|
|
2
|
-
import React, { useState, useMemo, useEffect, useCallback, useRef } from "react";
|
|
2
|
+
import React, { useState, useMemo, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
3
|
+
|
|
4
|
+
// src/utils/query.js
|
|
3
5
|
import Fuse from "fuse.js";
|
|
6
|
+
var getEmptyFilterValue = (filter) => {
|
|
7
|
+
const type = filter.type || "select";
|
|
8
|
+
if (type === "multiselect") return [];
|
|
9
|
+
if (type === "dateRange") return { from: null, to: null };
|
|
10
|
+
return "";
|
|
11
|
+
};
|
|
12
|
+
var isFilterActive = (filter, value) => {
|
|
13
|
+
const type = filter.type || "select";
|
|
14
|
+
if (type === "multiselect") return Array.isArray(value) && value.length > 0;
|
|
15
|
+
if (type === "dateRange") return value && (value.from || value.to);
|
|
16
|
+
return !!value;
|
|
17
|
+
};
|
|
18
|
+
var formatDateChip = (dateObj) => {
|
|
19
|
+
if (!dateObj) return "";
|
|
20
|
+
const { year, month, date } = dateObj;
|
|
21
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
22
|
+
month: "short",
|
|
23
|
+
day: "numeric",
|
|
24
|
+
year: "numeric"
|
|
25
|
+
}).format(new Date(year, month, date));
|
|
26
|
+
};
|
|
27
|
+
var dateToTimestamp = (dateObj) => {
|
|
28
|
+
if (!dateObj) return null;
|
|
29
|
+
return new Date(dateObj.year, dateObj.month, dateObj.date).getTime();
|
|
30
|
+
};
|
|
31
|
+
var toStableKey = (value) => {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.stringify(value);
|
|
34
|
+
} catch (_error) {
|
|
35
|
+
return String(value);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var filterRows = (rows, filters, values) => {
|
|
39
|
+
let result = rows;
|
|
40
|
+
for (const filter of filters || []) {
|
|
41
|
+
const value = values[filter.name];
|
|
42
|
+
if (!isFilterActive(filter, value)) continue;
|
|
43
|
+
const type = filter.type || "select";
|
|
44
|
+
if (filter.filterFn) {
|
|
45
|
+
result = result.filter((row) => filter.filterFn(row, value));
|
|
46
|
+
} else if (type === "multiselect") {
|
|
47
|
+
result = result.filter((row) => value.includes(row[filter.name]));
|
|
48
|
+
} else if (type === "dateRange") {
|
|
49
|
+
const fromTs = dateToTimestamp(value.from);
|
|
50
|
+
const toTs = value.to ? dateToTimestamp(value.to) + 864e5 - 1 : null;
|
|
51
|
+
result = result.filter((row) => {
|
|
52
|
+
const rowTs = new Date(row[filter.name]).getTime();
|
|
53
|
+
if (Number.isNaN(rowTs)) return false;
|
|
54
|
+
if (fromTs && rowTs < fromTs) return false;
|
|
55
|
+
if (toTs && rowTs > toTs) return false;
|
|
56
|
+
return true;
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
result = result.filter((row) => row[filter.name] === value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
var searchRows = (rows, term, fields, opts = {}) => {
|
|
65
|
+
const { fuzzy = false, fuzzyOptions } = opts;
|
|
66
|
+
const t = String(term ?? "").toLowerCase();
|
|
67
|
+
if (!t || !fields || fields.length === 0) return rows;
|
|
68
|
+
if (fuzzy) {
|
|
69
|
+
const fuse = new Fuse(rows, {
|
|
70
|
+
keys: fields,
|
|
71
|
+
threshold: 0.4,
|
|
72
|
+
distance: 100,
|
|
73
|
+
ignoreLocation: true,
|
|
74
|
+
...fuzzyOptions
|
|
75
|
+
});
|
|
76
|
+
return fuse.search(t).map((r) => r.item);
|
|
77
|
+
}
|
|
78
|
+
return rows.filter(
|
|
79
|
+
(row) => fields.some((field) => {
|
|
80
|
+
const val = row[field];
|
|
81
|
+
return val && String(val).toLowerCase().includes(t);
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// src/utils/interactionHooks.js
|
|
87
|
+
import { useRef, useEffect, useCallback } from "react";
|
|
88
|
+
import { useDebounce } from "@hubspot/ui-extensions";
|
|
89
|
+
var useDebouncedDispatch = (value, debounceMs, dispatch) => {
|
|
90
|
+
const debounced = useDebounce(value, debounceMs > 0 ? debounceMs : 300);
|
|
91
|
+
const pendingRef = useRef(null);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (debounceMs <= 0) return;
|
|
94
|
+
if (pendingRef.current == null) return;
|
|
95
|
+
if (debounced !== pendingRef.current) return;
|
|
96
|
+
const next = pendingRef.current;
|
|
97
|
+
pendingRef.current = null;
|
|
98
|
+
dispatch(next);
|
|
99
|
+
}, [debounceMs, debounced, dispatch]);
|
|
100
|
+
return useCallback(
|
|
101
|
+
(next) => {
|
|
102
|
+
if (debounceMs > 0) {
|
|
103
|
+
pendingRef.current = next;
|
|
104
|
+
} else {
|
|
105
|
+
pendingRef.current = null;
|
|
106
|
+
dispatch(next);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
[debounceMs, dispatch]
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
var useSelectionReset = ({ resetKey, enabled, isControlled, clearSelection }) => {
|
|
113
|
+
const ref = useRef("");
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (!enabled || isControlled) {
|
|
116
|
+
ref.current = resetKey;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (ref.current && ref.current !== resetKey) {
|
|
120
|
+
clearSelection();
|
|
121
|
+
}
|
|
122
|
+
ref.current = resetKey;
|
|
123
|
+
}, [resetKey, enabled, isControlled, clearSelection]);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// packages/datatable/src/editValidation.js
|
|
127
|
+
var editValidationError = (result) => {
|
|
128
|
+
if (result === true || result === void 0 || result === null) return null;
|
|
129
|
+
return typeof result === "string" ? result : "Invalid value";
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// packages/datatable/src/DataTable.jsx
|
|
4
133
|
import {
|
|
5
134
|
Box,
|
|
6
135
|
Button,
|
|
@@ -13,7 +142,6 @@ import {
|
|
|
13
142
|
Icon,
|
|
14
143
|
Input,
|
|
15
144
|
Link,
|
|
16
|
-
LoadingSpinner,
|
|
17
145
|
MultiSelect,
|
|
18
146
|
NumberInput,
|
|
19
147
|
SearchInput,
|
|
@@ -27,25 +155,13 @@ import {
|
|
|
27
155
|
TableHeader,
|
|
28
156
|
TableRow,
|
|
29
157
|
Tag,
|
|
158
|
+
Tile,
|
|
30
159
|
Text,
|
|
31
160
|
TextArea,
|
|
32
161
|
TimeInput,
|
|
33
162
|
Toggle,
|
|
34
163
|
Tooltip
|
|
35
164
|
} from "@hubspot/ui-extensions";
|
|
36
|
-
var formatDateChip = (dateObj) => {
|
|
37
|
-
if (!dateObj) return "";
|
|
38
|
-
const { year, month, date } = dateObj;
|
|
39
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
40
|
-
month: "short",
|
|
41
|
-
day: "numeric",
|
|
42
|
-
year: "numeric"
|
|
43
|
-
}).format(new Date(year, month, date));
|
|
44
|
-
};
|
|
45
|
-
var dateToTimestamp = (dateObj) => {
|
|
46
|
-
if (!dateObj) return null;
|
|
47
|
-
return new Date(dateObj.year, dateObj.month, dateObj.date).getTime();
|
|
48
|
-
};
|
|
49
165
|
var NARROW_EDIT_TYPES = /* @__PURE__ */ new Set(["checkbox", "toggle"]);
|
|
50
166
|
var DATE_PATTERN = /^\d{4}[-/]\d{2}[-/]\d{2}/;
|
|
51
167
|
var BOOL_VALUES = /* @__PURE__ */ new Set(["true", "false", "yes", "no", "0", "1"]);
|
|
@@ -71,13 +187,6 @@ var serializeSortState = (sortState) => {
|
|
|
71
187
|
if (!activeField) return null;
|
|
72
188
|
return { field: activeField, direction: sortState[activeField] };
|
|
73
189
|
};
|
|
74
|
-
var toStableKey = (value) => {
|
|
75
|
-
try {
|
|
76
|
-
return JSON.stringify(value);
|
|
77
|
-
} catch (_error) {
|
|
78
|
-
return String(value);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
190
|
var computeAutoWidths = (columns, data) => {
|
|
82
191
|
if (!data || data.length === 0) return {};
|
|
83
192
|
const sample = data.slice(0, 50);
|
|
@@ -129,12 +238,6 @@ var computeAutoWidths = (columns, data) => {
|
|
|
129
238
|
});
|
|
130
239
|
return results;
|
|
131
240
|
};
|
|
132
|
-
var getEmptyFilterValue = (filter) => {
|
|
133
|
-
const type = filter.type || "select";
|
|
134
|
-
if (type === "multiselect") return [];
|
|
135
|
-
if (type === "dateRange") return { from: null, to: null };
|
|
136
|
-
return "";
|
|
137
|
-
};
|
|
138
241
|
var BOOLEAN_SELECT_OPTIONS = [
|
|
139
242
|
{ label: "Yes", value: true },
|
|
140
243
|
{ label: "No", value: false }
|
|
@@ -145,12 +248,6 @@ var resolveEditOptions = (col, data) => {
|
|
|
145
248
|
if (sample && typeof sample[col.field] === "boolean") return BOOLEAN_SELECT_OPTIONS;
|
|
146
249
|
return [];
|
|
147
250
|
};
|
|
148
|
-
var isFilterActive = (filter, value) => {
|
|
149
|
-
const type = filter.type || "select";
|
|
150
|
-
if (type === "multiselect") return Array.isArray(value) && value.length > 0;
|
|
151
|
-
if (type === "dateRange") return value && (value.from || value.to);
|
|
152
|
-
return !!value;
|
|
153
|
-
};
|
|
154
251
|
var DataTable = ({
|
|
155
252
|
// Data
|
|
156
253
|
data,
|
|
@@ -169,8 +266,8 @@ var DataTable = ({
|
|
|
169
266
|
filters = [],
|
|
170
267
|
showFilterBadges = true,
|
|
171
268
|
// show active filter chips/badges
|
|
172
|
-
showClearFiltersButton
|
|
173
|
-
// show "Clear all"
|
|
269
|
+
showClearFiltersButton,
|
|
270
|
+
// show "Clear all" reset button; defaults to showFilterBadges when omitted
|
|
174
271
|
filterInlineLimit = 2,
|
|
175
272
|
// number of filters shown inline before overflow
|
|
176
273
|
// Pagination
|
|
@@ -320,11 +417,11 @@ var DataTable = ({
|
|
|
320
417
|
const [internalSortState, setInternalSortState] = useState(initialSortState);
|
|
321
418
|
const [currentPage, setCurrentPage] = useState(1);
|
|
322
419
|
const [showMoreFilters, setShowMoreFilters] = useState(false);
|
|
323
|
-
const lastAppliedSearchRef =
|
|
420
|
+
const lastAppliedSearchRef = useRef2(
|
|
324
421
|
serverSide && searchValue != null ? searchValue : ""
|
|
325
422
|
);
|
|
326
423
|
const searchTerm = serverSide && searchValue != null ? searchValue : internalSearchTerm;
|
|
327
|
-
|
|
424
|
+
useEffect2(() => {
|
|
328
425
|
if (!serverSide || searchValue == null) return;
|
|
329
426
|
if (searchValue === lastAppliedSearchRef.current) return;
|
|
330
427
|
lastAppliedSearchRef.current = searchValue;
|
|
@@ -337,14 +434,13 @@ var DataTable = ({
|
|
|
337
434
|
);
|
|
338
435
|
const sortState = serverSide && externalSort != null ? externalSortState : internalSortState;
|
|
339
436
|
const activePage = serverSide && externalPage != null ? externalPage : currentPage;
|
|
340
|
-
|
|
437
|
+
useEffect2(() => {
|
|
341
438
|
if (!serverSide) setCurrentPage(1);
|
|
342
439
|
}, [internalSearchTerm, internalFilterValues, internalSortState, serverSide]);
|
|
343
|
-
const
|
|
344
|
-
const fireSearchCallback = useCallback((term) => {
|
|
440
|
+
const fireSearchCallback = useCallback2((term) => {
|
|
345
441
|
if (serverSide && onSearchChange) onSearchChange(term);
|
|
346
442
|
}, [serverSide, onSearchChange]);
|
|
347
|
-
const fireParamsChange =
|
|
443
|
+
const fireParamsChange = useCallback2((overrides) => {
|
|
348
444
|
if (!onParamsChange) return;
|
|
349
445
|
const nextSortState = overrides.sort != null ? normalizeSortState(columns, overrides.sort) : sortState;
|
|
350
446
|
onParamsChange({
|
|
@@ -354,38 +450,35 @@ var DataTable = ({
|
|
|
354
450
|
page: overrides.page != null ? overrides.page : activePage
|
|
355
451
|
});
|
|
356
452
|
}, [onParamsChange, columns, searchTerm, filterValues, sortState, activePage]);
|
|
357
|
-
const resetPage =
|
|
453
|
+
const resetPage = useCallback2(() => {
|
|
358
454
|
if (resetPageOnChange) {
|
|
359
455
|
setCurrentPage(1);
|
|
360
456
|
if (serverSide && onPageChange) onPageChange(1);
|
|
361
457
|
}
|
|
362
458
|
}, [resetPageOnChange, serverSide, onPageChange]);
|
|
363
|
-
const
|
|
459
|
+
const dispatchSearchChange = useCallback2((term) => {
|
|
460
|
+
lastAppliedSearchRef.current = term;
|
|
461
|
+
fireSearchCallback(term);
|
|
462
|
+
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
463
|
+
}, [fireSearchCallback, fireParamsChange, resetPageOnChange]);
|
|
464
|
+
const dispatchSearchDebounced = useDebouncedDispatch(
|
|
465
|
+
internalSearchTerm,
|
|
466
|
+
searchDebounce,
|
|
467
|
+
dispatchSearchChange
|
|
468
|
+
);
|
|
469
|
+
const handleSearchChange = useCallback2((term) => {
|
|
364
470
|
setInternalSearchTerm(term);
|
|
365
471
|
resetPage();
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
370
|
-
};
|
|
371
|
-
if (searchDebounce > 0) {
|
|
372
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
373
|
-
debounceRef.current = setTimeout(dispatch, searchDebounce);
|
|
374
|
-
} else {
|
|
375
|
-
dispatch();
|
|
376
|
-
}
|
|
377
|
-
}, [searchDebounce, fireSearchCallback, fireParamsChange, resetPage, resetPageOnChange]);
|
|
378
|
-
useEffect(() => () => {
|
|
379
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
380
|
-
}, []);
|
|
381
|
-
const handleFilterChange = useCallback((name, value) => {
|
|
472
|
+
dispatchSearchDebounced(term);
|
|
473
|
+
}, [dispatchSearchDebounced, resetPage]);
|
|
474
|
+
const handleFilterChange = useCallback2((name, value) => {
|
|
382
475
|
const next = { ...filterValues, [name]: value };
|
|
383
476
|
setInternalFilterValues(next);
|
|
384
477
|
if (serverSide && onFilterChange) onFilterChange(next);
|
|
385
478
|
resetPage();
|
|
386
479
|
fireParamsChange({ filters: next, page: resetPageOnChange ? 1 : void 0 });
|
|
387
480
|
}, [filterValues, serverSide, onFilterChange, fireParamsChange, resetPage, resetPageOnChange]);
|
|
388
|
-
const handleSortChange =
|
|
481
|
+
const handleSortChange = useCallback2((field) => {
|
|
389
482
|
const current = sortState[field] || "none";
|
|
390
483
|
const nextDirection = current === "none" ? "ascending" : current === "ascending" ? "descending" : "none";
|
|
391
484
|
const reset = {};
|
|
@@ -398,55 +491,19 @@ var DataTable = ({
|
|
|
398
491
|
resetPage();
|
|
399
492
|
fireParamsChange({ sort: next, page: resetPageOnChange ? 1 : void 0 });
|
|
400
493
|
}, [sortState, columns, serverSide, onSortChange, fireParamsChange, resetPage, resetPageOnChange]);
|
|
401
|
-
const handlePageChange =
|
|
494
|
+
const handlePageChange = useCallback2((page) => {
|
|
402
495
|
setCurrentPage(page);
|
|
403
496
|
if (serverSide && onPageChange) onPageChange(page);
|
|
404
497
|
fireParamsChange({ page });
|
|
405
498
|
}, [serverSide, onPageChange, fireParamsChange]);
|
|
406
499
|
const filteredData = useMemo(() => {
|
|
407
500
|
if (serverSide) return data;
|
|
408
|
-
let result = data;
|
|
409
|
-
filters.forEach((filter) => {
|
|
410
|
-
const value = filterValues[filter.name];
|
|
411
|
-
if (!isFilterActive(filter, value)) return;
|
|
412
|
-
const type = filter.type || "select";
|
|
413
|
-
if (filter.filterFn) {
|
|
414
|
-
result = result.filter((row) => filter.filterFn(row, value));
|
|
415
|
-
} else if (type === "multiselect") {
|
|
416
|
-
result = result.filter((row) => value.includes(row[filter.name]));
|
|
417
|
-
} else if (type === "dateRange") {
|
|
418
|
-
const fromTs = dateToTimestamp(value.from);
|
|
419
|
-
const toTs = value.to ? dateToTimestamp(value.to) + 864e5 - 1 : null;
|
|
420
|
-
result = result.filter((row) => {
|
|
421
|
-
const rowTs = new Date(row[filter.name]).getTime();
|
|
422
|
-
if (Number.isNaN(rowTs)) return false;
|
|
423
|
-
if (fromTs && rowTs < fromTs) return false;
|
|
424
|
-
if (toTs && rowTs > toTs) return false;
|
|
425
|
-
return true;
|
|
426
|
-
});
|
|
427
|
-
} else {
|
|
428
|
-
result = result.filter((row) => row[filter.name] === value);
|
|
429
|
-
}
|
|
430
|
-
});
|
|
501
|
+
let result = filterRows(data, filters, filterValues);
|
|
431
502
|
if (searchTerm && searchFields.length > 0) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
distance: 100,
|
|
437
|
-
ignoreLocation: true,
|
|
438
|
-
...fuzzyOptions
|
|
439
|
-
});
|
|
440
|
-
result = fuse.search(searchTerm).map((r) => r.item);
|
|
441
|
-
} else {
|
|
442
|
-
const term = searchTerm.toLowerCase();
|
|
443
|
-
result = result.filter(
|
|
444
|
-
(row) => searchFields.some((field) => {
|
|
445
|
-
const val = row[field];
|
|
446
|
-
return val && String(val).toLowerCase().includes(term);
|
|
447
|
-
})
|
|
448
|
-
);
|
|
449
|
-
}
|
|
503
|
+
result = searchRows(result, searchTerm, searchFields, {
|
|
504
|
+
fuzzy: fuzzySearch,
|
|
505
|
+
fuzzyOptions
|
|
506
|
+
});
|
|
450
507
|
}
|
|
451
508
|
return result;
|
|
452
509
|
}, [data, filterValues, searchTerm, filters, searchFields, serverSide, fuzzySearch, fuzzyOptions]);
|
|
@@ -511,7 +568,7 @@ var DataTable = ({
|
|
|
511
568
|
}
|
|
512
569
|
return /* @__PURE__ */ new Set();
|
|
513
570
|
});
|
|
514
|
-
|
|
571
|
+
useEffect2(() => {
|
|
515
572
|
if (!groupedData) return;
|
|
516
573
|
const defaultExpanded = (groupBy == null ? void 0 : groupBy.defaultExpanded) !== false;
|
|
517
574
|
if (defaultExpanded) {
|
|
@@ -522,7 +579,7 @@ var DataTable = ({
|
|
|
522
579
|
});
|
|
523
580
|
}
|
|
524
581
|
}, [groupedData, groupBy]);
|
|
525
|
-
const toggleGroup =
|
|
582
|
+
const toggleGroup = useCallback2((key) => {
|
|
526
583
|
setExpandedGroups((prev) => {
|
|
527
584
|
const next = new Set(prev);
|
|
528
585
|
if (next.has(key)) next.delete(key);
|
|
@@ -583,7 +640,7 @@ var DataTable = ({
|
|
|
583
640
|
});
|
|
584
641
|
return chips;
|
|
585
642
|
}, [filterValues, filters]);
|
|
586
|
-
const handleFilterRemove =
|
|
643
|
+
const handleFilterRemove = useCallback2((key) => {
|
|
587
644
|
if (key === "all") {
|
|
588
645
|
const cleared = {};
|
|
589
646
|
filters.forEach((f) => {
|
|
@@ -619,13 +676,14 @@ var DataTable = ({
|
|
|
619
676
|
const resolvedDateFromLabel = (labels == null ? void 0 : labels.dateFrom) || "From";
|
|
620
677
|
const resolvedDateToLabel = (labels == null ? void 0 : labels.dateTo) || "To";
|
|
621
678
|
const resolvedLoadingLabel = (labels == null ? void 0 : labels.loading) || `Loading ${pluralLabel}...`;
|
|
679
|
+
const resolvedLoadingMessage = (labels == null ? void 0 : labels.loadingMessage) || "This should only take a moment.";
|
|
622
680
|
const resolvedErrorTitle = (labels == null ? void 0 : labels.errorTitle) || "Something went wrong.";
|
|
623
681
|
const resolvedErrorMessage = (labels == null ? void 0 : labels.errorMessage) || "An error occurred while loading data.";
|
|
624
682
|
const resolvedRetryMessage = (labels == null ? void 0 : labels.retryMessage) || "Please try again.";
|
|
683
|
+
const resolvedShowClearFiltersButton = showClearFiltersButton ?? showFilterBadges;
|
|
625
684
|
const recordCountLabel = rowCountText ? rowCountText(shownOnPageCount, displayCount) : displayCount === totalDataCount ? `${totalDataCount} ${countLabel(totalDataCount)}` : `${displayCount} of ${totalDataCount} ${countLabel(totalDataCount)}`;
|
|
626
685
|
const [internalSelectedIds, setInternalSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
627
|
-
|
|
628
|
-
useEffect(() => {
|
|
686
|
+
useEffect2(() => {
|
|
629
687
|
if (externalSelectedIds != null) {
|
|
630
688
|
setInternalSelectedIds(new Set(externalSelectedIds));
|
|
631
689
|
}
|
|
@@ -642,21 +700,21 @@ var DataTable = ({
|
|
|
642
700
|
() => `${selectionQueryKey}::${selectionResetKey == null ? "" : toStableKey(selectionResetKey)}`,
|
|
643
701
|
[selectionQueryKey, selectionResetKey]
|
|
644
702
|
);
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
selectionResetRef.current = combinedSelectionResetKey;
|
|
654
|
-
}, [combinedSelectionResetKey, selectable, externalSelectedIds]);
|
|
703
|
+
const clearSelection = useCallback2(() => setInternalSelectedIds(/* @__PURE__ */ new Set()), []);
|
|
704
|
+
useSelectionReset({
|
|
705
|
+
resetKey: combinedSelectionResetKey,
|
|
706
|
+
enabled: selectable,
|
|
707
|
+
isControlled: externalSelectedIds != null,
|
|
708
|
+
clearSelection
|
|
709
|
+
});
|
|
655
710
|
const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
|
|
656
711
|
const showToolbarCount = showRowCount && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
|
|
657
|
-
const
|
|
712
|
+
const hasToolbarLeft = showSearch && searchFields.length > 0 || filters.length > 0 || activeChips.length > 0 && (showFilterBadges || resolvedShowClearFiltersButton);
|
|
713
|
+
const countInTitleRow = !!title && showToolbarCount && !hasToolbarLeft;
|
|
714
|
+
const countInToolbar = showToolbarCount && !countInTitleRow;
|
|
715
|
+
const hasToolbarContent = hasToolbarLeft || countInToolbar;
|
|
658
716
|
const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
|
|
659
|
-
const applySelection =
|
|
717
|
+
const applySelection = useCallback2((nextSet) => {
|
|
660
718
|
if (externalSelectedIds == null) {
|
|
661
719
|
setInternalSelectedIds(nextSet);
|
|
662
720
|
}
|
|
@@ -672,13 +730,13 @@ var DataTable = ({
|
|
|
672
730
|
() => datasetRows.map((row) => row[rowIdField]).filter((id) => id != null),
|
|
673
731
|
[datasetRows, rowIdField]
|
|
674
732
|
);
|
|
675
|
-
const handleSelectRow =
|
|
733
|
+
const handleSelectRow = useCallback2((rowId, checked) => {
|
|
676
734
|
const next = new Set(selectedIds);
|
|
677
735
|
if (checked) next.add(rowId);
|
|
678
736
|
else next.delete(rowId);
|
|
679
737
|
applySelection(next);
|
|
680
738
|
}, [selectedIds, applySelection]);
|
|
681
|
-
const handleSelectAll =
|
|
739
|
+
const handleSelectAll = useCallback2((checked) => {
|
|
682
740
|
const next = new Set(selectedIds);
|
|
683
741
|
pageRowIds.forEach((id) => {
|
|
684
742
|
if (checked) next.add(id);
|
|
@@ -689,7 +747,7 @@ var DataTable = ({
|
|
|
689
747
|
const allVisibleSelected = useMemo(() => {
|
|
690
748
|
return pageRowIds.length > 0 && pageRowIds.every((id) => selectedIds.has(id));
|
|
691
749
|
}, [pageRowIds, selectedIds]);
|
|
692
|
-
const handleSelectAllRows =
|
|
750
|
+
const handleSelectAllRows = useCallback2(() => {
|
|
693
751
|
const idsToAdd = serverSide ? pageRowIds : allRowIds;
|
|
694
752
|
const next = new Set(selectedIds);
|
|
695
753
|
idsToAdd.forEach((id) => next.add(id));
|
|
@@ -702,13 +760,13 @@ var DataTable = ({
|
|
|
702
760
|
});
|
|
703
761
|
}
|
|
704
762
|
}, [serverSide, pageRowIds, allRowIds, selectedIds, applySelection, onSelectAllRequest, totalCount, data.length]);
|
|
705
|
-
const handleDeselectAll =
|
|
763
|
+
const handleDeselectAll = useCallback2(() => {
|
|
706
764
|
applySelection(/* @__PURE__ */ new Set());
|
|
707
765
|
}, [applySelection]);
|
|
708
766
|
const [editingCell, setEditingCell] = useState(null);
|
|
709
767
|
const [editValue, setEditValue] = useState(null);
|
|
710
768
|
const [editError, setEditError] = useState(null);
|
|
711
|
-
const startEditing =
|
|
769
|
+
const startEditing = useCallback2((rowId, field, currentValue) => {
|
|
712
770
|
setEditingCell({ rowId, field });
|
|
713
771
|
setEditValue(currentValue);
|
|
714
772
|
setEditError(null);
|
|
@@ -717,13 +775,13 @@ var DataTable = ({
|
|
|
717
775
|
if (row) onEditStart(row, field, currentValue);
|
|
718
776
|
}
|
|
719
777
|
}, [onEditStart, data, rowIdField]);
|
|
720
|
-
const commitEdit =
|
|
778
|
+
const commitEdit = useCallback2((row, field, value, options = {}) => {
|
|
721
779
|
const { keepEditing = false } = options;
|
|
722
780
|
const col = columns.find((c) => c.field === field);
|
|
723
781
|
if (col == null ? void 0 : col.editValidate) {
|
|
724
|
-
const
|
|
725
|
-
if (
|
|
726
|
-
setEditError(
|
|
782
|
+
const err = editValidationError(col.editValidate(value, row));
|
|
783
|
+
if (err) {
|
|
784
|
+
setEditError(err);
|
|
727
785
|
return false;
|
|
728
786
|
}
|
|
729
787
|
}
|
|
@@ -751,14 +809,7 @@ var DataTable = ({
|
|
|
751
809
|
const extra = col.editProps || {};
|
|
752
810
|
const validate = col.editValidate;
|
|
753
811
|
const validationProps = validate && editError ? { error: true, validationMessage: editError } : {};
|
|
754
|
-
const onInputValidate = validate ? (val) =>
|
|
755
|
-
const result = validate(val, row);
|
|
756
|
-
if (result !== true && result !== void 0 && result !== null) {
|
|
757
|
-
setEditError(typeof result === "string" ? result : "Invalid value");
|
|
758
|
-
} else {
|
|
759
|
-
setEditError(null);
|
|
760
|
-
}
|
|
761
|
-
} : void 0;
|
|
812
|
+
const onInputValidate = validate ? (val) => setEditError(editValidationError(validate(val, row))) : void 0;
|
|
762
813
|
const handleInput = (val) => {
|
|
763
814
|
setEditValue(val);
|
|
764
815
|
if (onInputValidate) onInputValidate(val);
|
|
@@ -834,9 +885,9 @@ var DataTable = ({
|
|
|
834
885
|
const validate = col.editValidate;
|
|
835
886
|
const fire = (val) => {
|
|
836
887
|
if (validate) {
|
|
837
|
-
const
|
|
838
|
-
if (
|
|
839
|
-
setInlineErrors((prev) => ({ ...prev, [cellKey]:
|
|
888
|
+
const err = editValidationError(validate(val, row));
|
|
889
|
+
if (err) {
|
|
890
|
+
setInlineErrors((prev) => ({ ...prev, [cellKey]: err }));
|
|
840
891
|
return;
|
|
841
892
|
}
|
|
842
893
|
setInlineErrors((prev) => {
|
|
@@ -851,16 +902,13 @@ var DataTable = ({
|
|
|
851
902
|
const cellError = inlineErrors[cellKey];
|
|
852
903
|
const validationProps = cellError ? { error: true, validationMessage: cellError } : {};
|
|
853
904
|
const onInputValidate = validate ? (val) => {
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
return next;
|
|
862
|
-
});
|
|
863
|
-
}
|
|
905
|
+
const err = editValidationError(validate(val, row));
|
|
906
|
+
setInlineErrors((prev) => {
|
|
907
|
+
if (err) return { ...prev, [cellKey]: err };
|
|
908
|
+
const next = { ...prev };
|
|
909
|
+
delete next[cellKey];
|
|
910
|
+
return next;
|
|
911
|
+
});
|
|
864
912
|
} : void 0;
|
|
865
913
|
const emitInput = (val) => {
|
|
866
914
|
if (onInputValidate) onInputValidate(val);
|
|
@@ -1004,7 +1052,7 @@ var DataTable = ({
|
|
|
1004
1052
|
}
|
|
1005
1053
|
);
|
|
1006
1054
|
};
|
|
1007
|
-
return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ React.createElement(Text, { format: { fontWeight: "demibold" } }, title)), hasToolbarContent && /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
|
|
1055
|
+
return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ React.createElement(Text, { format: { fontWeight: "demibold" } }, title), countInTitleRow && /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)), hasToolbarContent && /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
|
|
1008
1056
|
SearchInput,
|
|
1009
1057
|
{
|
|
1010
1058
|
name: "datatable-search",
|
|
@@ -1022,7 +1070,7 @@ var DataTable = ({
|
|
|
1022
1070
|
/* @__PURE__ */ React.createElement(Icon, { name: "filter", size: "sm" }),
|
|
1023
1071
|
" ",
|
|
1024
1072
|
resolvedFiltersButtonLabel
|
|
1025
|
-
)), showMoreFilters && filters.length > filterInlineLimit && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, filters.slice(filterInlineLimit).map(renderFilterControl)), activeChips.length > 0 && (showFilterBadges ||
|
|
1073
|
+
)), showMoreFilters && filters.length > filterInlineLimit && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, filters.slice(filterInlineLimit).map(renderFilterControl)), activeChips.length > 0 && (showFilterBadges || resolvedShowClearFiltersButton) && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showFilterBadges && activeChips.map((chip) => /* @__PURE__ */ React.createElement(Tag, { key: chip.key, variant: "default", onDelete: () => handleFilterRemove(chip.key) }, chip.label)), resolvedShowClearFiltersButton && /* @__PURE__ */ React.createElement(
|
|
1026
1074
|
Button,
|
|
1027
1075
|
{
|
|
1028
1076
|
variant: "transparent",
|
|
@@ -1030,7 +1078,7 @@ var DataTable = ({
|
|
|
1030
1078
|
onClick: () => handleFilterRemove("all")
|
|
1031
1079
|
},
|
|
1032
1080
|
resolvedClearAllLabel
|
|
1033
|
-
)))),
|
|
1081
|
+
)))), countInToolbar && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
|
|
1034
1082
|
selectedIds,
|
|
1035
1083
|
selectedCount: selectedIds.size,
|
|
1036
1084
|
displayCount,
|
|
@@ -1050,11 +1098,15 @@ var DataTable = ({
|
|
|
1050
1098
|
action.icon && /* @__PURE__ */ React.createElement(Icon, { name: action.icon, size: "sm" }),
|
|
1051
1099
|
" ",
|
|
1052
1100
|
action.label
|
|
1053
|
-
)))), showRowCount && displayCount > 0 && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "center" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel))))), loading ? renderLoadingState ? renderLoadingState({ label: resolvedLoadingLabel }) :
|
|
1101
|
+
)))), showRowCount && displayCount > 0 && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "center" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel))))), loading ? renderLoadingState ? renderLoadingState({ label: resolvedLoadingLabel }) : (
|
|
1102
|
+
// Same EmptyState layout as the empty state, just the "building" image
|
|
1103
|
+
// + a loading message — so loading and empty match with no layout shift.
|
|
1104
|
+
/* @__PURE__ */ React.createElement(Tile, null, /* @__PURE__ */ React.createElement(Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ React.createElement(EmptyState, { title: resolvedLoadingLabel, imageName: "building", layout: "vertical" }, /* @__PURE__ */ React.createElement(Text, null, resolvedLoadingMessage))))
|
|
1105
|
+
) : error ? renderErrorState ? renderErrorState({
|
|
1054
1106
|
error,
|
|
1055
1107
|
title: typeof error === "string" ? error : resolvedErrorTitle,
|
|
1056
1108
|
message: typeof error === "string" ? resolvedRetryMessage : resolvedErrorMessage
|
|
1057
|
-
}) : /* @__PURE__ */ React.createElement(ErrorState, { title: typeof error === "string" ? error : resolvedErrorTitle }, /* @__PURE__ */ React.createElement(Text, null, typeof error === "string" ? resolvedRetryMessage : resolvedErrorMessage)) : displayRows.length === 0 ? renderEmptyState ? renderEmptyState({ title: resolvedEmptyTitle, message: resolvedEmptyMessage }) : /* @__PURE__ */ React.createElement(Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ React.createElement(EmptyState, { title: resolvedEmptyTitle, layout: "vertical" }, /* @__PURE__ */ React.createElement(Text, null, resolvedEmptyMessage))) : /* @__PURE__ */ React.createElement(
|
|
1109
|
+
}) : /* @__PURE__ */ React.createElement(ErrorState, { title: typeof error === "string" ? error : resolvedErrorTitle }, /* @__PURE__ */ React.createElement(Text, null, typeof error === "string" ? resolvedRetryMessage : resolvedErrorMessage)) : displayRows.length === 0 ? renderEmptyState ? renderEmptyState({ title: resolvedEmptyTitle, message: resolvedEmptyMessage }) : /* @__PURE__ */ React.createElement(Tile, null, /* @__PURE__ */ React.createElement(Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ React.createElement(EmptyState, { title: resolvedEmptyTitle, layout: "vertical" }, /* @__PURE__ */ React.createElement(Text, null, resolvedEmptyMessage)))) : /* @__PURE__ */ React.createElement(
|
|
1058
1110
|
Table,
|
|
1059
1111
|
{
|
|
1060
1112
|
bordered,
|