@proveanything/smartlinks-utils-ui 0.9.1 → 0.9.3
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/dist/{chunk-CBIKDA3S.js → chunk-2IQEDRSZ.js} +4 -31
- package/dist/chunk-2IQEDRSZ.js.map +1 -0
- package/dist/chunk-OLYC54YT.js +59 -0
- package/dist/chunk-OLYC54YT.js.map +1 -0
- package/dist/components/AssetPicker/index.css +2153 -3
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/AssetPicker/index.js +2 -1
- package/dist/components/ConditionsEditor/index.css +2153 -3
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +2153 -3
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +2153 -3
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +25 -16
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +90 -3
- package/dist/components/RecordsAdmin/index.js +505 -67
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +2153 -3
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-CBIKDA3S.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertComponentStylesLoaded } from '../../chunk-OLYC54YT.js';
|
|
1
2
|
import '../../chunk-5UQQYXCX.js';
|
|
2
3
|
import { FacetRuleEditor } from '../../chunk-JMCV6FOW.js';
|
|
3
4
|
import { useFacets } from '../../chunk-4LHF5JB7.js';
|
|
@@ -5,7 +6,7 @@ import { cn } from '../../chunk-L7FQ52F5.js';
|
|
|
5
6
|
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KFKVGUUP.js';
|
|
6
7
|
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KFKVGUUP.js';
|
|
7
8
|
import { createContext, useState, useEffect, useCallback, useMemo, useRef, useContext, useSyncExternalStore, createElement, useId } from 'react';
|
|
8
|
-
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle,
|
|
9
|
+
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, AlertCircle, Undo2, Save, Loader2, XCircle, ArrowRight, BookOpen, Globe2, Target, Check, Settings2 } from 'lucide-react';
|
|
9
10
|
import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
10
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
12
|
import { createPortal } from 'react-dom';
|
|
@@ -146,7 +147,11 @@ var DEFAULT_I18N = {
|
|
|
146
147
|
subtitleConfigured: "Configured",
|
|
147
148
|
subtitleInherited: "Inherited",
|
|
148
149
|
rulesTabTooltip: "Use rules to scope records to a targeted audience or a subset of products.",
|
|
149
|
-
rulesEmptyBody: "Create a rule to target a subset of products or a specific audience \u2014 for example, \u201Conly premium tier customers in Germany\u201D."
|
|
150
|
+
rulesEmptyBody: "Create a rule to target a subset of products or a specific audience \u2014 for example, \u201Conly premium tier customers in Germany\u201D.",
|
|
151
|
+
hookBeforeSaveFailed: "Couldn't save: {message}",
|
|
152
|
+
hookAfterSaveFailed: "Saved, but a follow-up step failed: {message}",
|
|
153
|
+
hookBeforeDeleteFailed: "Couldn't delete: {message}",
|
|
154
|
+
hookAfterDeleteFailed: "Deleted, but a follow-up step failed: {message}"
|
|
150
155
|
};
|
|
151
156
|
|
|
152
157
|
// src/components/RecordsAdmin/types/presentation.ts
|
|
@@ -1819,7 +1824,8 @@ function useShellNavigation(args) {
|
|
|
1819
1824
|
deepLinkState,
|
|
1820
1825
|
onTelemetry,
|
|
1821
1826
|
onBeforeDelete,
|
|
1822
|
-
generateItemId
|
|
1827
|
+
generateItemId,
|
|
1828
|
+
hooks
|
|
1823
1829
|
} = args;
|
|
1824
1830
|
const buildItemUrlValue = useCallback((id) => {
|
|
1825
1831
|
if (!baseScopeRef && id.startsWith("item:")) return id;
|
|
@@ -1904,6 +1910,34 @@ function useShellNavigation(args) {
|
|
|
1904
1910
|
const ok = await onBeforeDelete(editingScope ?? parseRef(""));
|
|
1905
1911
|
if (!ok) return;
|
|
1906
1912
|
}
|
|
1913
|
+
const row = collectionItems.items.find(
|
|
1914
|
+
(it) => it.itemId === itemId || it.id === itemId
|
|
1915
|
+
);
|
|
1916
|
+
const hookCtxBase = {
|
|
1917
|
+
collectionId: ctx.collectionId,
|
|
1918
|
+
appId: ctx.appId,
|
|
1919
|
+
recordType: ctx.recordType,
|
|
1920
|
+
scope: editingScope?.kind ?? "collection",
|
|
1921
|
+
targetRef: editingScope?.raw || void 0,
|
|
1922
|
+
admin: true
|
|
1923
|
+
};
|
|
1924
|
+
const recordSummary = row ?? {
|
|
1925
|
+
id: itemId,
|
|
1926
|
+
ref: editingScope?.raw ?? "",
|
|
1927
|
+
scope: editingScope ?? parseRef(""),
|
|
1928
|
+
data: null,
|
|
1929
|
+
status: "configured",
|
|
1930
|
+
label: itemId
|
|
1931
|
+
};
|
|
1932
|
+
if (hooks?.beforeDelete) {
|
|
1933
|
+
try {
|
|
1934
|
+
const result = await hooks.beforeDelete({ ...hookCtxBase, record: recordSummary });
|
|
1935
|
+
if (result === false) return;
|
|
1936
|
+
} catch (err) {
|
|
1937
|
+
console.warn("[RecordsAdmin] item beforeDelete hook cancelled delete", err);
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1907
1941
|
try {
|
|
1908
1942
|
const { removeRecord: removeRecord2 } = await import('../../records-AYYQSP7E.js');
|
|
1909
1943
|
await removeRecord2(ctx, itemId);
|
|
@@ -1911,6 +1945,13 @@ function useShellNavigation(args) {
|
|
|
1911
1945
|
if (selectedItemId === itemId) setSelectedItemId(null);
|
|
1912
1946
|
if (selectedItemId === itemId) deepLinkState.emit({ recordId: null }, "record.close");
|
|
1913
1947
|
collectionItems.refetch();
|
|
1948
|
+
if (hooks?.afterDelete) {
|
|
1949
|
+
try {
|
|
1950
|
+
await hooks.afterDelete({ ...hookCtxBase, record: recordSummary });
|
|
1951
|
+
} catch (err) {
|
|
1952
|
+
console.warn("[RecordsAdmin] item afterDelete hook failed", err);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1914
1955
|
} catch (err) {
|
|
1915
1956
|
console.error("[RecordsAdminShell] item delete failed", err);
|
|
1916
1957
|
}
|
|
@@ -1925,7 +1966,8 @@ function useShellNavigation(args) {
|
|
|
1925
1966
|
collectionItems,
|
|
1926
1967
|
deepLinkState,
|
|
1927
1968
|
editingScope,
|
|
1928
|
-
setSelectedItemId
|
|
1969
|
+
setSelectedItemId,
|
|
1970
|
+
hooks
|
|
1929
1971
|
]);
|
|
1930
1972
|
const itemViewCtx = useMemo(() => ({
|
|
1931
1973
|
onOpen: onItemOpen,
|
|
@@ -2072,13 +2114,24 @@ var useShellDeepLink = (args) => {
|
|
|
2072
2114
|
setSelectedVariantId,
|
|
2073
2115
|
selectedBatchId,
|
|
2074
2116
|
setSelectedBatchId,
|
|
2075
|
-
setFacetBrowseFilter
|
|
2117
|
+
setFacetBrowseFilter,
|
|
2118
|
+
isCollection,
|
|
2119
|
+
setSelectedItemId,
|
|
2120
|
+
collectionItems,
|
|
2121
|
+
recordListItems,
|
|
2122
|
+
recordListLoading,
|
|
2123
|
+
skipNextItemResetRef
|
|
2076
2124
|
} = args;
|
|
2077
2125
|
const lastAppliedDLRef = useRef("");
|
|
2078
2126
|
const [pendingDeepLinkRecordId, setPendingDeepLinkRecordId] = useState(null);
|
|
2127
|
+
const warnedMissingRef = useRef(/* @__PURE__ */ new Set());
|
|
2079
2128
|
useEffect(() => {
|
|
2080
2129
|
if (!deepLinkState.enabled) return;
|
|
2081
2130
|
if (selectedItemId) return;
|
|
2131
|
+
console.debug("[RecordsAdminShell] rail-scope emit", {
|
|
2132
|
+
scope: editingScope?.raw ?? null,
|
|
2133
|
+
itemView
|
|
2134
|
+
});
|
|
2082
2135
|
deepLinkState.emit({ scope: editingScope?.raw ?? null, recordId: null }, "scope");
|
|
2083
2136
|
lastAppliedDLRef.current = `${""}|${editingScope?.raw ?? ""}|${itemView}`;
|
|
2084
2137
|
}, [deepLinkState.enabled, editingScope?.raw, selectedItemId, itemView]);
|
|
@@ -2118,6 +2171,53 @@ var useShellDeepLink = (args) => {
|
|
|
2118
2171
|
});
|
|
2119
2172
|
}
|
|
2120
2173
|
}, [deepLinkState.enabled, deepLinkState.urlState]);
|
|
2174
|
+
useEffect(() => {
|
|
2175
|
+
const pending = pendingDeepLinkRecordId;
|
|
2176
|
+
if (!pending) return;
|
|
2177
|
+
if (isCollection) {
|
|
2178
|
+
const hit2 = collectionItems.items.find((it) => it.id === pending || it.itemId === pending);
|
|
2179
|
+
if (hit2) {
|
|
2180
|
+
skipNextItemResetRef.current = true;
|
|
2181
|
+
setSelectedItemId(pending);
|
|
2182
|
+
setPendingDeepLinkRecordId(null);
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
if (!collectionItems.isLoading) {
|
|
2186
|
+
if (!warnedMissingRef.current.has(pending)) {
|
|
2187
|
+
warnedMissingRef.current.add(pending);
|
|
2188
|
+
console.warn("[RecordsAdminShell] deep-linked recordId not found in collection items \u2014 clearing pending selection", {
|
|
2189
|
+
recordId: pending,
|
|
2190
|
+
scope: editingScope?.raw ?? null
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
2193
|
+
setPendingDeepLinkRecordId(null);
|
|
2194
|
+
}
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
const hit = recordListItems.find((it) => it.id === pending);
|
|
2198
|
+
if (hit) {
|
|
2199
|
+
if (selectedRecordId !== pending) setSelectedRecordId(pending);
|
|
2200
|
+
setPendingDeepLinkRecordId(null);
|
|
2201
|
+
return;
|
|
2202
|
+
}
|
|
2203
|
+
if (!recordListLoading) {
|
|
2204
|
+
if (!warnedMissingRef.current.has(pending)) {
|
|
2205
|
+
warnedMissingRef.current.add(pending);
|
|
2206
|
+
console.warn("[RecordsAdminShell] deep-linked recordId not found in records list \u2014 clearing pending selection", {
|
|
2207
|
+
recordId: pending,
|
|
2208
|
+
scope: editingScope?.raw ?? null
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
setPendingDeepLinkRecordId(null);
|
|
2212
|
+
}
|
|
2213
|
+
}, [
|
|
2214
|
+
pendingDeepLinkRecordId,
|
|
2215
|
+
isCollection,
|
|
2216
|
+
collectionItems.items,
|
|
2217
|
+
collectionItems.isLoading,
|
|
2218
|
+
recordListItems,
|
|
2219
|
+
recordListLoading
|
|
2220
|
+
]);
|
|
2121
2221
|
return { pendingDeepLinkRecordId, lastAppliedDLRef };
|
|
2122
2222
|
};
|
|
2123
2223
|
var isFacetRuleValid = (rule) => {
|
|
@@ -2231,6 +2331,25 @@ var createEditorStore = () => {
|
|
|
2231
2331
|
const listeners = /* @__PURE__ */ new Set();
|
|
2232
2332
|
let cachedList = [];
|
|
2233
2333
|
let nextOrder = 0;
|
|
2334
|
+
let hooksBundle = null;
|
|
2335
|
+
let notifier = null;
|
|
2336
|
+
const buildRecordSummary = (entry, value) => ({
|
|
2337
|
+
id: entry.recordId ?? null,
|
|
2338
|
+
ref: entry.spec.scope.raw,
|
|
2339
|
+
scope: entry.spec.scope,
|
|
2340
|
+
label: entry.label,
|
|
2341
|
+
status: "configured",
|
|
2342
|
+
data: value,
|
|
2343
|
+
facetRule: entry.facetRule
|
|
2344
|
+
});
|
|
2345
|
+
const buildHookCtxBase = (entry) => ({
|
|
2346
|
+
collectionId: entry.saveSpec.ctx.collectionId,
|
|
2347
|
+
appId: entry.saveSpec.ctx.appId,
|
|
2348
|
+
recordType: entry.saveSpec.ctx.recordType,
|
|
2349
|
+
scope: entry.spec.scope.kind,
|
|
2350
|
+
targetRef: entry.spec.scope.raw || void 0,
|
|
2351
|
+
admin: true
|
|
2352
|
+
});
|
|
2234
2353
|
const recompute = () => {
|
|
2235
2354
|
cachedList = Array.from(map.values()).sort((a, b) => a.order - b.order);
|
|
2236
2355
|
};
|
|
@@ -2384,10 +2503,35 @@ var createEditorStore = () => {
|
|
|
2384
2503
|
const entry = map.get(editorId);
|
|
2385
2504
|
if (!entry) return;
|
|
2386
2505
|
if (entry.status !== "dirty" && entry.status !== "error") return;
|
|
2387
|
-
|
|
2506
|
+
let persistedValue = entry.value;
|
|
2388
2507
|
const persistedFacetRule = entry.facetRule;
|
|
2389
2508
|
const { ctx, anchors } = entry.saveSpec;
|
|
2390
2509
|
const spec = entry.spec;
|
|
2510
|
+
const isCreate = !(entry.recordId && entry.source === "self") || !!spec.createMode;
|
|
2511
|
+
if (hooksBundle?.beforeSave) {
|
|
2512
|
+
try {
|
|
2513
|
+
const hookCtx = {
|
|
2514
|
+
...buildHookCtxBase(entry),
|
|
2515
|
+
isCreate,
|
|
2516
|
+
record: buildRecordSummary(entry, persistedValue),
|
|
2517
|
+
before: !isCreate ? buildRecordSummary(entry, entry.baseline) : void 0
|
|
2518
|
+
};
|
|
2519
|
+
const result = await hooksBundle.beforeSave(hookCtx);
|
|
2520
|
+
if (result === false) {
|
|
2521
|
+
return;
|
|
2522
|
+
}
|
|
2523
|
+
if (result && typeof result === "object") {
|
|
2524
|
+
persistedValue = persistedValue && typeof persistedValue === "object" ? { ...persistedValue, ...result } : result;
|
|
2525
|
+
}
|
|
2526
|
+
} catch (err) {
|
|
2527
|
+
notifier?.({ kind: "hook-before-save", error: err, recordLabel: entry.label });
|
|
2528
|
+
update(editorId, (e) => {
|
|
2529
|
+
e.status = "error";
|
|
2530
|
+
e.error = err;
|
|
2531
|
+
});
|
|
2532
|
+
return;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2391
2535
|
update(editorId, (e) => {
|
|
2392
2536
|
e.status = "saving";
|
|
2393
2537
|
e.error = void 0;
|
|
@@ -2424,6 +2568,9 @@ var createEditorStore = () => {
|
|
|
2424
2568
|
nextRecordId = upserted.record?.id ?? nextRecordId;
|
|
2425
2569
|
}
|
|
2426
2570
|
update(editorId, (e) => {
|
|
2571
|
+
if (persistedValue !== entry.value) {
|
|
2572
|
+
e.value = cloneDeep(persistedValue);
|
|
2573
|
+
}
|
|
2427
2574
|
e.baseline = cloneDeep(e.value);
|
|
2428
2575
|
e.baselineFacetRule = e.facetRule;
|
|
2429
2576
|
e.recordId = nextRecordId;
|
|
@@ -2431,6 +2578,21 @@ var createEditorStore = () => {
|
|
|
2431
2578
|
e.status = "saved";
|
|
2432
2579
|
e.error = void 0;
|
|
2433
2580
|
});
|
|
2581
|
+
if (hooksBundle?.afterSave) {
|
|
2582
|
+
const refreshed = map.get(editorId);
|
|
2583
|
+
const hookCtx = {
|
|
2584
|
+
...buildHookCtxBase(refreshed ?? entry),
|
|
2585
|
+
isCreate,
|
|
2586
|
+
record: buildRecordSummary(refreshed ?? entry, persistedValue),
|
|
2587
|
+
before: !isCreate ? buildRecordSummary(entry, entry.baseline) : void 0
|
|
2588
|
+
};
|
|
2589
|
+
try {
|
|
2590
|
+
await hooksBundle.afterSave(hookCtx);
|
|
2591
|
+
} catch (err) {
|
|
2592
|
+
notifier?.({ kind: "hook-after-save", error: err, recordLabel: entry.label });
|
|
2593
|
+
console.warn("[RecordsAdmin] afterSave hook failed", err);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2434
2596
|
} catch (err) {
|
|
2435
2597
|
update(editorId, (e) => {
|
|
2436
2598
|
e.status = "error";
|
|
@@ -2452,9 +2614,35 @@ var createEditorStore = () => {
|
|
|
2452
2614
|
if (!entry) return;
|
|
2453
2615
|
if (entry.source !== "self") return;
|
|
2454
2616
|
if (!entry.recordId) return;
|
|
2617
|
+
if (hooksBundle?.beforeDelete) {
|
|
2618
|
+
try {
|
|
2619
|
+
const hookCtx = {
|
|
2620
|
+
...buildHookCtxBase(entry),
|
|
2621
|
+
record: buildRecordSummary(entry, entry.value)
|
|
2622
|
+
};
|
|
2623
|
+
const result = await hooksBundle.beforeDelete(hookCtx);
|
|
2624
|
+
if (result === false) return;
|
|
2625
|
+
} catch (err) {
|
|
2626
|
+
notifier?.({ kind: "hook-before-delete", error: err, recordLabel: entry.label });
|
|
2627
|
+
console.warn("[RecordsAdmin] beforeDelete hook cancelled delete", err);
|
|
2628
|
+
return;
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
const deletedSnapshot = hooksBundle?.afterDelete ? {
|
|
2632
|
+
...buildHookCtxBase(entry),
|
|
2633
|
+
record: buildRecordSummary(entry, entry.value)
|
|
2634
|
+
} : null;
|
|
2455
2635
|
await removeRecord(entry.saveSpec.ctx, entry.recordId);
|
|
2456
2636
|
map.delete(editorId);
|
|
2457
2637
|
emit();
|
|
2638
|
+
if (hooksBundle?.afterDelete && deletedSnapshot) {
|
|
2639
|
+
try {
|
|
2640
|
+
await hooksBundle.afterDelete(deletedSnapshot);
|
|
2641
|
+
} catch (err) {
|
|
2642
|
+
notifier?.({ kind: "hook-after-delete", error: err, recordLabel: entry.label });
|
|
2643
|
+
console.warn("[RecordsAdmin] afterDelete hook failed", err);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2458
2646
|
},
|
|
2459
2647
|
enforcePoolLimit(max, exceptEditorId) {
|
|
2460
2648
|
const alive = Array.from(map.values());
|
|
@@ -2475,6 +2663,12 @@ var createEditorStore = () => {
|
|
|
2475
2663
|
return () => {
|
|
2476
2664
|
listeners.delete(listener);
|
|
2477
2665
|
};
|
|
2666
|
+
},
|
|
2667
|
+
setHooks(hooks) {
|
|
2668
|
+
hooksBundle = hooks ?? null;
|
|
2669
|
+
},
|
|
2670
|
+
setNotifier(notify2) {
|
|
2671
|
+
notifier = notify2 ?? null;
|
|
2478
2672
|
}
|
|
2479
2673
|
};
|
|
2480
2674
|
};
|
|
@@ -2496,10 +2690,14 @@ var EditorSessionProvider = ({
|
|
|
2496
2690
|
ctx,
|
|
2497
2691
|
children,
|
|
2498
2692
|
maxOpenEditors = 8,
|
|
2499
|
-
defaultValueFactory
|
|
2693
|
+
defaultValueFactory,
|
|
2694
|
+
hooks,
|
|
2695
|
+
onHookNotice
|
|
2500
2696
|
}) => {
|
|
2501
2697
|
const storeRef = useRef(null);
|
|
2502
2698
|
if (!storeRef.current) storeRef.current = createEditorStore();
|
|
2699
|
+
storeRef.current.setHooks(hooks ?? null);
|
|
2700
|
+
storeRef.current.setNotifier(onHookNotice ?? null);
|
|
2503
2701
|
const currentRef = useRef(void 0);
|
|
2504
2702
|
const listenersRef = useRef(/* @__PURE__ */ new Set());
|
|
2505
2703
|
const subscribeCurrent = useCallback((cb) => {
|
|
@@ -3873,7 +4071,7 @@ var classify2 = (mode, kind) => {
|
|
|
3873
4071
|
return SMART_PUSH.includes(kind) ? "push" : "replace";
|
|
3874
4072
|
};
|
|
3875
4073
|
function useDeepLinkState(options) {
|
|
3876
|
-
const enabled =
|
|
4074
|
+
const enabled = options?.enabled !== false;
|
|
3877
4075
|
const history = options?.history ?? "smart";
|
|
3878
4076
|
const paramNames = useMemo(() => ({
|
|
3879
4077
|
...DEFAULT_DEEP_LINK_PARAM_NAMES,
|
|
@@ -3903,8 +4101,15 @@ function useDeepLinkState(options) {
|
|
|
3903
4101
|
return adapter.subscribe(() => setUrlState(adapter.read()));
|
|
3904
4102
|
}, [adapter]);
|
|
3905
4103
|
const emit = useCallback((partial, kind) => {
|
|
3906
|
-
if (!adapter)
|
|
4104
|
+
if (!adapter) {
|
|
4105
|
+
console.debug("[smartlinks-ui] deep-link emit skipped \u2014 no adapter (deepLink not enabled?)", {
|
|
4106
|
+
partial,
|
|
4107
|
+
kind
|
|
4108
|
+
});
|
|
4109
|
+
return;
|
|
4110
|
+
}
|
|
3907
4111
|
const mode = classify2(history, kind);
|
|
4112
|
+
console.debug("[smartlinks-ui] deep-link emit", { partial, kind, mode });
|
|
3908
4113
|
adapter.write(partial, mode);
|
|
3909
4114
|
setUrlState((prev) => ({ ...prev, ...partial }));
|
|
3910
4115
|
}, [adapter, history]);
|
|
@@ -4100,8 +4305,15 @@ function RecordEditor({
|
|
|
4100
4305
|
const DeleteIcon = actionIcons?.delete;
|
|
4101
4306
|
const showInherited = ctx.source === "inherited";
|
|
4102
4307
|
const showEmpty = ctx.source === "empty";
|
|
4308
|
+
const hasBreadcrumb = (() => {
|
|
4309
|
+
const s = ctx.scope;
|
|
4310
|
+
return Boolean(s?.facetId || s?.productId || s?.variantId || s?.batchId);
|
|
4311
|
+
})();
|
|
4312
|
+
const hasLeftContent = Boolean(headerLabel) || hasBreadcrumb;
|
|
4313
|
+
const hasRightContent = showInherited || showEmpty || Boolean(headerMeta) || Boolean(bulkActions) || Boolean(targetingControl);
|
|
4314
|
+
const showHeader = hasLeftContent || hasRightContent;
|
|
4103
4315
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
4104
|
-
/* @__PURE__ */ jsxs(
|
|
4316
|
+
showHeader && /* @__PURE__ */ jsxs(
|
|
4105
4317
|
"header",
|
|
4106
4318
|
{
|
|
4107
4319
|
className: "sticky top-0 z-40 px-5 py-3 border-b flex items-start justify-between gap-3",
|
|
@@ -4955,14 +5167,16 @@ var PreviewScopePicker = ({
|
|
|
4955
5167
|
onChange,
|
|
4956
5168
|
showVariants,
|
|
4957
5169
|
showBatches,
|
|
5170
|
+
activeScope,
|
|
4958
5171
|
i18n
|
|
4959
5172
|
}) => {
|
|
4960
5173
|
const productPinned = !!editingScope.productId;
|
|
5174
|
+
const hideForTab = activeScope === "product" || activeScope === "variant" || activeScope === "batch";
|
|
4961
5175
|
const products = useProductBrowse({
|
|
4962
5176
|
SL,
|
|
4963
5177
|
collectionId,
|
|
4964
5178
|
pageSize: 100,
|
|
4965
|
-
enabled: !productPinned
|
|
5179
|
+
enabled: !productPinned && !hideForTab
|
|
4966
5180
|
});
|
|
4967
5181
|
const variants = useProductChildren({
|
|
4968
5182
|
SL,
|
|
@@ -4976,11 +5190,8 @@ var PreviewScopePicker = ({
|
|
|
4976
5190
|
productId: value.productId,
|
|
4977
5191
|
kind: showBatches ? "batch" : null
|
|
4978
5192
|
});
|
|
4979
|
-
const isDefault = useMemo(
|
|
4980
|
-
() => value.raw === editingScope.raw,
|
|
4981
|
-
[value.raw, editingScope.raw]
|
|
4982
|
-
);
|
|
4983
5193
|
useEffect(() => {
|
|
5194
|
+
if (hideForTab) return;
|
|
4984
5195
|
if (productPinned) return;
|
|
4985
5196
|
if (value.productId) return;
|
|
4986
5197
|
const first = products.items[0];
|
|
@@ -4992,9 +5203,10 @@ var PreviewScopePicker = ({
|
|
|
4992
5203
|
batchId: void 0,
|
|
4993
5204
|
raw: `product:${first.id}`
|
|
4994
5205
|
});
|
|
4995
|
-
}, [productPinned, value.productId, products.items]);
|
|
4996
|
-
const [
|
|
4997
|
-
|
|
5206
|
+
}, [hideForTab, productPinned, value.productId, products.items]);
|
|
5207
|
+
const [lightboxOpen, setLightboxOpen] = useState(false);
|
|
5208
|
+
if (hideForTab) return null;
|
|
5209
|
+
const showProductPicker = !productPinned;
|
|
4998
5210
|
const showVariantPicker = showVariants && !!value.productId && variants.items.length > 0;
|
|
4999
5211
|
const showBatchPicker = showBatches && !!value.productId && batches.items.length > 0;
|
|
5000
5212
|
if (!showProductPicker && !showVariantPicker && !showBatchPicker) {
|
|
@@ -5005,6 +5217,16 @@ var PreviewScopePicker = ({
|
|
|
5005
5217
|
borderColor: "hsl(var(--ra-border))",
|
|
5006
5218
|
color: "hsl(var(--ra-text))"
|
|
5007
5219
|
};
|
|
5220
|
+
const pickProduct = (productId) => {
|
|
5221
|
+
onChange({
|
|
5222
|
+
...value,
|
|
5223
|
+
productId,
|
|
5224
|
+
variantId: void 0,
|
|
5225
|
+
batchId: void 0,
|
|
5226
|
+
raw: `product:${productId}`
|
|
5227
|
+
});
|
|
5228
|
+
setLightboxOpen(false);
|
|
5229
|
+
};
|
|
5008
5230
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
5009
5231
|
/* @__PURE__ */ jsxs(
|
|
5010
5232
|
"span",
|
|
@@ -5017,56 +5239,27 @@ var PreviewScopePicker = ({
|
|
|
5017
5239
|
]
|
|
5018
5240
|
}
|
|
5019
5241
|
),
|
|
5020
|
-
|
|
5021
|
-
"
|
|
5022
|
-
{
|
|
5023
|
-
type: "button",
|
|
5024
|
-
onClick: () => onChange(editingScope),
|
|
5025
|
-
className: "text-[10px] px-2 py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5026
|
-
style: selectStyle,
|
|
5027
|
-
children: [
|
|
5028
|
-
"\u21BA ",
|
|
5029
|
-
i18n?.previewAsDefault ?? "Same as edited"
|
|
5030
|
-
]
|
|
5031
|
-
}
|
|
5032
|
-
),
|
|
5033
|
-
showProductPicker && !productPickerOpen && currentProductName && /* @__PURE__ */ jsxs(
|
|
5034
|
-
"button",
|
|
5242
|
+
showProductPicker && /* @__PURE__ */ jsxs(
|
|
5243
|
+
"span",
|
|
5035
5244
|
{
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
className: "text-[10px] px-2 py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1 max-w-[12rem] truncate",
|
|
5039
|
-
style: selectStyle,
|
|
5040
|
-
title: `Preview as ${currentProductName} \u2014 click to change`,
|
|
5245
|
+
className: "inline-flex items-center gap-1.5 text-[11px] truncate max-w-[18rem]",
|
|
5246
|
+
style: { color: "hsl(var(--ra-text))" },
|
|
5041
5247
|
children: [
|
|
5042
|
-
"
|
|
5043
|
-
/* @__PURE__ */ jsx(
|
|
5044
|
-
|
|
5248
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate", title: currentProductName, children: currentProductName || "\u2014" }),
|
|
5249
|
+
/* @__PURE__ */ jsx(
|
|
5250
|
+
"button",
|
|
5251
|
+
{
|
|
5252
|
+
type: "button",
|
|
5253
|
+
onClick: () => setLightboxOpen(true),
|
|
5254
|
+
className: "text-[10px] px-1.5 py-0.5 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5255
|
+
style: selectStyle,
|
|
5256
|
+
title: i18n?.change ?? "Change preview product",
|
|
5257
|
+
children: i18n?.change ?? "Change"
|
|
5258
|
+
}
|
|
5259
|
+
)
|
|
5045
5260
|
]
|
|
5046
5261
|
}
|
|
5047
5262
|
),
|
|
5048
|
-
showProductPicker && productPickerOpen && /* @__PURE__ */ jsx(
|
|
5049
|
-
"select",
|
|
5050
|
-
{
|
|
5051
|
-
className: SELECT_CLS,
|
|
5052
|
-
style: selectStyle,
|
|
5053
|
-
autoFocus: true,
|
|
5054
|
-
onBlur: () => setProductPickerOpen(false),
|
|
5055
|
-
value: value.productId ?? "",
|
|
5056
|
-
onChange: (e) => {
|
|
5057
|
-
const productId = e.target.value || void 0;
|
|
5058
|
-
onChange({
|
|
5059
|
-
...value,
|
|
5060
|
-
productId,
|
|
5061
|
-
variantId: void 0,
|
|
5062
|
-
batchId: void 0,
|
|
5063
|
-
raw: productId ? `product:${productId}` : ""
|
|
5064
|
-
});
|
|
5065
|
-
setProductPickerOpen(false);
|
|
5066
|
-
},
|
|
5067
|
-
children: products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
|
|
5068
|
-
}
|
|
5069
|
-
),
|
|
5070
5263
|
showVariantPicker && /* @__PURE__ */ jsxs(
|
|
5071
5264
|
"select",
|
|
5072
5265
|
{
|
|
@@ -5107,9 +5300,161 @@ var PreviewScopePicker = ({
|
|
|
5107
5300
|
batches.items.map((b) => /* @__PURE__ */ jsx("option", { value: b.id, children: b.name }, b.id))
|
|
5108
5301
|
]
|
|
5109
5302
|
}
|
|
5303
|
+
),
|
|
5304
|
+
lightboxOpen && /* @__PURE__ */ jsx(
|
|
5305
|
+
ProductPickerLightbox,
|
|
5306
|
+
{
|
|
5307
|
+
SL,
|
|
5308
|
+
collectionId,
|
|
5309
|
+
currentProductId: value.productId,
|
|
5310
|
+
onPick: pickProduct,
|
|
5311
|
+
onClose: () => setLightboxOpen(false),
|
|
5312
|
+
i18n
|
|
5313
|
+
}
|
|
5110
5314
|
)
|
|
5111
5315
|
] });
|
|
5112
5316
|
};
|
|
5317
|
+
var ProductPickerLightbox = ({
|
|
5318
|
+
SL,
|
|
5319
|
+
collectionId,
|
|
5320
|
+
currentProductId,
|
|
5321
|
+
onPick,
|
|
5322
|
+
onClose,
|
|
5323
|
+
i18n
|
|
5324
|
+
}) => {
|
|
5325
|
+
const [search, setSearch] = useState("");
|
|
5326
|
+
const inputRef = useRef(null);
|
|
5327
|
+
const browse = useProductBrowse({
|
|
5328
|
+
SL,
|
|
5329
|
+
collectionId,
|
|
5330
|
+
search,
|
|
5331
|
+
pageSize: 50,
|
|
5332
|
+
enabled: true
|
|
5333
|
+
});
|
|
5334
|
+
useEffect(() => {
|
|
5335
|
+
const prev = document.body.style.overflow;
|
|
5336
|
+
document.body.style.overflow = "hidden";
|
|
5337
|
+
const t = window.setTimeout(() => inputRef.current?.focus(), 0);
|
|
5338
|
+
const onKey = (e) => {
|
|
5339
|
+
if (e.key === "Escape") {
|
|
5340
|
+
e.stopPropagation();
|
|
5341
|
+
onClose();
|
|
5342
|
+
}
|
|
5343
|
+
};
|
|
5344
|
+
window.addEventListener("keydown", onKey, true);
|
|
5345
|
+
return () => {
|
|
5346
|
+
window.clearTimeout(t);
|
|
5347
|
+
window.removeEventListener("keydown", onKey, true);
|
|
5348
|
+
document.body.style.overflow = prev;
|
|
5349
|
+
};
|
|
5350
|
+
}, [onClose]);
|
|
5351
|
+
if (typeof document === "undefined") return null;
|
|
5352
|
+
return createPortal(
|
|
5353
|
+
/* @__PURE__ */ jsxs(
|
|
5354
|
+
"div",
|
|
5355
|
+
{
|
|
5356
|
+
className: "ra-shell ra-confirm-root",
|
|
5357
|
+
role: "presentation",
|
|
5358
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5359
|
+
onClick: (e) => e.stopPropagation(),
|
|
5360
|
+
onTouchStart: (e) => e.stopPropagation(),
|
|
5361
|
+
children: [
|
|
5362
|
+
/* @__PURE__ */ jsx("div", { className: "ra-confirm-backdrop", onClick: onClose }),
|
|
5363
|
+
/* @__PURE__ */ jsxs(
|
|
5364
|
+
"div",
|
|
5365
|
+
{
|
|
5366
|
+
role: "dialog",
|
|
5367
|
+
"aria-modal": "true",
|
|
5368
|
+
"aria-label": i18n?.searchProducts ?? "Search products",
|
|
5369
|
+
className: "ra-confirm-card",
|
|
5370
|
+
style: { width: "min(520px, 100%)", padding: "1rem" },
|
|
5371
|
+
children: [
|
|
5372
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
|
|
5373
|
+
/* @__PURE__ */ jsx(Search, { className: "w-4 h-4 opacity-60" }),
|
|
5374
|
+
/* @__PURE__ */ jsx(
|
|
5375
|
+
"input",
|
|
5376
|
+
{
|
|
5377
|
+
ref: inputRef,
|
|
5378
|
+
type: "text",
|
|
5379
|
+
value: search,
|
|
5380
|
+
onChange: (e) => setSearch(e.target.value),
|
|
5381
|
+
placeholder: i18n?.searchProducts ?? "Search products\u2026",
|
|
5382
|
+
className: "flex-1 text-sm px-2 py-1.5 rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
5383
|
+
style: {
|
|
5384
|
+
borderColor: "hsl(var(--ra-border))",
|
|
5385
|
+
color: "hsl(var(--ra-text))"
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5388
|
+
),
|
|
5389
|
+
/* @__PURE__ */ jsx(
|
|
5390
|
+
"button",
|
|
5391
|
+
{
|
|
5392
|
+
type: "button",
|
|
5393
|
+
onClick: onClose,
|
|
5394
|
+
className: "p-1 rounded-md hover:bg-[hsl(var(--ra-muted))]",
|
|
5395
|
+
"aria-label": i18n?.close ?? "Close",
|
|
5396
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
5397
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
5398
|
+
}
|
|
5399
|
+
)
|
|
5400
|
+
] }),
|
|
5401
|
+
/* @__PURE__ */ jsxs(
|
|
5402
|
+
"div",
|
|
5403
|
+
{
|
|
5404
|
+
className: "overflow-y-auto rounded-md border",
|
|
5405
|
+
style: {
|
|
5406
|
+
maxHeight: "50vh",
|
|
5407
|
+
borderColor: "hsl(var(--ra-border))"
|
|
5408
|
+
},
|
|
5409
|
+
children: [
|
|
5410
|
+
browse.isLoading && browse.items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-xs px-3 py-4 text-center", style: { color: "hsl(var(--ra-muted-text))" }, children: "Loading\u2026" }) : browse.items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-xs px-3 py-4 text-center", style: { color: "hsl(var(--ra-muted-text))" }, children: "No products match." }) : /* @__PURE__ */ jsx("ul", { className: "divide-y", style: { borderColor: "hsl(var(--ra-border))" }, children: browse.items.map((p) => {
|
|
5411
|
+
const active = p.id === currentProductId;
|
|
5412
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
5413
|
+
"button",
|
|
5414
|
+
{
|
|
5415
|
+
type: "button",
|
|
5416
|
+
onClick: () => onPick(p.id),
|
|
5417
|
+
className: "w-full text-left px-3 py-2 text-sm hover:bg-[hsl(var(--ra-muted))] flex items-center justify-between gap-3",
|
|
5418
|
+
style: {
|
|
5419
|
+
color: "hsl(var(--ra-text))",
|
|
5420
|
+
background: active ? "hsl(var(--ra-muted))" : "transparent"
|
|
5421
|
+
},
|
|
5422
|
+
children: [
|
|
5423
|
+
/* @__PURE__ */ jsxs("span", { className: "flex flex-col min-w-0", children: [
|
|
5424
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: p.name }),
|
|
5425
|
+
p.sku ? /* @__PURE__ */ jsx("span", { className: "truncate text-[11px]", style: { color: "hsl(var(--ra-muted-text))" }, children: p.sku }) : null
|
|
5426
|
+
] }),
|
|
5427
|
+
active ? /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide", style: { color: "hsl(var(--ra-muted-text))" }, children: "current" }) : null
|
|
5428
|
+
]
|
|
5429
|
+
}
|
|
5430
|
+
) }, p.id);
|
|
5431
|
+
}) }),
|
|
5432
|
+
browse.hasNextPage && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t", style: { borderColor: "hsl(var(--ra-border))" }, children: /* @__PURE__ */ jsx(
|
|
5433
|
+
"button",
|
|
5434
|
+
{
|
|
5435
|
+
type: "button",
|
|
5436
|
+
onClick: () => browse.fetchNextPage(),
|
|
5437
|
+
disabled: browse.isFetchingNextPage,
|
|
5438
|
+
className: "text-xs w-full py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5439
|
+
style: {
|
|
5440
|
+
borderColor: "hsl(var(--ra-border))",
|
|
5441
|
+
color: "hsl(var(--ra-text))"
|
|
5442
|
+
},
|
|
5443
|
+
children: browse.isFetchingNextPage ? "Loading\u2026" : "Load more"
|
|
5444
|
+
}
|
|
5445
|
+
) })
|
|
5446
|
+
]
|
|
5447
|
+
}
|
|
5448
|
+
)
|
|
5449
|
+
]
|
|
5450
|
+
}
|
|
5451
|
+
)
|
|
5452
|
+
]
|
|
5453
|
+
}
|
|
5454
|
+
),
|
|
5455
|
+
document.body
|
|
5456
|
+
);
|
|
5457
|
+
};
|
|
5113
5458
|
var ICONS2 = {
|
|
5114
5459
|
table: Table,
|
|
5115
5460
|
cards: LayoutGrid,
|
|
@@ -5309,6 +5654,7 @@ function ItemListView({
|
|
|
5309
5654
|
error,
|
|
5310
5655
|
ctx,
|
|
5311
5656
|
itemNoun,
|
|
5657
|
+
ruleSummary,
|
|
5312
5658
|
view,
|
|
5313
5659
|
views,
|
|
5314
5660
|
onViewChange,
|
|
@@ -5406,6 +5752,27 @@ function ItemListView({
|
|
|
5406
5752
|
}
|
|
5407
5753
|
return /* @__PURE__ */ jsxs("div", { className: "ra-item-list", children: [
|
|
5408
5754
|
toolbar,
|
|
5755
|
+
ruleSummary ? /* @__PURE__ */ jsxs(
|
|
5756
|
+
"div",
|
|
5757
|
+
{
|
|
5758
|
+
className: "ra-item-rule-summary",
|
|
5759
|
+
style: {
|
|
5760
|
+
padding: "6px 12px",
|
|
5761
|
+
fontSize: "11px",
|
|
5762
|
+
color: "hsl(var(--ra-muted-text))",
|
|
5763
|
+
borderBottom: "1px solid hsl(var(--ra-border))",
|
|
5764
|
+
background: "hsl(var(--ra-muted) / 0.4)",
|
|
5765
|
+
display: "flex",
|
|
5766
|
+
alignItems: "center",
|
|
5767
|
+
gap: "6px"
|
|
5768
|
+
},
|
|
5769
|
+
children: [
|
|
5770
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500, color: "hsl(var(--ra-text))" }, children: "Rule" }),
|
|
5771
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
5772
|
+
/* @__PURE__ */ jsx("span", { children: ruleSummary })
|
|
5773
|
+
]
|
|
5774
|
+
}
|
|
5775
|
+
) : null,
|
|
5409
5776
|
/* @__PURE__ */ jsx("div", { className: "ra-item-list-body", children: body })
|
|
5410
5777
|
] });
|
|
5411
5778
|
}
|
|
@@ -6730,6 +7097,19 @@ function RecordsAdminShell(props) {
|
|
|
6730
7097
|
{
|
|
6731
7098
|
ctx,
|
|
6732
7099
|
defaultValueFactory: props.defaultData,
|
|
7100
|
+
hooks: props.hooks,
|
|
7101
|
+
onHookNotice: (notice) => {
|
|
7102
|
+
console.warn(`[RecordsAdmin] ${notice.kind} hook failed`, notice.error);
|
|
7103
|
+
try {
|
|
7104
|
+
props.onTelemetry?.({
|
|
7105
|
+
type: "record.hook.error",
|
|
7106
|
+
recordType: props.recordType,
|
|
7107
|
+
kind: notice.kind,
|
|
7108
|
+
message: notice.error instanceof Error ? notice.error.message : String(notice.error)
|
|
7109
|
+
});
|
|
7110
|
+
} catch {
|
|
7111
|
+
}
|
|
7112
|
+
},
|
|
6733
7113
|
children: /* @__PURE__ */ jsx(RecordsAdminShellInner, { ...props })
|
|
6734
7114
|
}
|
|
6735
7115
|
);
|
|
@@ -6829,6 +7209,18 @@ function RecordsAdminShellInner(props) {
|
|
|
6829
7209
|
const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
|
|
6830
7210
|
const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
|
|
6831
7211
|
const deepLinkState = useDeepLinkState(deepLink);
|
|
7212
|
+
const deepLinkLoggedRef = useRef(false);
|
|
7213
|
+
if (!deepLinkLoggedRef.current) {
|
|
7214
|
+
deepLinkLoggedRef.current = true;
|
|
7215
|
+
console.debug("[RecordsAdminShell] deep-link config", {
|
|
7216
|
+
enabled: deepLinkState.enabled,
|
|
7217
|
+
hostPassedOption: !!deepLink,
|
|
7218
|
+
// Resolved adapter mode: 'host' = host-supplied, 'default' = built-in
|
|
7219
|
+
// (window.location standalone, postMessage inside the SmartLinks iframe).
|
|
7220
|
+
adapterMode: deepLink?.adapter ? "host" : "default",
|
|
7221
|
+
paramNames: deepLinkState.paramNames
|
|
7222
|
+
});
|
|
7223
|
+
}
|
|
6832
7224
|
const multiOpenWarnedRef = useRef(false);
|
|
6833
7225
|
if (editorTabs === "multi" && !multiOpenWarnedRef.current) {
|
|
6834
7226
|
multiOpenWarnedRef.current = true;
|
|
@@ -7059,7 +7451,18 @@ function RecordsAdminShellInner(props) {
|
|
|
7059
7451
|
setSelectedVariantId,
|
|
7060
7452
|
selectedBatchId,
|
|
7061
7453
|
setSelectedBatchId,
|
|
7062
|
-
setFacetBrowseFilter
|
|
7454
|
+
setFacetBrowseFilter,
|
|
7455
|
+
// Pending-recordId resolution — without these the URL's `recordId` is
|
|
7456
|
+
// parsed but never opens the editor on refresh / share-link load.
|
|
7457
|
+
isCollection,
|
|
7458
|
+
setSelectedItemId,
|
|
7459
|
+
collectionItems: {
|
|
7460
|
+
items: collectionItems.items,
|
|
7461
|
+
isLoading: collectionItems.isLoading
|
|
7462
|
+
},
|
|
7463
|
+
recordListItems: recordList.items,
|
|
7464
|
+
recordListLoading: recordList.isLoading,
|
|
7465
|
+
skipNextItemResetRef
|
|
7063
7466
|
});
|
|
7064
7467
|
const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
|
|
7065
7468
|
const resolved = useResolvedRecord({
|
|
@@ -7290,7 +7693,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7290
7693
|
deepLinkState,
|
|
7291
7694
|
onTelemetry,
|
|
7292
7695
|
onBeforeDelete,
|
|
7293
|
-
generateItemId
|
|
7696
|
+
generateItemId,
|
|
7697
|
+
hooks: props.hooks
|
|
7294
7698
|
});
|
|
7295
7699
|
const renderEditorWithPreview = () => {
|
|
7296
7700
|
if (!editingTargetScope) return null;
|
|
@@ -7305,6 +7709,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7305
7709
|
onChange: setPreviewScope,
|
|
7306
7710
|
showVariants: drillVariantsAllowed,
|
|
7307
7711
|
showBatches: drillBatchesAllowed,
|
|
7712
|
+
activeScope,
|
|
7308
7713
|
i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
|
|
7309
7714
|
}
|
|
7310
7715
|
) : null;
|
|
@@ -7497,12 +7902,13 @@ function RecordsAdminShellInner(props) {
|
|
|
7497
7902
|
if (groupBy) return groupBy;
|
|
7498
7903
|
if (isAllTab) return void 0;
|
|
7499
7904
|
if (!isRuleTab) return void 0;
|
|
7905
|
+
if (isCollection) return void 0;
|
|
7500
7906
|
return (record) => {
|
|
7501
7907
|
const hash = ruleHash(record.facetRule);
|
|
7502
7908
|
if (!hash) return null;
|
|
7503
7909
|
return { key: `rule:${hash}`, label: summariseRule(record.facetRule) };
|
|
7504
7910
|
};
|
|
7505
|
-
}, [groupBy, isRuleTab, isAllTab]);
|
|
7911
|
+
}, [groupBy, isRuleTab, isAllTab, isCollection]);
|
|
7506
7912
|
const [bulkRuleEditTarget, setBulkRuleEditTarget] = useState(null);
|
|
7507
7913
|
const ruleCatalogue = useMemo(() => {
|
|
7508
7914
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -7601,6 +8007,32 @@ function RecordsAdminShellInner(props) {
|
|
|
7601
8007
|
() => isRuleTab ? applyRuleFilters(recordList.items, ruleFilters) : recordList.items,
|
|
7602
8008
|
[isRuleTab, recordList.items, ruleFilters]
|
|
7603
8009
|
);
|
|
8010
|
+
const collectionRuleRailItems = useMemo(() => {
|
|
8011
|
+
if (!isRuleTab || !isCollection) return filteredRuleItems;
|
|
8012
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
8013
|
+
for (const item of filteredRuleItems) {
|
|
8014
|
+
const hash = ruleHash(item.facetRule);
|
|
8015
|
+
if (!hash) continue;
|
|
8016
|
+
const existing = buckets.get(hash);
|
|
8017
|
+
if (existing) {
|
|
8018
|
+
existing.count += 1;
|
|
8019
|
+
} else {
|
|
8020
|
+
buckets.set(hash, { rep: item, count: 1 });
|
|
8021
|
+
}
|
|
8022
|
+
}
|
|
8023
|
+
return Array.from(buckets.values()).map(({ rep, count }) => ({
|
|
8024
|
+
...rep,
|
|
8025
|
+
label: summariseRule(rep.facetRule),
|
|
8026
|
+
subtitle: `${count} ${itemNoun}${count === 1 ? "" : "s"}`
|
|
8027
|
+
}));
|
|
8028
|
+
}, [isRuleTab, isCollection, filteredRuleItems, itemNoun]);
|
|
8029
|
+
const activeRuleSummary = useMemo(() => {
|
|
8030
|
+
if (!isRuleTab || !isCollection) return null;
|
|
8031
|
+
if (!selectedRecordId || isDraftId3(selectedRecordId)) return null;
|
|
8032
|
+
const hit = recordList.items.find((it) => it.id === selectedRecordId);
|
|
8033
|
+
if (!hit?.facetRule) return null;
|
|
8034
|
+
return summariseRule(hit.facetRule);
|
|
8035
|
+
}, [isRuleTab, isCollection, selectedRecordId, recordList.items]);
|
|
7604
8036
|
const applyFacetBrowseFilter = useCallback(
|
|
7605
8037
|
(items2) => {
|
|
7606
8038
|
if (!facetBrowseFilter) return items2;
|
|
@@ -7648,7 +8080,9 @@ function RecordsAdminShellInner(props) {
|
|
|
7648
8080
|
}),
|
|
7649
8081
|
[i18n.itemsAllLabel, collectionItems.items.length, itemNoun]
|
|
7650
8082
|
);
|
|
7651
|
-
const leftItems = isProductTab ? productListItems : isRuleTab ? applyFacetBrowseFilter(
|
|
8083
|
+
const leftItems = isProductTab ? productListItems : isRuleTab ? applyFacetBrowseFilter(
|
|
8084
|
+
isCollection ? collectionRuleRailItems : filteredRuleItems
|
|
8085
|
+
) : (isGlobalTab || isAllTab) && isCollection ? [collectionGlobalAllRow] : isRecordsTab ? applyFacetBrowseFilter(recordList.items) : [];
|
|
7652
8086
|
const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : isRecordsTab ? recordList.isLoading || probe.isLoading : false;
|
|
7653
8087
|
const leftError = isProductTab ? productBrowse.error : isRecordsTab ? recordList.error : null;
|
|
7654
8088
|
const leftSelectedId = isProductTab ? void 0 : selectedRecordId && selectedRecordId !== DRAFT_ID3 ? selectedRecordId : void 0;
|
|
@@ -8089,6 +8523,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8089
8523
|
renderItemEmpty,
|
|
8090
8524
|
itemColumns,
|
|
8091
8525
|
cardSize: itemCardSize,
|
|
8526
|
+
ruleSummary: activeRuleSummary,
|
|
8092
8527
|
i18n
|
|
8093
8528
|
}
|
|
8094
8529
|
),
|
|
@@ -9008,6 +9443,9 @@ function useMergedRecord(args) {
|
|
|
9008
9443
|
};
|
|
9009
9444
|
}
|
|
9010
9445
|
|
|
9446
|
+
// src/components/RecordsAdmin/index.ts
|
|
9447
|
+
assertComponentStylesLoaded("records-admin");
|
|
9448
|
+
|
|
9011
9449
|
export { ALL_ITEM_VIEWS, ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_DEEP_LINK_PARAM_NAMES, DEFAULT_I18N, DEFAULT_ICONS, DefaultItemCards, DefaultItemTable, DefaultRecordCard, DefaultRecordRow, DeleteButton, DirtyDraftProvider, DrawerPreview, EditorItemNav, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, ItemListView, ItemViewSwitcher, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SiblingRail, SidePreview, StatusDot, StatusFilterPills, StatusIcon, TabbedPreview, UtilityRow, VariantList, buildDraftKey, buildRef, checkPasteCompatibility, cloneValue, createDefaultDeepLinkAdapter, createPostMessageDeepLinkAdapter, downloadBlob, exportCsv, importCsv, isInSmartLinksIframe, mergeIcons, normaliseRule, parseRef, pickHeaderIcon, resolutionChain, resolveRecord, ruleHash, rulesEqual, scopeCountsQueryKey, statusToneLabel, summariseRule, useCollectedRecords, useCollectionItems, useDeepLinkState, useDirtyDraft, useDirtyDraftActions, useDirtyDraftStore, useDirtyDrafts, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useItemViewPref, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeCounts, useScopeProbe, useUnsavedGuard };
|
|
9012
9450
|
//# sourceMappingURL=index.js.map
|
|
9013
9451
|
//# sourceMappingURL=index.js.map
|