@open-mercato/ui 0.7.1-develop.7191.1.3c9346566b → 0.7.1-develop.7194.1.ab4fc81f82
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/.turbo/turbo-build.log +2 -2
- package/dist/backend/AppShell.js +66 -7
- package/dist/backend/AppShell.js.map +2 -2
- package/dist/backend/CrudForm.js +14 -8
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +167 -24
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/PerspectiveSidebar.js +60 -21
- package/dist/backend/PerspectiveSidebar.js.map +2 -2
- package/dist/backend/forms/ActionsDropdown.js +35 -5
- package/dist/backend/forms/ActionsDropdown.js.map +2 -2
- package/dist/backend/forms/index.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.generated.js +6 -0
- package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
- package/dist/backend/injection/spotIds.js +2 -0
- package/dist/backend/injection/spotIds.js.map +2 -2
- package/dist/backend/inputs/DurationInput.js +182 -0
- package/dist/backend/inputs/DurationInput.js.map +7 -0
- package/dist/backend/inputs/EventSelect.js.map +2 -2
- package/dist/backend/inputs/index.js +1 -0
- package/dist/backend/inputs/index.js.map +2 -2
- package/dist/backend/nav/navBadges.js +38 -0
- package/dist/backend/nav/navBadges.js.map +7 -0
- package/dist/backend/views/NewViewForm.js +46 -38
- package/dist/backend/views/NewViewForm.js.map +2 -2
- package/dist/primitives/segmented-control.js +4 -4
- package/dist/primitives/segmented-control.js.map +1 -1
- package/dist/primitives/sheet.js +21 -11
- package/dist/primitives/sheet.js.map +2 -2
- package/dist/primitives/textarea.js +54 -4
- package/dist/primitives/textarea.js.map +2 -2
- package/package.json +3 -3
- package/src/backend/AppShell.tsx +106 -2
- package/src/backend/CrudForm.tsx +28 -9
- package/src/backend/DataTable.tsx +293 -36
- package/src/backend/PerspectiveSidebar.tsx +80 -21
- package/src/backend/__tests__/CrudForm.density.test.tsx +113 -0
- package/src/backend/__tests__/DataTable.exportSectionTitles.test.tsx +134 -0
- package/src/backend/__tests__/DataTable.perspectiveReconcile.test.tsx +312 -0
- package/src/backend/__tests__/DataTable.propBulkActions.test.tsx +200 -0
- package/src/backend/__tests__/DataTable.render.test.tsx +76 -0
- package/src/backend/__tests__/PerspectiveSidebar.roleAutosave.test.tsx +252 -0
- package/src/backend/__tests__/navBadges.test.ts +57 -0
- package/src/backend/forms/ActionsDropdown.tsx +73 -6
- package/src/backend/forms/index.ts +1 -1
- package/src/backend/icons/lucideRegistry.generated.tsx +6 -0
- package/src/backend/injection/spotIds.ts +8 -0
- package/src/backend/inputs/DurationInput.tsx +207 -0
- package/src/backend/inputs/EventSelect.tsx +2 -0
- package/src/backend/inputs/__tests__/DurationInput.test.tsx +220 -0
- package/src/backend/inputs/index.ts +1 -0
- package/src/backend/nav/navBadges.ts +61 -0
- package/src/backend/views/NewViewForm.tsx +46 -32
- package/src/primitives/__tests__/segmented-control.test.tsx +2 -2
- package/src/primitives/__tests__/textarea.test.tsx +50 -0
- package/src/primitives/segmented-control.tsx +7 -7
- package/src/primitives/sheet.tsx +7 -1
- package/src/primitives/textarea.tsx +77 -4
|
@@ -3,11 +3,12 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useRouter } from "next/navigation";
|
|
5
5
|
import { flexRender } from "@tanstack/react-table";
|
|
6
|
-
import { useLegacyTable, getCoreRowModel, getSortedRowModel } from "@tanstack/react-table/legacy";
|
|
6
|
+
import { useLegacyTable, getCoreRowModel, getSortedRowModel, getExpandedRowModel } from "@tanstack/react-table/legacy";
|
|
7
7
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
8
|
-
import { RefreshCw, Loader2, SlidersHorizontal, MoreHorizontal, Circle, Filter, ChevronUp, ChevronDown, ChevronsUpDown, Check, Inbox, Save } from "lucide-react";
|
|
8
|
+
import { RefreshCw, Loader2, SlidersHorizontal, MoreHorizontal, Circle, Filter, ChevronUp, ChevronDown, ChevronRight, ChevronsUpDown, Check, Inbox, Save } from "lucide-react";
|
|
9
9
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../primitives/table.js";
|
|
10
10
|
import { Button } from "../primitives/button.js";
|
|
11
|
+
import { IconButton } from "../primitives/icon-button.js";
|
|
11
12
|
import { Checkbox } from "../primitives/checkbox.js";
|
|
12
13
|
import {
|
|
13
14
|
Select,
|
|
@@ -161,13 +162,17 @@ function collectUniqueById(entries, warningScope) {
|
|
|
161
162
|
}
|
|
162
163
|
return Array.from(byId.values());
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
+
const DEFAULT_VIEW_EXPORT_TITLE = "Export what you view";
|
|
166
|
+
const DEFAULT_FULL_EXPORT_TITLE = "Full data export";
|
|
167
|
+
function resolveExportSections(config, t) {
|
|
165
168
|
if (!config) return [];
|
|
166
169
|
const sections = [];
|
|
167
170
|
const baseFormats = config.formats && config.formats.length > 0 ? config.formats : DEFAULT_EXPORT_FORMATS;
|
|
168
|
-
const addSection = (key, section, fallbackTitle) => {
|
|
171
|
+
const addSection = (key, section, fallbackTitle, fallbackFilenameBase) => {
|
|
169
172
|
if (!section || !section.getUrl && !section.prepare) return;
|
|
170
|
-
const
|
|
173
|
+
const explicitTitle = section.title?.trim().length ? section.title.trim() : null;
|
|
174
|
+
const title = explicitTitle ?? fallbackTitle;
|
|
175
|
+
const filenameBase = explicitTitle ?? fallbackFilenameBase;
|
|
171
176
|
const seen = /* @__PURE__ */ new Set();
|
|
172
177
|
const formatsSource = section.formats && section.formats.length > 0 ? section.formats : baseFormats;
|
|
173
178
|
const formats = formatsSource.filter((format) => {
|
|
@@ -179,6 +184,7 @@ function resolveExportSections(config) {
|
|
|
179
184
|
sections.push({
|
|
180
185
|
key,
|
|
181
186
|
title,
|
|
187
|
+
filenameBase,
|
|
182
188
|
description: section.description,
|
|
183
189
|
formats,
|
|
184
190
|
getUrl: section.getUrl,
|
|
@@ -193,17 +199,19 @@ function resolveExportSections(config) {
|
|
|
193
199
|
});
|
|
194
200
|
};
|
|
195
201
|
const hasExplicitSections = Array.isArray(config.sections) && config.sections.length > 0;
|
|
202
|
+
const viewTitle = t("ui.dataTable.export.viewTitle", DEFAULT_VIEW_EXPORT_TITLE);
|
|
196
203
|
if (!config.view && !config.full && !hasExplicitSections && config.getUrl) {
|
|
197
|
-
addSection("view", { getUrl: config.getUrl, formats: config.formats },
|
|
204
|
+
addSection("view", { getUrl: config.getUrl, formats: config.formats }, viewTitle, DEFAULT_VIEW_EXPORT_TITLE);
|
|
198
205
|
} else {
|
|
199
|
-
addSection("view", config.view,
|
|
206
|
+
addSection("view", config.view, viewTitle, DEFAULT_VIEW_EXPORT_TITLE);
|
|
200
207
|
}
|
|
201
208
|
if (hasExplicitSections) {
|
|
202
209
|
config.sections.forEach((section, idx) => {
|
|
203
|
-
|
|
210
|
+
const numberedTitle = t("ui.dataTable.export.sectionTitle", "Export {index}", { index: idx + 1 });
|
|
211
|
+
addSection(`section-${idx}`, section, numberedTitle, `Export ${idx + 1}`);
|
|
204
212
|
});
|
|
205
213
|
}
|
|
206
|
-
addSection("full", config.full, "
|
|
214
|
+
addSection("full", config.full, t("ui.dataTable.export.fullTitle", DEFAULT_FULL_EXPORT_TITLE), DEFAULT_FULL_EXPORT_TITLE);
|
|
207
215
|
return sections;
|
|
208
216
|
}
|
|
209
217
|
const COLUMN_MIN_WIDTH = 60;
|
|
@@ -426,7 +434,7 @@ function ExportMenu({ config, sections }) {
|
|
|
426
434
|
if (!preparedResult) return;
|
|
427
435
|
const prepared = preparedResult.prepared;
|
|
428
436
|
const serialized = serializeExport(prepared, format);
|
|
429
|
-
const filename = preparedResult.filename ?? section.filename?.(format) ?? config.filename?.(format) ?? defaultExportFilename(section.
|
|
437
|
+
const filename = preparedResult.filename ?? section.filename?.(format) ?? config.filename?.(format) ?? defaultExportFilename(section.filenameBase, format);
|
|
430
438
|
if (typeof window !== "undefined") {
|
|
431
439
|
const blob = new Blob([serialized.body], { type: serialized.contentType });
|
|
432
440
|
const href = URL.createObjectURL(blob);
|
|
@@ -782,7 +790,11 @@ function DataTable({
|
|
|
782
790
|
advancedFilter: advancedFilterInput,
|
|
783
791
|
columnChooser,
|
|
784
792
|
activeFilterChips,
|
|
785
|
-
filterAwareEmptyState
|
|
793
|
+
filterAwareEmptyState,
|
|
794
|
+
getSubRows,
|
|
795
|
+
expandable,
|
|
796
|
+
expanded: expandedProp,
|
|
797
|
+
onExpandedChange
|
|
786
798
|
}) {
|
|
787
799
|
const t = useT();
|
|
788
800
|
const { confirm, ConfirmDialogElement } = useConfirmDialog();
|
|
@@ -828,9 +840,12 @@ function DataTable({
|
|
|
828
840
|
const queryClient = useQueryClient();
|
|
829
841
|
const perspectiveConfig = perspective ?? null;
|
|
830
842
|
const perspectiveTableId = perspectiveConfig?.tableId ?? null;
|
|
843
|
+
const perspectiveAlign = perspectiveConfig?.align ?? "left";
|
|
831
844
|
const perspectiveEnabled = Boolean(perspectiveTableId);
|
|
832
845
|
const initialSnapshotRef = React.useRef(null);
|
|
833
846
|
const snapshotHydratedTableRef = React.useRef(null);
|
|
847
|
+
const serverReconciledTableRef = React.useRef(null);
|
|
848
|
+
const hydratedSnapshotRef = React.useRef(null);
|
|
834
849
|
const initialSettingsSource = perspectiveConfig?.initialState?.initialSettings ?? null;
|
|
835
850
|
const mergedInitialSettings = React.useMemo(
|
|
836
851
|
() => sanitizePerspectiveSettings(initialSettingsSource),
|
|
@@ -1183,14 +1198,34 @@ function DataTable({
|
|
|
1183
1198
|
const [rowSelection, setRowSelection] = React.useState({});
|
|
1184
1199
|
const selectionScopeKeyRef = React.useRef(selectionScopeKey);
|
|
1185
1200
|
const enableClientSorting = sortable && !manualSorting;
|
|
1201
|
+
const expansionEnabled = getSubRows !== void 0 || expandable !== void 0;
|
|
1202
|
+
const [internalExpanded, setInternalExpanded] = React.useState({});
|
|
1203
|
+
const expandedState = expandedProp !== void 0 ? expandedProp : internalExpanded;
|
|
1204
|
+
const handleExpandedChange = React.useCallback((updater) => {
|
|
1205
|
+
if (onExpandedChange) {
|
|
1206
|
+
onExpandedChange(updater);
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
setInternalExpanded((prev) => typeof updater === "function" ? updater(prev) : updater);
|
|
1210
|
+
}, [onExpandedChange]);
|
|
1186
1211
|
const table = useLegacyTable({
|
|
1187
1212
|
data: clientFilteredData,
|
|
1188
1213
|
columns: mergedColumns,
|
|
1189
1214
|
getCoreRowModel: getCoreRowModel(),
|
|
1190
1215
|
...enableClientSorting ? { getSortedRowModel: getSortedRowModel() } : {},
|
|
1216
|
+
...expansionEnabled ? {
|
|
1217
|
+
getSubRows,
|
|
1218
|
+
getExpandedRowModel: getExpandedRowModel(),
|
|
1219
|
+
getRowCanExpand: (row) => {
|
|
1220
|
+
if (typeof expandable === "function") return expandable(row.original);
|
|
1221
|
+
if (expandable === true) return true;
|
|
1222
|
+
return (row.subRows?.length ?? 0) > 0;
|
|
1223
|
+
},
|
|
1224
|
+
onExpandedChange: handleExpandedChange
|
|
1225
|
+
} : {},
|
|
1191
1226
|
manualSorting: manualSorting === true,
|
|
1192
1227
|
getRowId: resolveDataTableRowId,
|
|
1193
|
-
state: { sorting, columnVisibility, columnOrder, rowSelection },
|
|
1228
|
+
state: { sorting, columnVisibility, columnOrder, rowSelection, ...expansionEnabled ? { expanded: expandedState } : {} },
|
|
1194
1229
|
enableRowSelection: hasInjectedBulkActions,
|
|
1195
1230
|
onSortingChange: (updater) => {
|
|
1196
1231
|
const next = typeof updater === "function" ? updater(sorting) : updater;
|
|
@@ -1399,6 +1434,7 @@ function DataTable({
|
|
|
1399
1434
|
const snapshot = readPerspectiveSnapshot(perspectiveTableId);
|
|
1400
1435
|
if (!snapshot) return;
|
|
1401
1436
|
initialSnapshotRef.current = snapshot;
|
|
1437
|
+
hydratedSnapshotRef.current = snapshot;
|
|
1402
1438
|
const preserveAdvancedFilter = !!advancedFilter?.onApplyTree;
|
|
1403
1439
|
applyPerspectiveSettings(
|
|
1404
1440
|
snapshot.settings,
|
|
@@ -1818,14 +1854,42 @@ function DataTable({
|
|
|
1818
1854
|
React.useLayoutEffect(() => {
|
|
1819
1855
|
if (!canUsePerspectives) return;
|
|
1820
1856
|
if (!perspectiveTableId) return;
|
|
1821
|
-
if (initialSnapshotRef.current) return;
|
|
1822
|
-
if (initialPerspectiveAppliedRef.current) return;
|
|
1823
1857
|
const source = perspectiveData ?? perspectiveConfig?.initialState?.response;
|
|
1824
1858
|
if (!source) return;
|
|
1859
|
+
let orphanedSnapshotDropped = false;
|
|
1825
1860
|
const tryResolve = (id) => {
|
|
1826
1861
|
if (!id) return void 0;
|
|
1827
1862
|
return source.perspectives.find((p) => p.id === id) ?? source.rolePerspectives.find((p) => p.id === id);
|
|
1828
1863
|
};
|
|
1864
|
+
if (initialSnapshotRef.current || initialPerspectiveAppliedRef.current) {
|
|
1865
|
+
if (serverReconciledTableRef.current === perspectiveTableId) return;
|
|
1866
|
+
serverReconciledTableRef.current = perspectiveTableId;
|
|
1867
|
+
const hydrated = hydratedSnapshotRef.current;
|
|
1868
|
+
const snapshot = hydrated && (!activePerspectiveId || activePerspectiveId === hydrated.perspectiveId) ? hydrated : null;
|
|
1869
|
+
const localId = snapshot?.perspectiveId ?? activePerspectiveId;
|
|
1870
|
+
if (!localId) return;
|
|
1871
|
+
const local = tryResolve(localId);
|
|
1872
|
+
if (local) {
|
|
1873
|
+
const serverUpdatedAt = local.updatedAt ? Date.parse(local.updatedAt) : NaN;
|
|
1874
|
+
const serverIsNewer = snapshot != null && Number.isFinite(serverUpdatedAt) && serverUpdatedAt > snapshot.updatedAt;
|
|
1875
|
+
const settingsDiffer = snapshot != null && diffPerspectiveSettings(
|
|
1876
|
+
sanitizePerspectiveSettings(local.settings) ?? {},
|
|
1877
|
+
sanitizePerspectiveSettings(snapshot.settings) ?? {}
|
|
1878
|
+
).length > 0;
|
|
1879
|
+
if (serverIsNewer && settingsDiffer) {
|
|
1880
|
+
applyPerspectiveSettings(local.settings, local.id, {
|
|
1881
|
+
preserveAdvancedFilter: !!advancedFilter?.onApplyTree
|
|
1882
|
+
});
|
|
1883
|
+
initialPerspectiveAppliedRef.current = true;
|
|
1884
|
+
}
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
writePerspectiveSnapshot(perspectiveTableId, null);
|
|
1888
|
+
initialSnapshotRef.current = null;
|
|
1889
|
+
hydratedSnapshotRef.current = null;
|
|
1890
|
+
initialPerspectiveAppliedRef.current = false;
|
|
1891
|
+
orphanedSnapshotDropped = true;
|
|
1892
|
+
}
|
|
1829
1893
|
let target;
|
|
1830
1894
|
if (activePerspectiveId) {
|
|
1831
1895
|
target = tryResolve(activePerspectiveId);
|
|
@@ -1842,10 +1906,18 @@ function DataTable({
|
|
|
1842
1906
|
target = source.perspectives[0];
|
|
1843
1907
|
}
|
|
1844
1908
|
if (target) {
|
|
1845
|
-
applyPerspectiveSettings(
|
|
1909
|
+
applyPerspectiveSettings(
|
|
1910
|
+
target.settings,
|
|
1911
|
+
target.id,
|
|
1912
|
+
orphanedSnapshotDropped ? { preserveAdvancedFilter: !!advancedFilter?.onApplyTree } : void 0
|
|
1913
|
+
);
|
|
1914
|
+
} else if (orphanedSnapshotDropped) {
|
|
1915
|
+
applyPerspectiveSettings({}, null, {
|
|
1916
|
+
preserveAdvancedFilter: !!advancedFilter?.onApplyTree
|
|
1917
|
+
});
|
|
1846
1918
|
}
|
|
1847
1919
|
initialPerspectiveAppliedRef.current = true;
|
|
1848
|
-
}, [canUsePerspectives, perspectiveData, perspectiveTableId, perspectiveConfig, applyPerspectiveSettings, activePerspectiveId]);
|
|
1920
|
+
}, [canUsePerspectives, perspectiveData, perspectiveTableId, perspectiveConfig, applyPerspectiveSettings, activePerspectiveId, advancedFilter?.onApplyTree]);
|
|
1849
1921
|
const scrollTableIntoView = React.useCallback(() => {
|
|
1850
1922
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1851
1923
|
if (!rect || rect.top >= 0) return;
|
|
@@ -2154,12 +2226,44 @@ function DataTable({
|
|
|
2154
2226
|
);
|
|
2155
2227
|
const runPropBulkAction = React.useCallback(
|
|
2156
2228
|
async (action) => {
|
|
2157
|
-
|
|
2158
|
-
|
|
2229
|
+
try {
|
|
2230
|
+
const result = await action.onExecute(selectedRows);
|
|
2231
|
+
if (result === false) return;
|
|
2232
|
+
if (!result || typeof result !== "object") {
|
|
2233
|
+
setRowSelection({});
|
|
2234
|
+
return;
|
|
2235
|
+
}
|
|
2236
|
+
if (result.ok === false) {
|
|
2237
|
+
if (result.message === void 0) return;
|
|
2238
|
+
flash(result.message, "error");
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2159
2241
|
setRowSelection({});
|
|
2242
|
+
if (result.progressJobId) {
|
|
2243
|
+
trackedBulkProgressJobIdsRef.current.add(result.progressJobId);
|
|
2244
|
+
flash(
|
|
2245
|
+
result.message ?? t("ui.dataTable.bulkAction.started", "Bulk action started. Track progress in the top bar."),
|
|
2246
|
+
"success"
|
|
2247
|
+
);
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
flash(
|
|
2251
|
+
result.message ?? t("ui.dataTable.bulkAction.success", "Bulk action completed."),
|
|
2252
|
+
"success"
|
|
2253
|
+
);
|
|
2254
|
+
if (refreshButton?.onRefresh) {
|
|
2255
|
+
refreshButton.onRefresh();
|
|
2256
|
+
} else {
|
|
2257
|
+
scheduleRouterRefresh(router);
|
|
2258
|
+
}
|
|
2259
|
+
} catch (error2) {
|
|
2260
|
+
flash(
|
|
2261
|
+
error2 instanceof Error ? error2.message : t("ui.dataTable.bulkAction.error", "Bulk action failed."),
|
|
2262
|
+
"error"
|
|
2263
|
+
);
|
|
2160
2264
|
}
|
|
2161
2265
|
},
|
|
2162
|
-
[selectedRows]
|
|
2266
|
+
[refreshButton, router, selectedRows, t]
|
|
2163
2267
|
);
|
|
2164
2268
|
const builtToolbar = React.useMemo(() => {
|
|
2165
2269
|
if (toolbar) return toolbar;
|
|
@@ -2240,6 +2344,7 @@ function DataTable({
|
|
|
2240
2344
|
}
|
|
2241
2345
|
)
|
|
2242
2346
|
] }) : null;
|
|
2347
|
+
const perspectiveButtonLeading = perspectiveAlign === "right" ? null : perspectiveButton;
|
|
2243
2348
|
const saveViewButton = showSaveViewButton && canUsePerspectives ? /* @__PURE__ */ jsxs(
|
|
2244
2349
|
Button,
|
|
2245
2350
|
{
|
|
@@ -2259,9 +2364,9 @@ function DataTable({
|
|
|
2259
2364
|
]
|
|
2260
2365
|
}
|
|
2261
2366
|
) : null;
|
|
2262
|
-
const leadingItems = advancedFilterButton ||
|
|
2367
|
+
const leadingItems = advancedFilterButton || perspectiveButtonLeading || saveViewButton ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2263
2368
|
advancedFilterButton,
|
|
2264
|
-
|
|
2369
|
+
perspectiveButtonLeading,
|
|
2265
2370
|
saveViewButton
|
|
2266
2371
|
] }) : null;
|
|
2267
2372
|
const trailingItems = hasBulkButtons ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -2305,6 +2410,7 @@ function DataTable({
|
|
|
2305
2410
|
}) : null
|
|
2306
2411
|
] }) : null;
|
|
2307
2412
|
const searchTrailingNode = searchTrailingInjectionSpotId && onSearchChange ? /* @__PURE__ */ jsx(InjectionSpot, { spotId: searchTrailingInjectionSpotId, context: resolvedInjectionContext }) : null;
|
|
2413
|
+
if (perspectiveAlign === "right" && !anySearch && combined.length === 0 && !advancedFilterButton && !saveViewButton && !trailingItems && !fieldsetSelector) return null;
|
|
2308
2414
|
return /* @__PURE__ */ jsx(
|
|
2309
2415
|
FilterBar,
|
|
2310
2416
|
{
|
|
@@ -2337,6 +2443,7 @@ function DataTable({
|
|
|
2337
2443
|
onFiltersApply,
|
|
2338
2444
|
onFiltersClear,
|
|
2339
2445
|
canUsePerspectives,
|
|
2446
|
+
perspectiveAlign,
|
|
2340
2447
|
embedded,
|
|
2341
2448
|
supportsCustomFieldFilterFieldsets,
|
|
2342
2449
|
resolvedEntityIds,
|
|
@@ -2367,7 +2474,7 @@ function DataTable({
|
|
|
2367
2474
|
const hasActions = actions !== void 0 && actions !== null && actions !== false;
|
|
2368
2475
|
const shouldReserveActionsSpace = actions === null || actions === false;
|
|
2369
2476
|
const exportConfig = exporter === false ? null : exporter || null;
|
|
2370
|
-
const resolvedExportSections = React.useMemo(() => resolveExportSections(exportConfig), [exportConfig]);
|
|
2477
|
+
const resolvedExportSections = React.useMemo(() => resolveExportSections(exportConfig, t), [exportConfig, t]);
|
|
2371
2478
|
const hasExport = resolvedExportSections.length > 0;
|
|
2372
2479
|
const refreshButtonConfig = refreshButton;
|
|
2373
2480
|
const hasRefreshButton = Boolean(refreshButtonConfig);
|
|
@@ -2432,7 +2539,18 @@ function DataTable({
|
|
|
2432
2539
|
]
|
|
2433
2540
|
}
|
|
2434
2541
|
) : null,
|
|
2435
|
-
canUsePerspectives ? /* @__PURE__ */
|
|
2542
|
+
canUsePerspectives ? perspectiveAlign === "right" ? /* @__PURE__ */ jsx(
|
|
2543
|
+
ViewSwitcherDropdown,
|
|
2544
|
+
{
|
|
2545
|
+
activePerspectiveId,
|
|
2546
|
+
perspectives: perspectiveData?.perspectives ?? [],
|
|
2547
|
+
rolePerspectives: perspectiveData?.rolePerspectives ?? [],
|
|
2548
|
+
onClear: () => applyPerspectiveSettings({}, null),
|
|
2549
|
+
onActivate: handlePerspectiveActivate,
|
|
2550
|
+
onOpenSidebar: () => setPerspectiveOpen(true),
|
|
2551
|
+
t
|
|
2552
|
+
}
|
|
2553
|
+
) : /* @__PURE__ */ jsxs(
|
|
2436
2554
|
Button,
|
|
2437
2555
|
{
|
|
2438
2556
|
type: "button",
|
|
@@ -2633,12 +2751,37 @@ function DataTable({
|
|
|
2633
2751
|
const sizedWidth = enableColumnResize && columnId ? columnSizing[columnId] : void 0;
|
|
2634
2752
|
const effectiveMaxWidth = typeof sizedWidth === "number" ? `${sizedWidth}px` : maxWidth;
|
|
2635
2753
|
const wrappedContent = shouldTruncate ? /* @__PURE__ */ jsx(TruncatedCell, { maxWidth: effectiveMaxWidth, tooltipContent: tooltipText, children: content }) : content;
|
|
2754
|
+
const expandAffordance = expansionEnabled && cellIndex === 0 ? /* @__PURE__ */ jsx(
|
|
2755
|
+
"span",
|
|
2756
|
+
{
|
|
2757
|
+
className: "inline-flex shrink-0 items-center",
|
|
2758
|
+
style: { paddingLeft: `${row.depth * 1.25}rem` },
|
|
2759
|
+
children: row.getCanExpand() ? /* @__PURE__ */ jsx(
|
|
2760
|
+
IconButton,
|
|
2761
|
+
{
|
|
2762
|
+
type: "button",
|
|
2763
|
+
variant: "ghost",
|
|
2764
|
+
size: "xs",
|
|
2765
|
+
"aria-label": row.getIsExpanded() ? t("ui.dataTable.expand.collapseRow", "Collapse row") : t("ui.dataTable.expand.expandRow", "Expand row"),
|
|
2766
|
+
"aria-expanded": row.getIsExpanded(),
|
|
2767
|
+
onClick: (event) => {
|
|
2768
|
+
event.stopPropagation();
|
|
2769
|
+
row.toggleExpanded();
|
|
2770
|
+
},
|
|
2771
|
+
children: row.getIsExpanded() ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
|
|
2772
|
+
}
|
|
2773
|
+
) : /* @__PURE__ */ jsx("span", { className: "inline-block size-6", "aria-hidden": "true" })
|
|
2774
|
+
}
|
|
2775
|
+
) : null;
|
|
2636
2776
|
return /* @__PURE__ */ jsx(
|
|
2637
2777
|
TableCell,
|
|
2638
2778
|
{
|
|
2639
2779
|
className: responsiveClass(priority, columnMeta?.hidden) + (isStickyCell ? ` md:sticky md:left-0 md:z-10 md:bg-background ${STICKY_LEFT_SHADOW_CLASS}` : ""),
|
|
2640
2780
|
style: typeof sizedWidth === "number" ? { width: sizedWidth, minWidth: sizedWidth, maxWidth: sizedWidth } : void 0,
|
|
2641
|
-
children:
|
|
2781
|
+
children: expandAffordance ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
2782
|
+
expandAffordance,
|
|
2783
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: wrappedContent })
|
|
2784
|
+
] }) : wrappedContent
|
|
2642
2785
|
},
|
|
2643
2786
|
cell.id
|
|
2644
2787
|
);
|