@proveanything/smartlinks-utils-ui 0.9.2 → 0.9.4
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-KFKVGUUP.js → chunk-KA4MKRHL.js} +2 -4
- package/dist/chunk-KA4MKRHL.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 +2189 -3
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/AssetPicker/index.js +2 -1
- package/dist/components/ConditionsEditor/index.css +2189 -3
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +2189 -3
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +2189 -3
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +75 -30
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +33 -4
- package/dist/components/RecordsAdmin/index.js +475 -176
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +2189 -3
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -2
- package/dist/records-4NN757SG.js +3 -0
- package/dist/{records-AYYQSP7E.js.map → records-4NN757SG.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-CBIKDA3S.js.map +0 -1
- package/dist/chunk-KFKVGUUP.js.map +0 -1
- package/dist/records-AYYQSP7E.js +0 -3
|
@@ -1,11 +1,12 @@
|
|
|
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';
|
|
4
5
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
5
|
-
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-
|
|
6
|
-
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-
|
|
7
|
-
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,
|
|
6
|
+
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
7
|
+
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
8
|
+
import { createContext, useState, useEffect, useCallback, useMemo, useRef, useContext, useSyncExternalStore, useLayoutEffect, createElement, useId } from 'react';
|
|
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';
|
|
@@ -267,10 +268,12 @@ var ruleHash = (rule) => {
|
|
|
267
268
|
if (!norm) return null;
|
|
268
269
|
return fnv1a(JSON.stringify(norm));
|
|
269
270
|
};
|
|
270
|
-
var summariseRule = (rule) => {
|
|
271
|
+
var summariseRule = (rule, lookup) => {
|
|
271
272
|
const norm = normaliseRule(rule);
|
|
272
273
|
if (!norm) return "No rule";
|
|
273
|
-
|
|
274
|
+
const fLabel = (k) => lookup?.facetLabel?.(k) ?? k;
|
|
275
|
+
const vLabel = (k, v) => lookup?.valueLabel?.(k, v) ?? v;
|
|
276
|
+
return norm.all.map((c) => `${fLabel(c.facetKey)}: ${c.anyOf.map((v) => vLabel(c.facetKey, v)).join(", ")}`).join(" \xB7 ");
|
|
274
277
|
};
|
|
275
278
|
var rulesEqual = (a, b) => ruleHash(a) === ruleHash(b);
|
|
276
279
|
|
|
@@ -280,18 +283,6 @@ var resolveRecord = async (args) => {
|
|
|
280
283
|
const editingScope = parsedRefToScope(args.target);
|
|
281
284
|
const result = await matchRecords(args.ctx, target, { strategy: "all" }).catch(() => null);
|
|
282
285
|
const entries = result?.data ?? [];
|
|
283
|
-
console.info("[RecordsAdmin/resolveRecord]", {
|
|
284
|
-
editingScope,
|
|
285
|
-
target,
|
|
286
|
-
matchCount: entries.length,
|
|
287
|
-
winnerAnchors: entries[0] && {
|
|
288
|
-
productId: entries[0].productId,
|
|
289
|
-
variantId: entries[0].variantId,
|
|
290
|
-
batchId: entries[0].batchId,
|
|
291
|
-
proofId: entries[0].proofId
|
|
292
|
-
},
|
|
293
|
-
winnerRef: entries[0]?.ref
|
|
294
|
-
});
|
|
295
286
|
if (entries.length === 0) {
|
|
296
287
|
return { data: null, source: "empty" };
|
|
297
288
|
}
|
|
@@ -305,16 +296,6 @@ var resolveRecord = async (args) => {
|
|
|
305
296
|
},
|
|
306
297
|
editingScope
|
|
307
298
|
);
|
|
308
|
-
console.info("[RecordsAdmin/resolveRecord] classification", {
|
|
309
|
-
winnerIsSelf,
|
|
310
|
-
winnerAnchors: {
|
|
311
|
-
productId: winner.productId,
|
|
312
|
-
variantId: winner.variantId,
|
|
313
|
-
batchId: winner.batchId,
|
|
314
|
-
proofId: winner.proofId
|
|
315
|
-
},
|
|
316
|
-
editingScope
|
|
317
|
-
});
|
|
318
299
|
if (winnerIsSelf) {
|
|
319
300
|
const parent = entries[1];
|
|
320
301
|
return {
|
|
@@ -1833,11 +1814,6 @@ function useShellNavigation(args) {
|
|
|
1833
1814
|
const onItemOpen = useCallback((itemId) => {
|
|
1834
1815
|
if (!isCollection) return;
|
|
1835
1816
|
void runWithGuard(() => {
|
|
1836
|
-
console.info("[RecordsAdminShell] item open requested", {
|
|
1837
|
-
itemId,
|
|
1838
|
-
scopeRef: baseScopeRef,
|
|
1839
|
-
previousSelectedItemId: selectedItemId
|
|
1840
|
-
});
|
|
1841
1817
|
if (!isDraftId(itemId)) {
|
|
1842
1818
|
const row = collectionItems.items.find((it) => it.itemId === itemId || it.id === itemId);
|
|
1843
1819
|
if (row && row.data !== void 0) {
|
|
@@ -1938,7 +1914,7 @@ function useShellNavigation(args) {
|
|
|
1938
1914
|
}
|
|
1939
1915
|
}
|
|
1940
1916
|
try {
|
|
1941
|
-
const { removeRecord: removeRecord2 } = await import('../../records-
|
|
1917
|
+
const { removeRecord: removeRecord2 } = await import('../../records-4NN757SG.js');
|
|
1942
1918
|
await removeRecord2(ctx, itemId);
|
|
1943
1919
|
onTelemetry?.({ type: "item.delete", recordType, scopeRef: baseScopeRef, itemId });
|
|
1944
1920
|
if (selectedItemId === itemId) setSelectedItemId(null);
|
|
@@ -2113,16 +2089,30 @@ var useShellDeepLink = (args) => {
|
|
|
2113
2089
|
setSelectedVariantId,
|
|
2114
2090
|
selectedBatchId,
|
|
2115
2091
|
setSelectedBatchId,
|
|
2116
|
-
setFacetBrowseFilter
|
|
2092
|
+
setFacetBrowseFilter,
|
|
2093
|
+
isCollection,
|
|
2094
|
+
setSelectedItemId,
|
|
2095
|
+
collectionItems,
|
|
2096
|
+
recordListItems,
|
|
2097
|
+
recordListLoading,
|
|
2098
|
+
skipNextItemResetRef
|
|
2117
2099
|
} = args;
|
|
2118
2100
|
const lastAppliedDLRef = useRef("");
|
|
2119
2101
|
const [pendingDeepLinkRecordId, setPendingDeepLinkRecordId] = useState(null);
|
|
2102
|
+
const preserveInitialRecordIdRef = useRef(!!deepLinkState.urlState.recordId);
|
|
2103
|
+
const warnedMissingRef = useRef(/* @__PURE__ */ new Set());
|
|
2120
2104
|
useEffect(() => {
|
|
2121
2105
|
if (!deepLinkState.enabled) return;
|
|
2122
2106
|
if (selectedItemId) return;
|
|
2123
|
-
deepLinkState.
|
|
2124
|
-
|
|
2125
|
-
|
|
2107
|
+
const echoView = deepLinkState.urlState.view ?? "";
|
|
2108
|
+
const currentDeepLinkedRecordId = pendingDeepLinkRecordId ?? deepLinkState.urlState.recordId ?? null;
|
|
2109
|
+
const preservingPendingRecordId = preserveInitialRecordIdRef.current && !!currentDeepLinkedRecordId;
|
|
2110
|
+
deepLinkState.emit(
|
|
2111
|
+
preservingPendingRecordId ? { scope: editingScope?.raw ?? null } : { scope: editingScope?.raw ?? null, recordId: null },
|
|
2112
|
+
"scope"
|
|
2113
|
+
);
|
|
2114
|
+
lastAppliedDLRef.current = `${preservingPendingRecordId ? currentDeepLinkedRecordId ?? "" : ""}|${editingScope?.raw ?? ""}|${echoView}`;
|
|
2115
|
+
}, [deepLinkState.enabled, deepLinkState.urlState.recordId, editingScope?.raw, selectedItemId, itemView, pendingDeepLinkRecordId]);
|
|
2126
2116
|
useEffect(() => {
|
|
2127
2117
|
if (!deepLinkState.enabled) return;
|
|
2128
2118
|
const { recordId, scope, view } = deepLinkState.urlState;
|
|
@@ -2151,6 +2141,7 @@ var useShellDeepLink = (args) => {
|
|
|
2151
2141
|
if (selectedRecordId !== null) setSelectedRecordId(null);
|
|
2152
2142
|
}
|
|
2153
2143
|
setPendingDeepLinkRecordId(recordId ?? null);
|
|
2144
|
+
if (recordId) preserveInitialRecordIdRef.current = true;
|
|
2154
2145
|
if (!recordId && selectedItemId !== null) {
|
|
2155
2146
|
console.info("[RecordsAdminShell] preserving selected item during restore without recordId", {
|
|
2156
2147
|
selectedItemId,
|
|
@@ -2159,6 +2150,57 @@ var useShellDeepLink = (args) => {
|
|
|
2159
2150
|
});
|
|
2160
2151
|
}
|
|
2161
2152
|
}, [deepLinkState.enabled, deepLinkState.urlState]);
|
|
2153
|
+
useEffect(() => {
|
|
2154
|
+
const pending = pendingDeepLinkRecordId;
|
|
2155
|
+
if (!pending) return;
|
|
2156
|
+
if (isCollection) {
|
|
2157
|
+
const hit2 = collectionItems.items.find((it) => it.id === pending || it.itemId === pending);
|
|
2158
|
+
if (hit2) {
|
|
2159
|
+
skipNextItemResetRef.current = true;
|
|
2160
|
+
setSelectedItemId(pending);
|
|
2161
|
+
preserveInitialRecordIdRef.current = false;
|
|
2162
|
+
setPendingDeepLinkRecordId(null);
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2165
|
+
if (!collectionItems.isLoading) {
|
|
2166
|
+
if (!warnedMissingRef.current.has(pending)) {
|
|
2167
|
+
warnedMissingRef.current.add(pending);
|
|
2168
|
+
console.warn("[RecordsAdminShell] deep-linked recordId not found in collection items \u2014 clearing pending selection", {
|
|
2169
|
+
recordId: pending,
|
|
2170
|
+
scope: editingScope?.raw ?? null
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
preserveInitialRecordIdRef.current = false;
|
|
2174
|
+
setPendingDeepLinkRecordId(null);
|
|
2175
|
+
}
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
const hit = recordListItems.find((it) => it.id === pending);
|
|
2179
|
+
if (hit) {
|
|
2180
|
+
if (selectedRecordId !== pending) setSelectedRecordId(pending);
|
|
2181
|
+
preserveInitialRecordIdRef.current = false;
|
|
2182
|
+
setPendingDeepLinkRecordId(null);
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
if (!recordListLoading) {
|
|
2186
|
+
if (!warnedMissingRef.current.has(pending)) {
|
|
2187
|
+
warnedMissingRef.current.add(pending);
|
|
2188
|
+
console.warn("[RecordsAdminShell] deep-linked recordId not found in records list \u2014 clearing pending selection", {
|
|
2189
|
+
recordId: pending,
|
|
2190
|
+
scope: editingScope?.raw ?? null
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
2193
|
+
preserveInitialRecordIdRef.current = false;
|
|
2194
|
+
setPendingDeepLinkRecordId(null);
|
|
2195
|
+
}
|
|
2196
|
+
}, [
|
|
2197
|
+
pendingDeepLinkRecordId,
|
|
2198
|
+
isCollection,
|
|
2199
|
+
collectionItems.items,
|
|
2200
|
+
collectionItems.isLoading,
|
|
2201
|
+
recordListItems,
|
|
2202
|
+
recordListLoading
|
|
2203
|
+
]);
|
|
2162
2204
|
return { pendingDeepLinkRecordId, lastAppliedDLRef };
|
|
2163
2205
|
};
|
|
2164
2206
|
var isFacetRuleValid = (rule) => {
|
|
@@ -3196,10 +3238,16 @@ var RowContextMenu = ({
|
|
|
3196
3238
|
}) => {
|
|
3197
3239
|
const [open, setOpen] = useState(false);
|
|
3198
3240
|
const wrapperRef = useRef(null);
|
|
3241
|
+
const triggerRef = useRef(null);
|
|
3242
|
+
const menuRef = useRef(null);
|
|
3243
|
+
const [pos, setPos] = useState(null);
|
|
3199
3244
|
useEffect(() => {
|
|
3200
3245
|
if (!open) return;
|
|
3201
3246
|
const onDoc = (e) => {
|
|
3202
|
-
|
|
3247
|
+
const t = e.target;
|
|
3248
|
+
if (wrapperRef.current?.contains(t)) return;
|
|
3249
|
+
if (menuRef.current?.contains(t)) return;
|
|
3250
|
+
setOpen(false);
|
|
3203
3251
|
};
|
|
3204
3252
|
const onKey = (e) => {
|
|
3205
3253
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -3211,12 +3259,36 @@ var RowContextMenu = ({
|
|
|
3211
3259
|
document.removeEventListener("keydown", onKey);
|
|
3212
3260
|
};
|
|
3213
3261
|
}, [open]);
|
|
3262
|
+
useLayoutEffect(() => {
|
|
3263
|
+
if (!open) {
|
|
3264
|
+
setPos(null);
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
const update = () => {
|
|
3268
|
+
const el = triggerRef.current;
|
|
3269
|
+
if (!el) return;
|
|
3270
|
+
const r = el.getBoundingClientRect();
|
|
3271
|
+
const menuWidth = menuRef.current?.offsetWidth ?? 176;
|
|
3272
|
+
const margin = 8;
|
|
3273
|
+
const left = Math.max(margin, Math.min(window.innerWidth - menuWidth - margin, r.right - menuWidth));
|
|
3274
|
+
const top = r.bottom + 4;
|
|
3275
|
+
setPos({ top, left });
|
|
3276
|
+
};
|
|
3277
|
+
update();
|
|
3278
|
+
window.addEventListener("resize", update);
|
|
3279
|
+
window.addEventListener("scroll", update, true);
|
|
3280
|
+
return () => {
|
|
3281
|
+
window.removeEventListener("resize", update);
|
|
3282
|
+
window.removeEventListener("scroll", update, true);
|
|
3283
|
+
};
|
|
3284
|
+
}, [open]);
|
|
3214
3285
|
if (!onCopy && !onPaste) return null;
|
|
3215
3286
|
const pasteLabel = !canPaste ? i18n.clipboardEmpty : pasteSourceLabel ? i18n.pasteFrom.replace("{name}", pasteSourceLabel) : pasteWillReplace ? i18n.pasteReplace : i18n.paste;
|
|
3216
3287
|
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: "ra-row-menu-wrap relative", children: [
|
|
3217
3288
|
/* @__PURE__ */ jsx(
|
|
3218
3289
|
"button",
|
|
3219
3290
|
{
|
|
3291
|
+
ref: triggerRef,
|
|
3220
3292
|
type: "button",
|
|
3221
3293
|
className: "ra-row-menu-trigger",
|
|
3222
3294
|
"aria-label": "Row actions",
|
|
@@ -3229,75 +3301,106 @@ var RowContextMenu = ({
|
|
|
3229
3301
|
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "w-3.5 h-3.5", "aria-hidden": "true" })
|
|
3230
3302
|
}
|
|
3231
3303
|
),
|
|
3232
|
-
open &&
|
|
3233
|
-
|
|
3234
|
-
"
|
|
3304
|
+
open && typeof document !== "undefined" && createPortal(
|
|
3305
|
+
/* @__PURE__ */ jsxs(
|
|
3306
|
+
"div",
|
|
3235
3307
|
{
|
|
3236
|
-
|
|
3237
|
-
role: "
|
|
3238
|
-
className: "ra-row-menu-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
onCopy();
|
|
3243
|
-
},
|
|
3308
|
+
ref: menuRef,
|
|
3309
|
+
role: "menu",
|
|
3310
|
+
className: "ra-row-menu ra-row-menu-portal",
|
|
3311
|
+
style: pos ? { top: pos.top, left: pos.left } : { visibility: "hidden" },
|
|
3312
|
+
onClick: (e) => e.stopPropagation(),
|
|
3313
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
3244
3314
|
children: [
|
|
3245
|
-
/* @__PURE__ */
|
|
3246
|
-
|
|
3315
|
+
onCopy && /* @__PURE__ */ jsxs(
|
|
3316
|
+
"button",
|
|
3317
|
+
{
|
|
3318
|
+
type: "button",
|
|
3319
|
+
role: "menuitem",
|
|
3320
|
+
className: "ra-row-menu-item",
|
|
3321
|
+
onClick: (e) => {
|
|
3322
|
+
e.stopPropagation();
|
|
3323
|
+
setOpen(false);
|
|
3324
|
+
onCopy();
|
|
3325
|
+
},
|
|
3326
|
+
children: [
|
|
3327
|
+
/* @__PURE__ */ jsx(Copy, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
3328
|
+
/* @__PURE__ */ jsx("span", { children: i18n.copy })
|
|
3329
|
+
]
|
|
3330
|
+
}
|
|
3331
|
+
),
|
|
3332
|
+
onPaste && /* @__PURE__ */ jsxs(
|
|
3333
|
+
"button",
|
|
3334
|
+
{
|
|
3335
|
+
type: "button",
|
|
3336
|
+
role: "menuitem",
|
|
3337
|
+
className: "ra-row-menu-item",
|
|
3338
|
+
disabled: !canPaste,
|
|
3339
|
+
onClick: (e) => {
|
|
3340
|
+
e.stopPropagation();
|
|
3341
|
+
setOpen(false);
|
|
3342
|
+
if (canPaste) onPaste();
|
|
3343
|
+
},
|
|
3344
|
+
children: [
|
|
3345
|
+
/* @__PURE__ */ jsx(ClipboardPaste, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
3346
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: pasteLabel })
|
|
3347
|
+
]
|
|
3348
|
+
}
|
|
3349
|
+
)
|
|
3247
3350
|
]
|
|
3248
3351
|
}
|
|
3249
3352
|
),
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
{
|
|
3253
|
-
type: "button",
|
|
3254
|
-
role: "menuitem",
|
|
3255
|
-
className: "ra-row-menu-item",
|
|
3256
|
-
disabled: !canPaste,
|
|
3257
|
-
onClick: (e) => {
|
|
3258
|
-
e.stopPropagation();
|
|
3259
|
-
setOpen(false);
|
|
3260
|
-
if (canPaste) onPaste();
|
|
3261
|
-
},
|
|
3262
|
-
children: [
|
|
3263
|
-
/* @__PURE__ */ jsx(ClipboardPaste, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
3264
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: pasteLabel })
|
|
3265
|
-
]
|
|
3266
|
-
}
|
|
3267
|
-
)
|
|
3268
|
-
] })
|
|
3353
|
+
document.body
|
|
3354
|
+
)
|
|
3269
3355
|
] });
|
|
3270
3356
|
};
|
|
3271
3357
|
|
|
3272
3358
|
// src/components/RecordsAdmin/browser/formatFacetRule.ts
|
|
3273
|
-
function formatFacetRule(rule) {
|
|
3359
|
+
function formatFacetRule(rule, lookup) {
|
|
3274
3360
|
if (!rule || !rule.all || rule.all.length === 0) return null;
|
|
3361
|
+
const fLabel = (k) => lookup?.facetLabel?.(k) ?? k;
|
|
3362
|
+
const vLabel = (k, v) => lookup?.valueLabel?.(k, v) ?? v;
|
|
3275
3363
|
const parts = rule.all.map((c) => {
|
|
3276
3364
|
const vals = (c.anyOf ?? []).filter(Boolean);
|
|
3277
|
-
|
|
3278
|
-
if (vals.length ===
|
|
3279
|
-
return `${
|
|
3365
|
+
const fk = fLabel(c.facetKey);
|
|
3366
|
+
if (vals.length === 0) return `${fk} (no values)`;
|
|
3367
|
+
if (vals.length === 1) return `${fk} = ${vLabel(c.facetKey, vals[0])}`;
|
|
3368
|
+
return `${fk} \u2208 {${vals.map((v) => vLabel(c.facetKey, v)).join(", ")}}`;
|
|
3280
3369
|
});
|
|
3281
3370
|
return parts.join(" AND ");
|
|
3282
3371
|
}
|
|
3283
|
-
function summarizeFacetRule(rule) {
|
|
3372
|
+
function summarizeFacetRule(rule, lookup) {
|
|
3284
3373
|
if (!rule || !rule.all || rule.all.length === 0) return [];
|
|
3374
|
+
const fLabel = (k) => lookup?.facetLabel?.(k) ?? k;
|
|
3375
|
+
const vLabel = (k, v) => lookup?.valueLabel?.(k, v) ?? v;
|
|
3285
3376
|
return rule.all.map((c) => {
|
|
3286
|
-
const
|
|
3377
|
+
const rawValues = (c.anyOf ?? []).filter(Boolean);
|
|
3378
|
+
const values = rawValues.map((v) => vLabel(c.facetKey, v));
|
|
3379
|
+
const fk = fLabel(c.facetKey);
|
|
3287
3380
|
let label;
|
|
3288
|
-
if (values.length === 0) label = `${
|
|
3289
|
-
else if (values.length === 1) label = `${
|
|
3290
|
-
else if (values.length <= 3) label = `${
|
|
3291
|
-
else label = `${
|
|
3381
|
+
if (values.length === 0) label = `${fk}: \u2014`;
|
|
3382
|
+
else if (values.length === 1) label = `${fk}: ${values[0]}`;
|
|
3383
|
+
else if (values.length <= 3) label = `${fk}: ${values.join(", ")}`;
|
|
3384
|
+
else label = `${fk}: ${values.slice(0, 2).join(", ")} +${values.length - 2}`;
|
|
3292
3385
|
return { facetKey: c.facetKey, values, label };
|
|
3293
3386
|
});
|
|
3294
3387
|
}
|
|
3388
|
+
var RuleLabelLookupContext = createContext(null);
|
|
3389
|
+
var useRuleLabelLookup = () => useContext(RuleLabelLookupContext) ?? void 0;
|
|
3390
|
+
var RuleLabelLookupProvider = ({
|
|
3391
|
+
value,
|
|
3392
|
+
children
|
|
3393
|
+
}) => {
|
|
3394
|
+
const v = useMemo(() => value, [value]);
|
|
3395
|
+
return /* @__PURE__ */ jsx(RuleLabelLookupContext.Provider, { value: v, children });
|
|
3396
|
+
};
|
|
3295
3397
|
var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
3296
3398
|
const { selected, onSelect, isDirty, hasError, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
|
|
3399
|
+
const ruleLabelLookup = useRuleLabelLookup();
|
|
3297
3400
|
const ScopeIcon = record.scope.kind && record.scope.kind !== "collection" ? DEFAULT_ICONS.scope[record.scope.kind] : DEFAULT_ICONS.scope.product;
|
|
3298
3401
|
const tone = resolveTone(void 0, record.status);
|
|
3299
|
-
const ruleSummary = formatFacetRule(record.facetRule);
|
|
3300
|
-
const ruleClauses = summarizeFacetRule(record.facetRule);
|
|
3402
|
+
const ruleSummary = formatFacetRule(record.facetRule, ruleLabelLookup);
|
|
3403
|
+
const ruleClauses = summarizeFacetRule(record.facetRule, ruleLabelLookup);
|
|
3301
3404
|
const isRuleRecord = ruleClauses.length > 0;
|
|
3302
3405
|
const i18n = ctx.i18n ?? DEFAULT_I18N;
|
|
3303
3406
|
const subtitle = record.subtitle ?? (isRuleRecord ? null : ruleSummary) ?? (tone === "missing" ? i18n.subtitleEmpty : tone === "own" ? i18n.subtitleConfigured : i18n.subtitleInherited);
|
|
@@ -3338,9 +3441,9 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
3338
3441
|
!compact && !isRuleRecord && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: subtitle })
|
|
3339
3442
|
] }),
|
|
3340
3443
|
compact && /* @__PURE__ */ jsx(StatusIcon, { status: record.status, size: "0.85rem" }),
|
|
3341
|
-
!compact && record.scope.kind && record.scope.kind !== "collection" && /* @__PURE__ */ jsx("span", { className: "ra-row-scope", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ScopeIcon, { className: "w-3 h-3" }) }),
|
|
3444
|
+
!compact && record.scope.kind && record.scope.kind !== "collection" && record.scope.kind !== "rule" && /* @__PURE__ */ jsx("span", { className: "ra-row-scope", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ScopeIcon, { className: "w-3 h-3" }) }),
|
|
3342
3445
|
record.badges?.slice(0, 1).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)),
|
|
3343
|
-
record.facetRule && !compact && /* @__PURE__ */ jsx(
|
|
3446
|
+
record.facetRule && !compact && !isRuleRecord && /* @__PURE__ */ jsx(
|
|
3344
3447
|
"span",
|
|
3345
3448
|
{
|
|
3346
3449
|
className: "ra-row-rule-pip",
|
|
@@ -3848,15 +3951,19 @@ function useCollectionItems(args) {
|
|
|
3848
3951
|
|
|
3849
3952
|
// src/components/RecordsAdmin/data/deepLinkAdapter.ts
|
|
3850
3953
|
var findQueryHost = (loc) => {
|
|
3851
|
-
if (loc.
|
|
3954
|
+
if (loc.hash && loc.hash.startsWith("#/")) return "hash";
|
|
3852
3955
|
if (loc.hash && loc.hash.includes("?")) return "hash";
|
|
3956
|
+
if (loc.search && loc.search.length > 1) return "search";
|
|
3853
3957
|
return "search";
|
|
3854
3958
|
};
|
|
3855
|
-
var
|
|
3856
|
-
|
|
3857
|
-
if (host === "search") return loc.search.startsWith("?") ? loc.search.slice(1) : loc.search;
|
|
3959
|
+
var getSearchParams = (loc) => new URLSearchParams(loc.search.startsWith("?") ? loc.search.slice(1) : loc.search);
|
|
3960
|
+
var getHashParams = (loc) => {
|
|
3858
3961
|
const idx = loc.hash.indexOf("?");
|
|
3859
|
-
return idx >= 0 ? loc.hash.slice(idx + 1) : "";
|
|
3962
|
+
return new URLSearchParams(idx >= 0 ? loc.hash.slice(idx + 1) : "");
|
|
3963
|
+
};
|
|
3964
|
+
var getReadParams = (loc) => {
|
|
3965
|
+
if (loc.hash && loc.hash.includes("?")) return getHashParams(loc);
|
|
3966
|
+
return getSearchParams(loc);
|
|
3860
3967
|
};
|
|
3861
3968
|
var buildUrl = (loc, nextQuery) => {
|
|
3862
3969
|
const host = findQueryHost(loc);
|
|
@@ -3870,7 +3977,7 @@ var buildUrl = (loc, nextQuery) => {
|
|
|
3870
3977
|
var createDefaultDeepLinkAdapter = (paramNames) => ({
|
|
3871
3978
|
read() {
|
|
3872
3979
|
if (typeof window === "undefined") return {};
|
|
3873
|
-
const params =
|
|
3980
|
+
const params = getReadParams(window.location);
|
|
3874
3981
|
return {
|
|
3875
3982
|
recordId: params.get(paramNames.recordId),
|
|
3876
3983
|
scope: params.get(paramNames.scope),
|
|
@@ -3879,7 +3986,7 @@ var createDefaultDeepLinkAdapter = (paramNames) => ({
|
|
|
3879
3986
|
},
|
|
3880
3987
|
write(partial, mode) {
|
|
3881
3988
|
if (typeof window === "undefined") return;
|
|
3882
|
-
const params =
|
|
3989
|
+
const params = findQueryHost(window.location) === "hash" ? getHashParams(window.location) : getSearchParams(window.location);
|
|
3883
3990
|
const apply = (key, value) => {
|
|
3884
3991
|
if (value == null || value === "") params.delete(key);
|
|
3885
3992
|
else params.set(key, value);
|
|
@@ -3913,14 +4020,22 @@ var CONTEXT_KEYS = [
|
|
|
3913
4020
|
"lang",
|
|
3914
4021
|
"theme"
|
|
3915
4022
|
];
|
|
3916
|
-
var
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
return
|
|
4023
|
+
var getSearchParams2 = (loc) => new URLSearchParams(loc.search.startsWith("?") ? loc.search.slice(1) : loc.search);
|
|
4024
|
+
var getHashParams2 = (loc) => {
|
|
4025
|
+
const idx = loc.hash.indexOf("?");
|
|
4026
|
+
return new URLSearchParams(idx >= 0 ? loc.hash.slice(idx + 1) : "");
|
|
4027
|
+
};
|
|
4028
|
+
var getReadParams2 = (loc) => {
|
|
4029
|
+
if (loc.hash && loc.hash.includes("?")) return getHashParams2(loc);
|
|
4030
|
+
return getSearchParams2(loc);
|
|
4031
|
+
};
|
|
4032
|
+
var getMergedParams = (loc) => {
|
|
4033
|
+
const merged = getSearchParams2(loc);
|
|
4034
|
+
const hashParams = getHashParams2(loc);
|
|
4035
|
+
hashParams.forEach((value, key) => {
|
|
4036
|
+
merged.set(key, value);
|
|
4037
|
+
});
|
|
4038
|
+
return merged;
|
|
3924
4039
|
};
|
|
3925
4040
|
var findPath = (loc) => {
|
|
3926
4041
|
if (loc.hash && loc.hash.startsWith("#")) {
|
|
@@ -3943,7 +4058,7 @@ var createPostMessageDeepLinkAdapter = (paramNames) => {
|
|
|
3943
4058
|
const lastShellState = {};
|
|
3944
4059
|
const post = (path) => {
|
|
3945
4060
|
if (typeof window === "undefined") return;
|
|
3946
|
-
const params =
|
|
4061
|
+
const params = getMergedParams(window.location);
|
|
3947
4062
|
const context = {};
|
|
3948
4063
|
const state = {};
|
|
3949
4064
|
params.forEach((value, key) => {
|
|
@@ -3967,9 +4082,6 @@ var createPostMessageDeepLinkAdapter = (paramNames) => {
|
|
|
3967
4082
|
state,
|
|
3968
4083
|
appId: context.appId
|
|
3969
4084
|
};
|
|
3970
|
-
console.debug("[smartlinks-ui] postMessage \u2192 parent", message, {
|
|
3971
|
-
sameWindow: window.parent === window
|
|
3972
|
-
});
|
|
3973
4085
|
window.parent.postMessage(message, "*");
|
|
3974
4086
|
} catch {
|
|
3975
4087
|
}
|
|
@@ -3977,7 +4089,7 @@ var createPostMessageDeepLinkAdapter = (paramNames) => {
|
|
|
3977
4089
|
return {
|
|
3978
4090
|
read() {
|
|
3979
4091
|
if (typeof window === "undefined") return {};
|
|
3980
|
-
const params =
|
|
4092
|
+
const params = getReadParams2(window.location);
|
|
3981
4093
|
return {
|
|
3982
4094
|
recordId: params.get(paramNames.recordId),
|
|
3983
4095
|
scope: params.get(paramNames.scope),
|
|
@@ -4012,7 +4124,7 @@ var classify2 = (mode, kind) => {
|
|
|
4012
4124
|
return SMART_PUSH.includes(kind) ? "push" : "replace";
|
|
4013
4125
|
};
|
|
4014
4126
|
function useDeepLinkState(options) {
|
|
4015
|
-
const enabled =
|
|
4127
|
+
const enabled = options?.enabled !== false;
|
|
4016
4128
|
const history = options?.history ?? "smart";
|
|
4017
4129
|
const paramNames = useMemo(() => ({
|
|
4018
4130
|
...DEFAULT_DEEP_LINK_PARAM_NAMES,
|
|
@@ -4024,11 +4136,6 @@ function useDeepLinkState(options) {
|
|
|
4024
4136
|
if (options?.adapter) return options.adapter;
|
|
4025
4137
|
if (!defaultAdapterRef.current) {
|
|
4026
4138
|
const inIframe = isInSmartLinksIframe();
|
|
4027
|
-
console.debug("[smartlinks-ui] deep-link adapter selected", {
|
|
4028
|
-
adapter: inIframe ? "postMessage" : "default",
|
|
4029
|
-
inIframe,
|
|
4030
|
-
href: typeof window !== "undefined" ? window.location.href : "(ssr)"
|
|
4031
|
-
});
|
|
4032
4139
|
defaultAdapterRef.current = inIframe ? createPostMessageDeepLinkAdapter(paramNames) : createDefaultDeepLinkAdapter(paramNames);
|
|
4033
4140
|
}
|
|
4034
4141
|
return defaultAdapterRef.current;
|
|
@@ -4042,7 +4149,9 @@ function useDeepLinkState(options) {
|
|
|
4042
4149
|
return adapter.subscribe(() => setUrlState(adapter.read()));
|
|
4043
4150
|
}, [adapter]);
|
|
4044
4151
|
const emit = useCallback((partial, kind) => {
|
|
4045
|
-
if (!adapter)
|
|
4152
|
+
if (!adapter) {
|
|
4153
|
+
return;
|
|
4154
|
+
}
|
|
4046
4155
|
const mode = classify2(history, kind);
|
|
4047
4156
|
adapter.write(partial, mode);
|
|
4048
4157
|
setUrlState((prev) => ({ ...prev, ...partial }));
|
|
@@ -5101,14 +5210,16 @@ var PreviewScopePicker = ({
|
|
|
5101
5210
|
onChange,
|
|
5102
5211
|
showVariants,
|
|
5103
5212
|
showBatches,
|
|
5213
|
+
activeScope,
|
|
5104
5214
|
i18n
|
|
5105
5215
|
}) => {
|
|
5106
5216
|
const productPinned = !!editingScope.productId;
|
|
5217
|
+
const hideForTab = activeScope === "product" || activeScope === "variant" || activeScope === "batch";
|
|
5107
5218
|
const products = useProductBrowse({
|
|
5108
5219
|
SL,
|
|
5109
5220
|
collectionId,
|
|
5110
5221
|
pageSize: 100,
|
|
5111
|
-
enabled: !productPinned
|
|
5222
|
+
enabled: !productPinned && !hideForTab
|
|
5112
5223
|
});
|
|
5113
5224
|
const variants = useProductChildren({
|
|
5114
5225
|
SL,
|
|
@@ -5122,11 +5233,8 @@ var PreviewScopePicker = ({
|
|
|
5122
5233
|
productId: value.productId,
|
|
5123
5234
|
kind: showBatches ? "batch" : null
|
|
5124
5235
|
});
|
|
5125
|
-
const isDefault = useMemo(
|
|
5126
|
-
() => value.raw === editingScope.raw,
|
|
5127
|
-
[value.raw, editingScope.raw]
|
|
5128
|
-
);
|
|
5129
5236
|
useEffect(() => {
|
|
5237
|
+
if (hideForTab) return;
|
|
5130
5238
|
if (productPinned) return;
|
|
5131
5239
|
if (value.productId) return;
|
|
5132
5240
|
const first = products.items[0];
|
|
@@ -5138,9 +5246,10 @@ var PreviewScopePicker = ({
|
|
|
5138
5246
|
batchId: void 0,
|
|
5139
5247
|
raw: `product:${first.id}`
|
|
5140
5248
|
});
|
|
5141
|
-
}, [productPinned, value.productId, products.items]);
|
|
5142
|
-
const [
|
|
5143
|
-
|
|
5249
|
+
}, [hideForTab, productPinned, value.productId, products.items]);
|
|
5250
|
+
const [lightboxOpen, setLightboxOpen] = useState(false);
|
|
5251
|
+
if (hideForTab) return null;
|
|
5252
|
+
const showProductPicker = !productPinned;
|
|
5144
5253
|
const showVariantPicker = showVariants && !!value.productId && variants.items.length > 0;
|
|
5145
5254
|
const showBatchPicker = showBatches && !!value.productId && batches.items.length > 0;
|
|
5146
5255
|
if (!showProductPicker && !showVariantPicker && !showBatchPicker) {
|
|
@@ -5151,6 +5260,16 @@ var PreviewScopePicker = ({
|
|
|
5151
5260
|
borderColor: "hsl(var(--ra-border))",
|
|
5152
5261
|
color: "hsl(var(--ra-text))"
|
|
5153
5262
|
};
|
|
5263
|
+
const pickProduct = (productId) => {
|
|
5264
|
+
onChange({
|
|
5265
|
+
...value,
|
|
5266
|
+
productId,
|
|
5267
|
+
variantId: void 0,
|
|
5268
|
+
batchId: void 0,
|
|
5269
|
+
raw: `product:${productId}`
|
|
5270
|
+
});
|
|
5271
|
+
setLightboxOpen(false);
|
|
5272
|
+
};
|
|
5154
5273
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
5155
5274
|
/* @__PURE__ */ jsxs(
|
|
5156
5275
|
"span",
|
|
@@ -5163,56 +5282,27 @@ var PreviewScopePicker = ({
|
|
|
5163
5282
|
]
|
|
5164
5283
|
}
|
|
5165
5284
|
),
|
|
5166
|
-
|
|
5167
|
-
"
|
|
5168
|
-
{
|
|
5169
|
-
type: "button",
|
|
5170
|
-
onClick: () => onChange(editingScope),
|
|
5171
|
-
className: "text-[10px] px-2 py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5172
|
-
style: selectStyle,
|
|
5173
|
-
children: [
|
|
5174
|
-
"\u21BA ",
|
|
5175
|
-
i18n?.previewAsDefault ?? "Same as edited"
|
|
5176
|
-
]
|
|
5177
|
-
}
|
|
5178
|
-
),
|
|
5179
|
-
showProductPicker && !productPickerOpen && currentProductName && /* @__PURE__ */ jsxs(
|
|
5180
|
-
"button",
|
|
5285
|
+
showProductPicker && /* @__PURE__ */ jsxs(
|
|
5286
|
+
"span",
|
|
5181
5287
|
{
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
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",
|
|
5185
|
-
style: selectStyle,
|
|
5186
|
-
title: `Preview as ${currentProductName} \u2014 click to change`,
|
|
5288
|
+
className: "inline-flex items-center gap-1.5 text-[11px] truncate max-w-[18rem]",
|
|
5289
|
+
style: { color: "hsl(var(--ra-text))" },
|
|
5187
5290
|
children: [
|
|
5188
|
-
"
|
|
5189
|
-
/* @__PURE__ */ jsx(
|
|
5190
|
-
|
|
5291
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate", title: currentProductName, children: currentProductName || "\u2014" }),
|
|
5292
|
+
/* @__PURE__ */ jsx(
|
|
5293
|
+
"button",
|
|
5294
|
+
{
|
|
5295
|
+
type: "button",
|
|
5296
|
+
onClick: () => setLightboxOpen(true),
|
|
5297
|
+
className: "text-[10px] px-1.5 py-0.5 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5298
|
+
style: selectStyle,
|
|
5299
|
+
title: i18n?.change ?? "Change preview product",
|
|
5300
|
+
children: i18n?.change ?? "Change"
|
|
5301
|
+
}
|
|
5302
|
+
)
|
|
5191
5303
|
]
|
|
5192
5304
|
}
|
|
5193
5305
|
),
|
|
5194
|
-
showProductPicker && productPickerOpen && /* @__PURE__ */ jsx(
|
|
5195
|
-
"select",
|
|
5196
|
-
{
|
|
5197
|
-
className: SELECT_CLS,
|
|
5198
|
-
style: selectStyle,
|
|
5199
|
-
autoFocus: true,
|
|
5200
|
-
onBlur: () => setProductPickerOpen(false),
|
|
5201
|
-
value: value.productId ?? "",
|
|
5202
|
-
onChange: (e) => {
|
|
5203
|
-
const productId = e.target.value || void 0;
|
|
5204
|
-
onChange({
|
|
5205
|
-
...value,
|
|
5206
|
-
productId,
|
|
5207
|
-
variantId: void 0,
|
|
5208
|
-
batchId: void 0,
|
|
5209
|
-
raw: productId ? `product:${productId}` : ""
|
|
5210
|
-
});
|
|
5211
|
-
setProductPickerOpen(false);
|
|
5212
|
-
},
|
|
5213
|
-
children: products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
|
|
5214
|
-
}
|
|
5215
|
-
),
|
|
5216
5306
|
showVariantPicker && /* @__PURE__ */ jsxs(
|
|
5217
5307
|
"select",
|
|
5218
5308
|
{
|
|
@@ -5253,9 +5343,161 @@ var PreviewScopePicker = ({
|
|
|
5253
5343
|
batches.items.map((b) => /* @__PURE__ */ jsx("option", { value: b.id, children: b.name }, b.id))
|
|
5254
5344
|
]
|
|
5255
5345
|
}
|
|
5346
|
+
),
|
|
5347
|
+
lightboxOpen && /* @__PURE__ */ jsx(
|
|
5348
|
+
ProductPickerLightbox,
|
|
5349
|
+
{
|
|
5350
|
+
SL,
|
|
5351
|
+
collectionId,
|
|
5352
|
+
currentProductId: value.productId,
|
|
5353
|
+
onPick: pickProduct,
|
|
5354
|
+
onClose: () => setLightboxOpen(false),
|
|
5355
|
+
i18n
|
|
5356
|
+
}
|
|
5256
5357
|
)
|
|
5257
5358
|
] });
|
|
5258
5359
|
};
|
|
5360
|
+
var ProductPickerLightbox = ({
|
|
5361
|
+
SL,
|
|
5362
|
+
collectionId,
|
|
5363
|
+
currentProductId,
|
|
5364
|
+
onPick,
|
|
5365
|
+
onClose,
|
|
5366
|
+
i18n
|
|
5367
|
+
}) => {
|
|
5368
|
+
const [search, setSearch] = useState("");
|
|
5369
|
+
const inputRef = useRef(null);
|
|
5370
|
+
const browse = useProductBrowse({
|
|
5371
|
+
SL,
|
|
5372
|
+
collectionId,
|
|
5373
|
+
search,
|
|
5374
|
+
pageSize: 50,
|
|
5375
|
+
enabled: true
|
|
5376
|
+
});
|
|
5377
|
+
useEffect(() => {
|
|
5378
|
+
const prev = document.body.style.overflow;
|
|
5379
|
+
document.body.style.overflow = "hidden";
|
|
5380
|
+
const t = window.setTimeout(() => inputRef.current?.focus(), 0);
|
|
5381
|
+
const onKey = (e) => {
|
|
5382
|
+
if (e.key === "Escape") {
|
|
5383
|
+
e.stopPropagation();
|
|
5384
|
+
onClose();
|
|
5385
|
+
}
|
|
5386
|
+
};
|
|
5387
|
+
window.addEventListener("keydown", onKey, true);
|
|
5388
|
+
return () => {
|
|
5389
|
+
window.clearTimeout(t);
|
|
5390
|
+
window.removeEventListener("keydown", onKey, true);
|
|
5391
|
+
document.body.style.overflow = prev;
|
|
5392
|
+
};
|
|
5393
|
+
}, [onClose]);
|
|
5394
|
+
if (typeof document === "undefined") return null;
|
|
5395
|
+
return createPortal(
|
|
5396
|
+
/* @__PURE__ */ jsxs(
|
|
5397
|
+
"div",
|
|
5398
|
+
{
|
|
5399
|
+
className: "ra-shell ra-confirm-root",
|
|
5400
|
+
role: "presentation",
|
|
5401
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5402
|
+
onClick: (e) => e.stopPropagation(),
|
|
5403
|
+
onTouchStart: (e) => e.stopPropagation(),
|
|
5404
|
+
children: [
|
|
5405
|
+
/* @__PURE__ */ jsx("div", { className: "ra-confirm-backdrop", onClick: onClose }),
|
|
5406
|
+
/* @__PURE__ */ jsxs(
|
|
5407
|
+
"div",
|
|
5408
|
+
{
|
|
5409
|
+
role: "dialog",
|
|
5410
|
+
"aria-modal": "true",
|
|
5411
|
+
"aria-label": i18n?.searchProducts ?? "Search products",
|
|
5412
|
+
className: "ra-confirm-card",
|
|
5413
|
+
style: { width: "min(520px, 100%)", padding: "1rem" },
|
|
5414
|
+
children: [
|
|
5415
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
|
|
5416
|
+
/* @__PURE__ */ jsx(Search, { className: "w-4 h-4 opacity-60" }),
|
|
5417
|
+
/* @__PURE__ */ jsx(
|
|
5418
|
+
"input",
|
|
5419
|
+
{
|
|
5420
|
+
ref: inputRef,
|
|
5421
|
+
type: "text",
|
|
5422
|
+
value: search,
|
|
5423
|
+
onChange: (e) => setSearch(e.target.value),
|
|
5424
|
+
placeholder: i18n?.searchProducts ?? "Search products\u2026",
|
|
5425
|
+
className: "flex-1 text-sm px-2 py-1.5 rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
5426
|
+
style: {
|
|
5427
|
+
borderColor: "hsl(var(--ra-border))",
|
|
5428
|
+
color: "hsl(var(--ra-text))"
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
),
|
|
5432
|
+
/* @__PURE__ */ jsx(
|
|
5433
|
+
"button",
|
|
5434
|
+
{
|
|
5435
|
+
type: "button",
|
|
5436
|
+
onClick: onClose,
|
|
5437
|
+
className: "p-1 rounded-md hover:bg-[hsl(var(--ra-muted))]",
|
|
5438
|
+
"aria-label": i18n?.close ?? "Close",
|
|
5439
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
5440
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
5441
|
+
}
|
|
5442
|
+
)
|
|
5443
|
+
] }),
|
|
5444
|
+
/* @__PURE__ */ jsxs(
|
|
5445
|
+
"div",
|
|
5446
|
+
{
|
|
5447
|
+
className: "overflow-y-auto rounded-md border",
|
|
5448
|
+
style: {
|
|
5449
|
+
maxHeight: "50vh",
|
|
5450
|
+
borderColor: "hsl(var(--ra-border))"
|
|
5451
|
+
},
|
|
5452
|
+
children: [
|
|
5453
|
+
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) => {
|
|
5454
|
+
const active = p.id === currentProductId;
|
|
5455
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
5456
|
+
"button",
|
|
5457
|
+
{
|
|
5458
|
+
type: "button",
|
|
5459
|
+
onClick: () => onPick(p.id),
|
|
5460
|
+
className: "w-full text-left px-3 py-2 text-sm hover:bg-[hsl(var(--ra-muted))] flex items-center justify-between gap-3",
|
|
5461
|
+
style: {
|
|
5462
|
+
color: "hsl(var(--ra-text))",
|
|
5463
|
+
background: active ? "hsl(var(--ra-muted))" : "transparent"
|
|
5464
|
+
},
|
|
5465
|
+
children: [
|
|
5466
|
+
/* @__PURE__ */ jsxs("span", { className: "flex flex-col min-w-0", children: [
|
|
5467
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: p.name }),
|
|
5468
|
+
p.sku ? /* @__PURE__ */ jsx("span", { className: "truncate text-[11px]", style: { color: "hsl(var(--ra-muted-text))" }, children: p.sku }) : null
|
|
5469
|
+
] }),
|
|
5470
|
+
active ? /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide", style: { color: "hsl(var(--ra-muted-text))" }, children: "current" }) : null
|
|
5471
|
+
]
|
|
5472
|
+
}
|
|
5473
|
+
) }, p.id);
|
|
5474
|
+
}) }),
|
|
5475
|
+
browse.hasNextPage && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t", style: { borderColor: "hsl(var(--ra-border))" }, children: /* @__PURE__ */ jsx(
|
|
5476
|
+
"button",
|
|
5477
|
+
{
|
|
5478
|
+
type: "button",
|
|
5479
|
+
onClick: () => browse.fetchNextPage(),
|
|
5480
|
+
disabled: browse.isFetchingNextPage,
|
|
5481
|
+
className: "text-xs w-full py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))]",
|
|
5482
|
+
style: {
|
|
5483
|
+
borderColor: "hsl(var(--ra-border))",
|
|
5484
|
+
color: "hsl(var(--ra-text))"
|
|
5485
|
+
},
|
|
5486
|
+
children: browse.isFetchingNextPage ? "Loading\u2026" : "Load more"
|
|
5487
|
+
}
|
|
5488
|
+
) })
|
|
5489
|
+
]
|
|
5490
|
+
}
|
|
5491
|
+
)
|
|
5492
|
+
]
|
|
5493
|
+
}
|
|
5494
|
+
)
|
|
5495
|
+
]
|
|
5496
|
+
}
|
|
5497
|
+
),
|
|
5498
|
+
document.body
|
|
5499
|
+
);
|
|
5500
|
+
};
|
|
5259
5501
|
var ICONS2 = {
|
|
5260
5502
|
table: Table,
|
|
5261
5503
|
cards: LayoutGrid,
|
|
@@ -7154,6 +7396,11 @@ function RecordsAdminShellInner(props) {
|
|
|
7154
7396
|
variantChildren,
|
|
7155
7397
|
batchChildren
|
|
7156
7398
|
} = browser;
|
|
7399
|
+
const ruleScopedList = useRecordList({
|
|
7400
|
+
ctx,
|
|
7401
|
+
scopeKind: "rule",
|
|
7402
|
+
enabled: true
|
|
7403
|
+
});
|
|
7157
7404
|
const pinnedProduct = useSingleProduct({
|
|
7158
7405
|
SL,
|
|
7159
7406
|
collectionId,
|
|
@@ -7240,7 +7487,18 @@ function RecordsAdminShellInner(props) {
|
|
|
7240
7487
|
setSelectedVariantId,
|
|
7241
7488
|
selectedBatchId,
|
|
7242
7489
|
setSelectedBatchId,
|
|
7243
|
-
setFacetBrowseFilter
|
|
7490
|
+
setFacetBrowseFilter,
|
|
7491
|
+
// Pending-recordId resolution — without these the URL's `recordId` is
|
|
7492
|
+
// parsed but never opens the editor on refresh / share-link load.
|
|
7493
|
+
isCollection,
|
|
7494
|
+
setSelectedItemId,
|
|
7495
|
+
collectionItems: {
|
|
7496
|
+
items: collectionItems.items,
|
|
7497
|
+
isLoading: collectionItems.isLoading
|
|
7498
|
+
},
|
|
7499
|
+
recordListItems: recordList.items,
|
|
7500
|
+
recordListLoading: recordList.isLoading,
|
|
7501
|
+
skipNextItemResetRef
|
|
7244
7502
|
});
|
|
7245
7503
|
const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
|
|
7246
7504
|
const resolved = useResolvedRecord({
|
|
@@ -7487,6 +7745,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7487
7745
|
onChange: setPreviewScope,
|
|
7488
7746
|
showVariants: drillVariantsAllowed,
|
|
7489
7747
|
showBatches: drillBatchesAllowed,
|
|
7748
|
+
activeScope,
|
|
7490
7749
|
i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
|
|
7491
7750
|
}
|
|
7492
7751
|
) : null;
|
|
@@ -7675,6 +7934,26 @@ function RecordsAdminShellInner(props) {
|
|
|
7675
7934
|
const isGlobalTab = activeScope === "collection";
|
|
7676
7935
|
const isAllTab = activeScope === "all";
|
|
7677
7936
|
const isRecordsTab = isRuleTab || isGlobalTab || isAllTab;
|
|
7937
|
+
const ruleLabelLookup = useMemo(() => {
|
|
7938
|
+
const map = /* @__PURE__ */ new Map();
|
|
7939
|
+
for (const it of facetBrowse.items) {
|
|
7940
|
+
const k = it.scope.facetId;
|
|
7941
|
+
const v = it.scope.facetValue;
|
|
7942
|
+
if (!k || !v) continue;
|
|
7943
|
+
const facetLabel = it.subtitle ?? k;
|
|
7944
|
+
const valueLabel = it.label ?? v;
|
|
7945
|
+
let info = map.get(k);
|
|
7946
|
+
if (!info) {
|
|
7947
|
+
info = { label: facetLabel, values: /* @__PURE__ */ new Map() };
|
|
7948
|
+
map.set(k, info);
|
|
7949
|
+
}
|
|
7950
|
+
if (!info.values.has(v)) info.values.set(v, valueLabel);
|
|
7951
|
+
}
|
|
7952
|
+
return {
|
|
7953
|
+
facetLabel: (k) => map.get(k)?.label,
|
|
7954
|
+
valueLabel: (k, v) => map.get(k)?.values.get(v)
|
|
7955
|
+
};
|
|
7956
|
+
}, [facetBrowse.items]);
|
|
7678
7957
|
const effectiveGroupBy = useMemo(() => {
|
|
7679
7958
|
if (groupBy) return groupBy;
|
|
7680
7959
|
if (isAllTab) return void 0;
|
|
@@ -7683,13 +7962,25 @@ function RecordsAdminShellInner(props) {
|
|
|
7683
7962
|
return (record) => {
|
|
7684
7963
|
const hash = ruleHash(record.facetRule);
|
|
7685
7964
|
if (!hash) return null;
|
|
7686
|
-
return { key: `rule:${hash}`, label: summariseRule(record.facetRule) };
|
|
7965
|
+
return { key: `rule:${hash}`, label: summariseRule(record.facetRule, ruleLabelLookup) };
|
|
7687
7966
|
};
|
|
7688
|
-
}, [groupBy, isRuleTab, isAllTab, isCollection]);
|
|
7967
|
+
}, [groupBy, isRuleTab, isAllTab, isCollection, ruleLabelLookup]);
|
|
7689
7968
|
const [bulkRuleEditTarget, setBulkRuleEditTarget] = useState(null);
|
|
7690
7969
|
const ruleCatalogue = useMemo(() => {
|
|
7691
7970
|
const buckets = /* @__PURE__ */ new Map();
|
|
7971
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
7972
|
+
const merged = [];
|
|
7973
|
+
for (const item of ruleScopedList.allItems) {
|
|
7974
|
+
if (item.id && seenIds.has(item.id)) continue;
|
|
7975
|
+
if (item.id) seenIds.add(item.id);
|
|
7976
|
+
merged.push(item);
|
|
7977
|
+
}
|
|
7692
7978
|
for (const item of recordList.items) {
|
|
7979
|
+
if (item.id && seenIds.has(item.id)) continue;
|
|
7980
|
+
if (item.id) seenIds.add(item.id);
|
|
7981
|
+
merged.push(item);
|
|
7982
|
+
}
|
|
7983
|
+
for (const item of merged) {
|
|
7693
7984
|
const hash = ruleHash(item.facetRule);
|
|
7694
7985
|
if (!hash || !item.facetRule) continue;
|
|
7695
7986
|
const existing = buckets.get(hash);
|
|
@@ -7699,7 +7990,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7699
7990
|
buckets.set(hash, {
|
|
7700
7991
|
hash,
|
|
7701
7992
|
rule: item.facetRule,
|
|
7702
|
-
summary: summariseRule(item.facetRule),
|
|
7993
|
+
summary: summariseRule(item.facetRule, ruleLabelLookup),
|
|
7703
7994
|
count: 1
|
|
7704
7995
|
});
|
|
7705
7996
|
}
|
|
@@ -7708,7 +7999,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7708
7999
|
if (b.count !== a.count) return b.count - a.count;
|
|
7709
8000
|
return a.summary.localeCompare(b.summary);
|
|
7710
8001
|
});
|
|
7711
|
-
}, [recordList.items]);
|
|
8002
|
+
}, [recordList.items, ruleScopedList.allItems, ruleLabelLookup]);
|
|
7712
8003
|
const [targetingExpandNonce, setTargetingExpandNonce] = useState(0);
|
|
7713
8004
|
const renderRuleGroupActions = useCallback(
|
|
7714
8005
|
(group) => {
|
|
@@ -7799,8 +8090,13 @@ function RecordsAdminShellInner(props) {
|
|
|
7799
8090
|
}
|
|
7800
8091
|
return Array.from(buckets.values()).map(({ rep, count }) => ({
|
|
7801
8092
|
...rep,
|
|
7802
|
-
|
|
7803
|
-
|
|
8093
|
+
// Title carries the count + identity; the rule chips below render
|
|
8094
|
+
// the friendly facet/value labels (via the lookup) so we don't
|
|
8095
|
+
// repeat the same information in two places. Without this, a row
|
|
8096
|
+
// had three echoes of the same rule (raw-key title, friendly chip,
|
|
8097
|
+
// and the right-pane "Rule · …" header).
|
|
8098
|
+
label: `${count} ${itemNoun}${count === 1 ? "" : "s"}`,
|
|
8099
|
+
subtitle: void 0
|
|
7804
8100
|
}));
|
|
7805
8101
|
}, [isRuleTab, isCollection, filteredRuleItems, itemNoun]);
|
|
7806
8102
|
const activeRuleSummary = useMemo(() => {
|
|
@@ -7808,8 +8104,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7808
8104
|
if (!selectedRecordId || isDraftId3(selectedRecordId)) return null;
|
|
7809
8105
|
const hit = recordList.items.find((it) => it.id === selectedRecordId);
|
|
7810
8106
|
if (!hit?.facetRule) return null;
|
|
7811
|
-
return summariseRule(hit.facetRule);
|
|
7812
|
-
}, [isRuleTab, isCollection, selectedRecordId, recordList.items]);
|
|
8107
|
+
return summariseRule(hit.facetRule, ruleLabelLookup);
|
|
8108
|
+
}, [isRuleTab, isCollection, selectedRecordId, recordList.items, ruleLabelLookup]);
|
|
7813
8109
|
const applyFacetBrowseFilter = useCallback(
|
|
7814
8110
|
(items2) => {
|
|
7815
8111
|
if (!facetBrowseFilter) return items2;
|
|
@@ -7884,7 +8180,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7884
8180
|
});
|
|
7885
8181
|
};
|
|
7886
8182
|
onLeftSelectRef.current = onLeftSelect;
|
|
7887
|
-
return /* @__PURE__ */ jsxs(
|
|
8183
|
+
return /* @__PURE__ */ jsx(RuleLabelLookupProvider, { value: ruleLabelLookup, children: /* @__PURE__ */ jsxs(
|
|
7888
8184
|
"div",
|
|
7889
8185
|
{
|
|
7890
8186
|
className: `ra-shell flex flex-col h-full ${className ?? ""}`,
|
|
@@ -8365,7 +8661,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8365
8661
|
)
|
|
8366
8662
|
]
|
|
8367
8663
|
}
|
|
8368
|
-
);
|
|
8664
|
+
) });
|
|
8369
8665
|
}
|
|
8370
8666
|
var RecordBrowser = ({
|
|
8371
8667
|
scopes,
|
|
@@ -9220,6 +9516,9 @@ function useMergedRecord(args) {
|
|
|
9220
9516
|
};
|
|
9221
9517
|
}
|
|
9222
9518
|
|
|
9519
|
+
// src/components/RecordsAdmin/index.ts
|
|
9520
|
+
assertComponentStylesLoaded("records-admin");
|
|
9521
|
+
|
|
9223
9522
|
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 };
|
|
9224
9523
|
//# sourceMappingURL=index.js.map
|
|
9225
9524
|
//# sourceMappingURL=index.js.map
|