@open-mercato/ui 0.8.1-develop.7296.1.2111d779db → 0.8.1-develop.7441.1.b42958b98c
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 +1 -1
- package/dist/backend/CrudForm.js +19 -6
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +61 -9
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/RowActions.js +54 -5
- package/dist/backend/RowActions.js.map +2 -2
- package/dist/backend/charts/KpiCard.js +2 -1
- package/dist/backend/charts/KpiCard.js.map +2 -2
- package/dist/backend/detail/AttachmentsSection.js +17 -5
- package/dist/backend/detail/AttachmentsSection.js.map +2 -2
- package/dist/backend/detail/NotesSection.js +38 -20
- package/dist/backend/detail/NotesSection.js.map +2 -2
- package/dist/backend/dev/DevRuntimeDiagnosticsBanner.js +11 -1
- package/dist/backend/dev/DevRuntimeDiagnosticsBanner.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.generated.js +26 -0
- package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
- package/dist/backend/injection/eventBridge.js +33 -0
- package/dist/backend/injection/eventBridge.js.map +2 -2
- package/dist/backend/inputs/LookupSelect.js +20 -3
- package/dist/backend/inputs/LookupSelect.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +1 -1
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/inputs/TagsInput.js +20 -2
- package/dist/backend/inputs/TagsInput.js.map +2 -2
- package/dist/backend/messages/EmailThreadsPanel.js +2 -1
- package/dist/backend/messages/EmailThreadsPanel.js.map +2 -2
- package/dist/backend/messages/MessageComposer.js.map +2 -2
- package/dist/backend/messages/index.js.map +2 -2
- package/dist/backend/messages/message-compose-form-groups.js +24 -0
- package/dist/backend/messages/message-compose-form-groups.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +27 -0
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/backend/messages/useMessageComposeOperations.js +1 -0
- package/dist/backend/messages/useMessageComposeOperations.js.map +2 -2
- package/dist/backend/notifications/NotificationItem.js +8 -1
- package/dist/backend/notifications/NotificationItem.js.map +2 -2
- package/dist/portal/PortalShell.js +2 -2
- package/dist/portal/PortalShell.js.map +2 -2
- package/dist/primitives/calendar.js +69 -14
- package/dist/primitives/calendar.js.map +2 -2
- package/package.json +3 -3
- package/src/backend/CrudForm.tsx +30 -8
- package/src/backend/DataTable.tsx +92 -19
- package/src/backend/RowActions.tsx +114 -6
- package/src/backend/__tests__/AttachmentsSection.upload.test.tsx +183 -0
- package/src/backend/__tests__/CrudForm.fieldInjection.test.tsx +139 -2
- package/src/backend/__tests__/CrudForm.hiddenGroups.test.tsx +1 -1
- package/src/backend/__tests__/DataTable.extensions.test.tsx +30 -0
- package/src/backend/__tests__/DataTable.perspectiveReconcile.test.tsx +320 -2
- package/src/backend/__tests__/DevRuntimeDiagnosticsBanner.test.tsx +117 -0
- package/src/backend/__tests__/NotesSection.test.tsx +138 -0
- package/src/backend/__tests__/RowActions.test.tsx +202 -0
- package/src/backend/charts/KpiCard.tsx +1 -0
- package/src/backend/charts/__tests__/KpiCard.test.tsx +20 -0
- package/src/backend/detail/AttachmentsSection.tsx +17 -5
- package/src/backend/detail/NotesSection.tsx +122 -66
- package/src/backend/dev/DevRuntimeDiagnosticsBanner.tsx +24 -1
- package/src/backend/icons/lucideRegistry.generated.tsx +26 -0
- package/src/backend/injection/__tests__/eventBridge.test.tsx +47 -1
- package/src/backend/injection/eventBridge.ts +35 -0
- package/src/backend/inputs/LookupSelect.tsx +32 -3
- package/src/backend/inputs/PhoneNumberField.tsx +1 -1
- package/src/backend/inputs/TagsInput.tsx +24 -3
- package/src/backend/inputs/__tests__/LookupSelect.test.tsx +166 -1
- package/src/backend/inputs/__tests__/PhoneNumberField.typeahead.test.tsx +43 -0
- package/src/backend/inputs/__tests__/TagsInput.test.tsx +81 -0
- package/src/backend/messages/EmailThreadsPanel.tsx +21 -1
- package/src/backend/messages/MessageComposer.tsx +1 -0
- package/src/backend/messages/__tests__/EmailThreadsPanel.senderLabel.test.tsx +99 -0
- package/src/backend/messages/__tests__/MessageComposer.test.tsx +44 -0
- package/src/backend/messages/__tests__/useMessageCompose.test.tsx +69 -0
- package/src/backend/messages/__tests__/useMessageComposeSender.test.tsx +208 -0
- package/src/backend/messages/index.ts +1 -0
- package/src/backend/messages/message-compose-form-groups.tsx +41 -0
- package/src/backend/messages/message-composer.types.ts +26 -0
- package/src/backend/messages/useMessageCompose.ts +46 -0
- package/src/backend/messages/useMessageComposeOperations.ts +8 -0
- package/src/backend/notifications/NotificationItem.tsx +7 -0
- package/src/backend/notifications/__tests__/NotificationItem.customRenderer.test.tsx +139 -0
- package/src/portal/PortalShell.tsx +7 -4
- package/src/portal/__tests__/PortalShell.test.tsx +29 -1
- package/src/primitives/__tests__/calendar.test.tsx +174 -1
- package/src/primitives/calendar.tsx +168 -96
|
@@ -50,6 +50,7 @@ import { flash } from "./FlashMessages.js";
|
|
|
50
50
|
import { useConfirmDialog } from "./confirm-dialog/index.js";
|
|
51
51
|
import { surfaceRecordConflict } from "./conflicts/index.js";
|
|
52
52
|
import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
|
|
53
|
+
import { useRegisteredComponent } from "./injection/useRegisteredComponent.js";
|
|
53
54
|
import { dataTableExtensionSpotId, extensionSpotChildId } from "@open-mercato/shared/modules/widgets/extension-points";
|
|
54
55
|
import { insertByInjectionPlacement } from "@open-mercato/shared/modules/widgets/injection-position";
|
|
55
56
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
@@ -736,7 +737,7 @@ function ViewSwitcherDropdown({
|
|
|
736
737
|
] })
|
|
737
738
|
] });
|
|
738
739
|
}
|
|
739
|
-
function
|
|
740
|
+
function DataTableImpl({
|
|
740
741
|
columns,
|
|
741
742
|
data,
|
|
742
743
|
toolbar,
|
|
@@ -846,6 +847,11 @@ function DataTable({
|
|
|
846
847
|
const snapshotHydratedTableRef = React.useRef(null);
|
|
847
848
|
const serverReconciledTableRef = React.useRef(null);
|
|
848
849
|
const hydratedSnapshotRef = React.useRef(null);
|
|
850
|
+
const hydratedAdvancedFilterRestoredRef = React.useRef(false);
|
|
851
|
+
const pendingPerspectiveFiltersRef = React.useRef(null);
|
|
852
|
+
React.useLayoutEffect(() => {
|
|
853
|
+
pendingPerspectiveFiltersRef.current = null;
|
|
854
|
+
}, [advancedFilter?.value, perspectiveTableId]);
|
|
849
855
|
const initialSettingsSource = perspectiveConfig?.initialState?.initialSettings ?? null;
|
|
850
856
|
const mergedInitialSettings = React.useMemo(
|
|
851
857
|
() => sanitizePerspectiveSettings(initialSettingsSource),
|
|
@@ -1350,9 +1356,18 @@ function DataTable({
|
|
|
1350
1356
|
}, [table, columnOrder, columnVisibility, columnSizing, sorting, filterValues, searchValue, advancedFilter]);
|
|
1351
1357
|
const applyPerspectiveSettings = React.useCallback((settings, nextId, options) => {
|
|
1352
1358
|
const normalized = sanitizePerspectiveSettings(settings) ?? {};
|
|
1359
|
+
if (!options?.preserveAdvancedFilter && advancedFilter?.onApplyTree) {
|
|
1360
|
+
hydratedAdvancedFilterRestoredRef.current = false;
|
|
1361
|
+
pendingPerspectiveFiltersRef.current = {
|
|
1362
|
+
filters: isPersistedFilterTree(normalized.filters) ? normalized.filters : void 0
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1353
1365
|
autoHiddenVisibilityRef.current = {};
|
|
1354
1366
|
setViewBaseline(
|
|
1355
|
-
options?.preserveAdvancedFilter ? {
|
|
1367
|
+
options?.preserveAdvancedFilter ? {
|
|
1368
|
+
...normalized,
|
|
1369
|
+
filters: pendingPerspectiveFiltersRef.current ? pendingPerspectiveFiltersRef.current.filters : getCurrentSettings().filters
|
|
1370
|
+
} : normalized
|
|
1356
1371
|
);
|
|
1357
1372
|
if (normalized.columnOrder && normalized.columnOrder.length) {
|
|
1358
1373
|
setColumnOrder(normalized.columnOrder);
|
|
@@ -1399,7 +1414,10 @@ function DataTable({
|
|
|
1399
1414
|
if (perspectiveTableId) {
|
|
1400
1415
|
writePerspectiveCookie(perspectiveTableId, nextId);
|
|
1401
1416
|
if (nextId) {
|
|
1402
|
-
const
|
|
1417
|
+
const previousSnapshot = readPerspectiveSnapshot(perspectiveTableId) ?? initialSnapshotRef.current;
|
|
1418
|
+
const preserveClearedFilter = options?.preserveAdvancedFilter && !getCurrentSettings().filters && !previousSnapshot?.settings.filters;
|
|
1419
|
+
const snapshotSettings = preserveClearedFilter ? { ...normalized, filters: void 0 } : normalized;
|
|
1420
|
+
const snapshot = { perspectiveId: nextId, settings: snapshotSettings, updatedAt: Date.now() };
|
|
1403
1421
|
writePerspectiveSnapshot(perspectiveTableId, snapshot);
|
|
1404
1422
|
initialSnapshotRef.current = snapshot;
|
|
1405
1423
|
} else if (normalized.columnSizing && Object.keys(normalized.columnSizing).length) {
|
|
@@ -1450,18 +1468,36 @@ function DataTable({
|
|
|
1450
1468
|
if (!perspectiveTableId) return;
|
|
1451
1469
|
if (snapshotHydratedTableRef.current === perspectiveTableId) return;
|
|
1452
1470
|
snapshotHydratedTableRef.current = perspectiveTableId;
|
|
1471
|
+
hydratedAdvancedFilterRestoredRef.current = false;
|
|
1453
1472
|
const snapshot = readPerspectiveSnapshot(perspectiveTableId);
|
|
1454
1473
|
if (!snapshot) return;
|
|
1455
1474
|
initialSnapshotRef.current = snapshot;
|
|
1456
1475
|
hydratedSnapshotRef.current = snapshot;
|
|
1457
|
-
const
|
|
1476
|
+
const restoredTree = isPersistedFilterTree(snapshot.settings.filters) ? deserializeTreeFromPersist(snapshot.settings.filters) : null;
|
|
1477
|
+
const preserveAdvancedFilter = !!advancedFilter?.onApplyTree && (advancedFilter.value.root.children.length > 0 || !restoredTree?.root.children.length);
|
|
1458
1478
|
applyPerspectiveSettings(
|
|
1459
1479
|
snapshot.settings,
|
|
1460
1480
|
snapshot.perspectiveId ?? null,
|
|
1461
1481
|
{ preserveAdvancedFilter }
|
|
1462
1482
|
);
|
|
1483
|
+
hydratedAdvancedFilterRestoredRef.current = !!advancedFilter?.onApplyTree && !preserveAdvancedFilter;
|
|
1463
1484
|
initialPerspectiveAppliedRef.current = true;
|
|
1464
1485
|
}, [perspectiveTableId, applyPerspectiveSettings, advancedFilter]);
|
|
1486
|
+
const previousAdvancedFilterRef = React.useRef(null);
|
|
1487
|
+
const advancedFilterHasRules = !!advancedFilter?.value.root.children.length;
|
|
1488
|
+
React.useEffect(() => {
|
|
1489
|
+
const previous = previousAdvancedFilterRef.current;
|
|
1490
|
+
previousAdvancedFilterRef.current = { tableId: perspectiveTableId, hasRules: advancedFilterHasRules };
|
|
1491
|
+
if (!perspectiveTableId || !advancedFilter?.onApplyTree) return;
|
|
1492
|
+
if (previous?.tableId !== perspectiveTableId || !previous.hasRules || advancedFilterHasRules) return;
|
|
1493
|
+
const snapshot = readPerspectiveSnapshot(perspectiveTableId) ?? initialSnapshotRef.current;
|
|
1494
|
+
if (!snapshot) return;
|
|
1495
|
+
const settings = { ...snapshot.settings };
|
|
1496
|
+
delete settings.filters;
|
|
1497
|
+
const clearedSnapshot = { ...snapshot, settings, updatedAt: Date.now() };
|
|
1498
|
+
writePerspectiveSnapshot(perspectiveTableId, clearedSnapshot);
|
|
1499
|
+
initialSnapshotRef.current = clearedSnapshot;
|
|
1500
|
+
}, [perspectiveTableId, advancedFilterHasRules, advancedFilter?.onApplyTree]);
|
|
1465
1501
|
const perspectiveQueryKey = ["table-perspectives", perspectiveTableId];
|
|
1466
1502
|
const rolePerspectivesForLocking = React.useMemo(
|
|
1467
1503
|
() => perspectiveData?.manageableRolePerspectives ?? perspectiveData?.rolePerspectives ?? [],
|
|
@@ -1873,15 +1909,21 @@ function DataTable({
|
|
|
1873
1909
|
React.useLayoutEffect(() => {
|
|
1874
1910
|
if (!canUsePerspectives) return;
|
|
1875
1911
|
if (!perspectiveTableId) return;
|
|
1912
|
+
if ((initialSnapshotRef.current || initialPerspectiveAppliedRef.current) && serverReconciledTableRef.current === perspectiveTableId) return;
|
|
1876
1913
|
const source = perspectiveData ?? perspectiveConfig?.initialState?.response;
|
|
1877
1914
|
if (!source) return;
|
|
1878
1915
|
let orphanedSnapshotDropped = false;
|
|
1916
|
+
const currentFilters = pendingPerspectiveFiltersRef.current ? pendingPerspectiveFiltersRef.current.filters : getCurrentSettings().filters;
|
|
1917
|
+
const restoredFilterStillActive = hydratedAdvancedFilterRestoredRef.current && diffPerspectiveSettings(
|
|
1918
|
+
{ filters: currentFilters },
|
|
1919
|
+
{ filters: hydratedSnapshotRef.current?.settings.filters }
|
|
1920
|
+
).length === 0;
|
|
1921
|
+
const preserveAdvancedFilter = !!advancedFilter?.onApplyTree && !restoredFilterStillActive;
|
|
1879
1922
|
const tryResolve = (id) => {
|
|
1880
1923
|
if (!id) return void 0;
|
|
1881
1924
|
return source.perspectives.find((p) => p.id === id) ?? source.rolePerspectives.find((p) => p.id === id);
|
|
1882
1925
|
};
|
|
1883
1926
|
if (initialSnapshotRef.current || initialPerspectiveAppliedRef.current) {
|
|
1884
|
-
if (serverReconciledTableRef.current === perspectiveTableId) return;
|
|
1885
1927
|
serverReconciledTableRef.current = perspectiveTableId;
|
|
1886
1928
|
const hydrated = hydratedSnapshotRef.current;
|
|
1887
1929
|
const snapshot = hydrated && (!activePerspectiveId || activePerspectiveId === hydrated.perspectiveId) ? hydrated : null;
|
|
@@ -1897,7 +1939,7 @@ function DataTable({
|
|
|
1897
1939
|
).length > 0;
|
|
1898
1940
|
if (serverIsNewer && settingsDiffer) {
|
|
1899
1941
|
applyPerspectiveSettings(local.settings, local.id, {
|
|
1900
|
-
preserveAdvancedFilter
|
|
1942
|
+
preserveAdvancedFilter
|
|
1901
1943
|
});
|
|
1902
1944
|
initialPerspectiveAppliedRef.current = true;
|
|
1903
1945
|
}
|
|
@@ -1928,15 +1970,15 @@ function DataTable({
|
|
|
1928
1970
|
applyPerspectiveSettings(
|
|
1929
1971
|
target.settings,
|
|
1930
1972
|
target.id,
|
|
1931
|
-
orphanedSnapshotDropped ? { preserveAdvancedFilter
|
|
1973
|
+
orphanedSnapshotDropped ? { preserveAdvancedFilter } : void 0
|
|
1932
1974
|
);
|
|
1933
1975
|
} else if (orphanedSnapshotDropped) {
|
|
1934
1976
|
applyPerspectiveSettings({}, null, {
|
|
1935
|
-
preserveAdvancedFilter
|
|
1977
|
+
preserveAdvancedFilter
|
|
1936
1978
|
});
|
|
1937
1979
|
}
|
|
1938
1980
|
initialPerspectiveAppliedRef.current = true;
|
|
1939
|
-
}, [canUsePerspectives, perspectiveData, perspectiveTableId, perspectiveConfig, applyPerspectiveSettings, activePerspectiveId, advancedFilter?.onApplyTree]);
|
|
1981
|
+
}, [canUsePerspectives, perspectiveData, perspectiveTableId, perspectiveConfig, applyPerspectiveSettings, activePerspectiveId, advancedFilter?.onApplyTree, getCurrentSettings]);
|
|
1940
1982
|
const scrollTableIntoView = React.useCallback(() => {
|
|
1941
1983
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1942
1984
|
if (!rect || rect.top >= 0) return;
|
|
@@ -2893,6 +2935,16 @@ function DataTable({
|
|
|
2893
2935
|
) : null
|
|
2894
2936
|
] }) });
|
|
2895
2937
|
}
|
|
2938
|
+
const DataTableFallback = DataTableImpl;
|
|
2939
|
+
function DataTable(props) {
|
|
2940
|
+
const extensionTableId = props.perspective?.tableId ?? props.extensionTableId ?? (props.injectionSpotId?.startsWith("data-table:") ? props.injectionSpotId.slice("data-table:".length) : null);
|
|
2941
|
+
const handle = props.replacementHandle ?? ComponentReplacementHandles.dataTable(extensionTableId ?? "unknown");
|
|
2942
|
+
const Resolved = useRegisteredComponent(
|
|
2943
|
+
handle,
|
|
2944
|
+
DataTableFallback
|
|
2945
|
+
);
|
|
2946
|
+
return /* @__PURE__ */ jsx(Resolved, { ...props });
|
|
2947
|
+
}
|
|
2896
2948
|
export {
|
|
2897
2949
|
DataTable,
|
|
2898
2950
|
clearAllPerspectiveState,
|