@proveanything/smartlinks-utils-ui 0.9.13 → 0.10.2
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/components/AssetPicker/index.css +90 -4
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +90 -4
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +90 -4
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +90 -4
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +90 -4
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +137 -17
- package/dist/components/RecordsAdmin/index.js +394 -158
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +90 -4
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import { cn } from '../../chunk-L7FQ52F5.js';
|
|
|
6
6
|
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
7
7
|
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
8
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,
|
|
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, Target, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, CopyPlus, AlertCircle, Undo2, Save, Loader2, XCircle, ArrowRight, BookOpen, Globe2, Check, Settings2 } from 'lucide-react';
|
|
10
10
|
import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
11
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
12
|
import { createPortal } from 'react-dom';
|
|
@@ -142,6 +142,8 @@ var DEFAULT_I18N = {
|
|
|
142
142
|
pasteConfirmCancel: "Cancel",
|
|
143
143
|
pasteWarnTitle: "Cross-scope paste",
|
|
144
144
|
pasteWarnContinue: "Continue",
|
|
145
|
+
duplicateAction: "Duplicate",
|
|
146
|
+
duplicateToast: "Duplicated {name}. Review and Save.",
|
|
145
147
|
itemsAllLabel: "All items",
|
|
146
148
|
subtitleEmpty: "Not set",
|
|
147
149
|
subtitleConfigured: "Configured",
|
|
@@ -1549,7 +1551,8 @@ function useShellClipboard(args) {
|
|
|
1549
1551
|
onTelemetry,
|
|
1550
1552
|
onCopyOverride,
|
|
1551
1553
|
onPasteOverride,
|
|
1552
|
-
onLeftSelectRef
|
|
1554
|
+
onLeftSelectRef,
|
|
1555
|
+
onCreateItemDraftRef
|
|
1553
1556
|
} = args;
|
|
1554
1557
|
const clipboard = useRecordClipboard({
|
|
1555
1558
|
appId,
|
|
@@ -1681,8 +1684,7 @@ function useShellClipboard(args) {
|
|
|
1681
1684
|
const rowClipboard = enabled ? (record) => {
|
|
1682
1685
|
const summaryHasData = record.data != null;
|
|
1683
1686
|
const sourceParsed = record.scope;
|
|
1684
|
-
const
|
|
1685
|
-
const sameTarget = clipboard.entry ? clipboard.entry.sourceRecordId && record.id ? clipboard.entry.sourceRecordId === record.id : clipboard.entry.sourceScope.raw === anchorKey(record.scope) : false;
|
|
1687
|
+
const canDuplicate = summaryHasData && isCollection;
|
|
1686
1688
|
return {
|
|
1687
1689
|
onCopy: summaryHasData ? () => {
|
|
1688
1690
|
const value = onCopyOverride ? onCopyOverride({ value: record.data, scope: sourceParsed }) : cloneValue(record.data);
|
|
@@ -1698,15 +1700,27 @@ function useShellClipboard(args) {
|
|
|
1698
1700
|
variant: "copy"
|
|
1699
1701
|
});
|
|
1700
1702
|
} : void 0,
|
|
1701
|
-
|
|
1703
|
+
onDuplicate: canDuplicate ? () => {
|
|
1704
|
+
const value = onCopyOverride ? onCopyOverride({ value: record.data, scope: sourceParsed }) : cloneValue(record.data);
|
|
1705
|
+
clipboard.set({
|
|
1706
|
+
value,
|
|
1707
|
+
sourceScope: sourceParsed,
|
|
1708
|
+
sourceRecordId: record.id ?? void 0,
|
|
1709
|
+
sourceLabel: record.label
|
|
1710
|
+
});
|
|
1711
|
+
onTelemetry?.({ type: "clipboard.copy", recordType, sourceRef: anchorKey(record.scope) });
|
|
1702
1712
|
onLeftSelectRef.current?.(record);
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
)
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1713
|
+
const create = onCreateItemDraftRef?.current;
|
|
1714
|
+
if (!create) return;
|
|
1715
|
+
window.setTimeout(() => {
|
|
1716
|
+
const newId = create();
|
|
1717
|
+
if (newId) setPendingPasteTarget({ kind: "record", recordId: newId });
|
|
1718
|
+
}, 0);
|
|
1719
|
+
setNotice({
|
|
1720
|
+
message: i18n.duplicateToast.replace("{name}", record.label),
|
|
1721
|
+
variant: "copy"
|
|
1722
|
+
});
|
|
1723
|
+
} : void 0
|
|
1710
1724
|
};
|
|
1711
1725
|
} : void 0;
|
|
1712
1726
|
const toast = notice ? /* @__PURE__ */ jsx(
|
|
@@ -1860,14 +1874,17 @@ function useShellNavigation(args) {
|
|
|
1860
1874
|
lastAppliedDLRef
|
|
1861
1875
|
]);
|
|
1862
1876
|
const onItemCreate = useCallback(() => {
|
|
1863
|
-
if (!isCollection) return;
|
|
1877
|
+
if (!isCollection) return void 0;
|
|
1878
|
+
let createdId;
|
|
1864
1879
|
void runWithGuard(() => {
|
|
1865
1880
|
const id = coerceDraftItemId(generateItemId);
|
|
1881
|
+
createdId = id;
|
|
1866
1882
|
setSelectedItemId(id);
|
|
1867
1883
|
onTelemetry?.({ type: "item.create", recordType, scopeRef: baseScopeRef });
|
|
1868
1884
|
deepLinkState.emit({ recordId: null, scope: baseScopeRef || null }, "record.open");
|
|
1869
1885
|
stampEcho(null, baseScopeRef || null);
|
|
1870
1886
|
});
|
|
1887
|
+
return createdId;
|
|
1871
1888
|
}, [
|
|
1872
1889
|
isCollection,
|
|
1873
1890
|
runWithGuard,
|
|
@@ -1951,7 +1968,9 @@ function useShellNavigation(args) {
|
|
|
1951
1968
|
]);
|
|
1952
1969
|
const itemViewCtx = useMemo(() => ({
|
|
1953
1970
|
onOpen: onItemOpen,
|
|
1954
|
-
onCreate:
|
|
1971
|
+
onCreate: () => {
|
|
1972
|
+
onItemCreate();
|
|
1973
|
+
},
|
|
1955
1974
|
onDelete: (id) => {
|
|
1956
1975
|
void onItemDelete(id);
|
|
1957
1976
|
},
|
|
@@ -2108,20 +2127,6 @@ var useShellDeepLink = (args) => {
|
|
|
2108
2127
|
const [pendingDeepLinkRecordId, setPendingDeepLinkRecordId] = useState(null);
|
|
2109
2128
|
const preserveInitialRecordIdRef = useRef(!!deepLinkState.urlState.recordId);
|
|
2110
2129
|
const warnedMissingRef = useRef(/* @__PURE__ */ new Set());
|
|
2111
|
-
const bootLoggedRef = useRef(false);
|
|
2112
|
-
if (!bootLoggedRef.current) {
|
|
2113
|
-
bootLoggedRef.current = true;
|
|
2114
|
-
console.info("[RecordsAdminShell] deep-link boot snapshot", {
|
|
2115
|
-
enabled: deepLinkState.enabled,
|
|
2116
|
-
urlStateRecordId: deepLinkState.urlState.recordId ?? null,
|
|
2117
|
-
urlStateScope: deepLinkState.urlState.scope ?? null,
|
|
2118
|
-
urlStateView: deepLinkState.urlState.view ?? null,
|
|
2119
|
-
urlStateRaw: JSON.stringify(deepLinkState.urlState),
|
|
2120
|
-
paramNames: deepLinkState.paramNames,
|
|
2121
|
-
windowHash: typeof window !== "undefined" ? window.location.hash : null,
|
|
2122
|
-
windowSearch: typeof window !== "undefined" ? window.location.search : null
|
|
2123
|
-
});
|
|
2124
|
-
}
|
|
2125
2130
|
useEffect(() => {
|
|
2126
2131
|
if (!deepLinkState.enabled) return;
|
|
2127
2132
|
if (selectedItemId) return;
|
|
@@ -2140,14 +2145,6 @@ var useShellDeepLink = (args) => {
|
|
|
2140
2145
|
useEffect(() => {
|
|
2141
2146
|
const { recordId, scope, view } = deepLinkState.urlState;
|
|
2142
2147
|
const sig = `${recordId ?? ""}|${scope ?? ""}|${view ?? ""}`;
|
|
2143
|
-
console.info("[RecordsAdminShell] restore effect tick", {
|
|
2144
|
-
enabled: deepLinkState.enabled,
|
|
2145
|
-
recordId,
|
|
2146
|
-
scope,
|
|
2147
|
-
view,
|
|
2148
|
-
sig,
|
|
2149
|
-
lastApplied: lastAppliedDLRef.current
|
|
2150
|
-
});
|
|
2151
2148
|
if (!deepLinkState.enabled) return;
|
|
2152
2149
|
if (sig === lastAppliedDLRef.current) return;
|
|
2153
2150
|
lastAppliedDLRef.current = sig;
|
|
@@ -2174,31 +2171,9 @@ var useShellDeepLink = (args) => {
|
|
|
2174
2171
|
}
|
|
2175
2172
|
setPendingDeepLinkRecordId(recordId ?? null);
|
|
2176
2173
|
if (recordId) preserveInitialRecordIdRef.current = true;
|
|
2177
|
-
if (recordId) {
|
|
2178
|
-
console.info("[RecordsAdminShell] deep-link restore \u2014 pending recordId set", {
|
|
2179
|
-
recordId,
|
|
2180
|
-
scope: scope ?? null,
|
|
2181
|
-
view: view ?? null
|
|
2182
|
-
});
|
|
2183
|
-
}
|
|
2184
|
-
if (!recordId && selectedItemId !== null) {
|
|
2185
|
-
console.info("[RecordsAdminShell] preserving selected item during restore without recordId", {
|
|
2186
|
-
selectedItemId,
|
|
2187
|
-
scope,
|
|
2188
|
-
view
|
|
2189
|
-
});
|
|
2190
|
-
}
|
|
2191
2174
|
}, [deepLinkState.enabled, deepLinkState.urlState]);
|
|
2192
2175
|
useEffect(() => {
|
|
2193
2176
|
const pending = pendingDeepLinkRecordId;
|
|
2194
|
-
console.info("[RecordsAdminShell] resolver tick", {
|
|
2195
|
-
pending,
|
|
2196
|
-
isCollection,
|
|
2197
|
-
collectionItemsCount: collectionItems.items.length,
|
|
2198
|
-
collectionItemsLoading: collectionItems.isLoading,
|
|
2199
|
-
recordListCount: recordListItems.length,
|
|
2200
|
-
recordListLoading
|
|
2201
|
-
});
|
|
2202
2177
|
if (!pending) return;
|
|
2203
2178
|
if (isCollection) {
|
|
2204
2179
|
const hit2 = collectionItems.items.find((it) => it.id === pending || it.itemId === pending);
|
|
@@ -3282,10 +3257,8 @@ var statusToneLabel = (tone) => {
|
|
|
3282
3257
|
};
|
|
3283
3258
|
var RowContextMenu = ({
|
|
3284
3259
|
onCopy,
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
pasteWillReplace,
|
|
3288
|
-
pasteSourceLabel,
|
|
3260
|
+
onDuplicate,
|
|
3261
|
+
actions,
|
|
3289
3262
|
i18n
|
|
3290
3263
|
}) => {
|
|
3291
3264
|
const [open, setOpen] = useState(false);
|
|
@@ -3334,8 +3307,9 @@ var RowContextMenu = ({
|
|
|
3334
3307
|
window.removeEventListener("scroll", update, true);
|
|
3335
3308
|
};
|
|
3336
3309
|
}, [open]);
|
|
3337
|
-
|
|
3338
|
-
|
|
3310
|
+
const hasActions = (actions?.length ?? 0) > 0;
|
|
3311
|
+
if (!onCopy && !onDuplicate && !hasActions) return null;
|
|
3312
|
+
const showDivider = (onCopy || onDuplicate) && hasActions;
|
|
3339
3313
|
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: "ra-row-menu-wrap relative", children: [
|
|
3340
3314
|
/* @__PURE__ */ jsx(
|
|
3341
3315
|
"button",
|
|
@@ -3381,24 +3355,49 @@ var RowContextMenu = ({
|
|
|
3381
3355
|
]
|
|
3382
3356
|
}
|
|
3383
3357
|
),
|
|
3384
|
-
|
|
3358
|
+
onDuplicate && /* @__PURE__ */ jsxs(
|
|
3385
3359
|
"button",
|
|
3386
3360
|
{
|
|
3387
3361
|
type: "button",
|
|
3388
3362
|
role: "menuitem",
|
|
3389
3363
|
className: "ra-row-menu-item",
|
|
3390
|
-
disabled: !canPaste,
|
|
3391
3364
|
onClick: (e) => {
|
|
3392
3365
|
e.stopPropagation();
|
|
3393
3366
|
setOpen(false);
|
|
3394
|
-
|
|
3367
|
+
onDuplicate();
|
|
3395
3368
|
},
|
|
3396
3369
|
children: [
|
|
3397
|
-
/* @__PURE__ */ jsx(
|
|
3398
|
-
/* @__PURE__ */ jsx("span", {
|
|
3370
|
+
/* @__PURE__ */ jsx(CopyPlus, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
3371
|
+
/* @__PURE__ */ jsx("span", { children: i18n.duplicateAction })
|
|
3399
3372
|
]
|
|
3400
3373
|
}
|
|
3401
|
-
)
|
|
3374
|
+
),
|
|
3375
|
+
showDivider && /* @__PURE__ */ jsx("div", { className: "ra-row-menu-divider", role: "separator" }),
|
|
3376
|
+
hasActions && actions.map((action) => {
|
|
3377
|
+
const Icon = action.icon;
|
|
3378
|
+
return /* @__PURE__ */ jsxs(
|
|
3379
|
+
"button",
|
|
3380
|
+
{
|
|
3381
|
+
type: "button",
|
|
3382
|
+
role: "menuitem",
|
|
3383
|
+
className: "ra-row-menu-item",
|
|
3384
|
+
"data-tone": action.variant === "danger" ? "danger" : void 0,
|
|
3385
|
+
disabled: action.disabled,
|
|
3386
|
+
title: action.disabled ? action.disabledReason : void 0,
|
|
3387
|
+
onClick: (e) => {
|
|
3388
|
+
e.stopPropagation();
|
|
3389
|
+
if (action.disabled) return;
|
|
3390
|
+
setOpen(false);
|
|
3391
|
+
void action.onAction();
|
|
3392
|
+
},
|
|
3393
|
+
children: [
|
|
3394
|
+
Icon && /* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }),
|
|
3395
|
+
/* @__PURE__ */ jsx("span", { children: action.label })
|
|
3396
|
+
]
|
|
3397
|
+
},
|
|
3398
|
+
action.key
|
|
3399
|
+
);
|
|
3400
|
+
})
|
|
3402
3401
|
]
|
|
3403
3402
|
}
|
|
3404
3403
|
),
|
|
@@ -3447,7 +3446,7 @@ var RuleLabelLookupProvider = ({
|
|
|
3447
3446
|
return /* @__PURE__ */ jsx(RuleLabelLookupContext.Provider, { value: v, children });
|
|
3448
3447
|
};
|
|
3449
3448
|
var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
3450
|
-
const { selected, onSelect, isDirty, hasError, onCopy,
|
|
3449
|
+
const { selected, onSelect, isDirty, hasError, onCopy, onDuplicate, actions } = ctx;
|
|
3451
3450
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
3452
3451
|
const ScopeIcon = record.scope.kind && record.scope.kind !== "collection" ? DEFAULT_ICONS.scope[record.scope.kind] : DEFAULT_ICONS.scope.product;
|
|
3453
3452
|
const tone = resolveTone(void 0, record.status);
|
|
@@ -3500,7 +3499,7 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
3500
3499
|
className: "ra-row-rule-pip",
|
|
3501
3500
|
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This record has targeting rules",
|
|
3502
3501
|
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This record has targeting rules",
|
|
3503
|
-
children: /* @__PURE__ */ jsx(
|
|
3502
|
+
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
3504
3503
|
}
|
|
3505
3504
|
),
|
|
3506
3505
|
hasError ? /* @__PURE__ */ jsx(
|
|
@@ -3519,20 +3518,15 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
3519
3518
|
}
|
|
3520
3519
|
)
|
|
3521
3520
|
] }),
|
|
3522
|
-
(onCopy ||
|
|
3521
|
+
(onCopy || onDuplicate || actions && actions.length > 0) && /* @__PURE__ */ jsx(
|
|
3523
3522
|
RowContextMenu,
|
|
3524
3523
|
{
|
|
3525
3524
|
onCopy,
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
pasteWillReplace,
|
|
3529
|
-
pasteSourceLabel: clipboardSourceLabel,
|
|
3525
|
+
onDuplicate,
|
|
3526
|
+
actions,
|
|
3530
3527
|
i18n: {
|
|
3531
3528
|
copy: DEFAULT_I18N.copy,
|
|
3532
|
-
|
|
3533
|
-
pasteFrom: DEFAULT_I18N.pasteFrom,
|
|
3534
|
-
pasteReplace: DEFAULT_I18N.pasteReplace,
|
|
3535
|
-
clipboardEmpty: DEFAULT_I18N.clipboardEmpty
|
|
3529
|
+
duplicateAction: DEFAULT_I18N.duplicateAction
|
|
3536
3530
|
}
|
|
3537
3531
|
}
|
|
3538
3532
|
)
|
|
@@ -3554,10 +3548,37 @@ var RecordList = ({
|
|
|
3554
3548
|
groupBy,
|
|
3555
3549
|
renderGroupActions,
|
|
3556
3550
|
rowClipboard,
|
|
3551
|
+
rowActions,
|
|
3557
3552
|
i18n
|
|
3558
3553
|
}) => {
|
|
3554
|
+
const containerRef = useRef(null);
|
|
3555
|
+
const onKeyDown = useCallback((e) => {
|
|
3556
|
+
const key = e.key;
|
|
3557
|
+
if (key !== "ArrowDown" && key !== "ArrowUp" && key !== "Home" && key !== "End") {
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
const root = containerRef.current;
|
|
3561
|
+
if (!root) return;
|
|
3562
|
+
const buttons = Array.from(
|
|
3563
|
+
root.querySelectorAll("button.ra-row-hit")
|
|
3564
|
+
).filter((btn) => !btn.hasAttribute("disabled") && btn.offsetParent !== null);
|
|
3565
|
+
if (buttons.length === 0) return;
|
|
3566
|
+
const active = document.activeElement;
|
|
3567
|
+
const currentIdx = active ? buttons.indexOf(active) : -1;
|
|
3568
|
+
let nextIdx = currentIdx;
|
|
3569
|
+
if (key === "ArrowDown") nextIdx = currentIdx < 0 ? 0 : Math.min(currentIdx + 1, buttons.length - 1);
|
|
3570
|
+
else if (key === "ArrowUp") nextIdx = currentIdx <= 0 ? 0 : currentIdx - 1;
|
|
3571
|
+
else if (key === "Home") nextIdx = 0;
|
|
3572
|
+
else if (key === "End") nextIdx = buttons.length - 1;
|
|
3573
|
+
if (nextIdx !== currentIdx && buttons[nextIdx]) {
|
|
3574
|
+
e.preventDefault();
|
|
3575
|
+
buttons[nextIdx].focus();
|
|
3576
|
+
buttons[nextIdx].scrollIntoView({ block: "nearest" });
|
|
3577
|
+
}
|
|
3578
|
+
}, []);
|
|
3559
3579
|
const buildCtx = (item) => {
|
|
3560
3580
|
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
3581
|
+
const extraActions = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
3561
3582
|
const itemAnchorKey = anchorKey(item.scope);
|
|
3562
3583
|
const idMatch = selectedId != null && item.id != null && item.id === selectedId;
|
|
3563
3584
|
const anchorMatch = selectedAnchorKey != null && !!itemAnchorKey && itemAnchorKey === selectedAnchorKey;
|
|
@@ -3572,7 +3593,8 @@ var RecordList = ({
|
|
|
3572
3593
|
isDirty: dirtyIdMatch || dirtyAnchorMatch || idInStore || anchorInStore,
|
|
3573
3594
|
hasError: errorInStore,
|
|
3574
3595
|
i18n,
|
|
3575
|
-
...cb ?? {}
|
|
3596
|
+
...cb ?? {},
|
|
3597
|
+
actions: extraActions && extraActions.length > 0 ? extraActions : void 0
|
|
3576
3598
|
};
|
|
3577
3599
|
};
|
|
3578
3600
|
const groups = useMemo(() => {
|
|
@@ -3599,15 +3621,33 @@ var RecordList = ({
|
|
|
3599
3621
|
};
|
|
3600
3622
|
if (groups) {
|
|
3601
3623
|
return /* @__PURE__ */ jsx(
|
|
3602
|
-
|
|
3624
|
+
"div",
|
|
3603
3625
|
{
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3626
|
+
ref: containerRef,
|
|
3627
|
+
onKeyDown,
|
|
3628
|
+
role: "listbox",
|
|
3629
|
+
"aria-label": "Records",
|
|
3630
|
+
children: /* @__PURE__ */ jsx(
|
|
3631
|
+
GroupedList,
|
|
3632
|
+
{
|
|
3633
|
+
groups,
|
|
3634
|
+
renderItems,
|
|
3635
|
+
renderGroupActions
|
|
3636
|
+
}
|
|
3637
|
+
)
|
|
3607
3638
|
}
|
|
3608
3639
|
);
|
|
3609
3640
|
}
|
|
3610
|
-
return
|
|
3641
|
+
return /* @__PURE__ */ jsx(
|
|
3642
|
+
"div",
|
|
3643
|
+
{
|
|
3644
|
+
ref: containerRef,
|
|
3645
|
+
onKeyDown,
|
|
3646
|
+
role: "listbox",
|
|
3647
|
+
"aria-label": "Records",
|
|
3648
|
+
children: renderItems(items)
|
|
3649
|
+
}
|
|
3650
|
+
);
|
|
3611
3651
|
};
|
|
3612
3652
|
var GroupedList = ({
|
|
3613
3653
|
groups,
|
|
@@ -5518,6 +5558,8 @@ function DefaultItemTable({
|
|
|
5518
5558
|
selectedId,
|
|
5519
5559
|
onOpen,
|
|
5520
5560
|
onDelete,
|
|
5561
|
+
rowActions,
|
|
5562
|
+
rowClipboard,
|
|
5521
5563
|
i18n
|
|
5522
5564
|
}) {
|
|
5523
5565
|
const cols = columns ?? [];
|
|
@@ -5555,6 +5597,31 @@ function DefaultItemTable({
|
|
|
5555
5597
|
/* @__PURE__ */ jsx("td", { className: "ra-item-row-meta", children: formatDate(item.updatedAt) })
|
|
5556
5598
|
] }) : cols.map((c) => /* @__PURE__ */ jsx("td", { style: { textAlign: c.align ?? "left" }, children: c.render(item) }, c.key)),
|
|
5557
5599
|
/* @__PURE__ */ jsxs("td", { className: "ra-item-row-actions", children: [
|
|
5600
|
+
(() => {
|
|
5601
|
+
const extra = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
5602
|
+
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
5603
|
+
const hasExtras = !!(extra && extra.length > 0);
|
|
5604
|
+
if (!cb?.onCopy && !cb?.onDuplicate && !hasExtras) return null;
|
|
5605
|
+
return /* @__PURE__ */ jsx(
|
|
5606
|
+
"span",
|
|
5607
|
+
{
|
|
5608
|
+
onClick: (e) => e.stopPropagation(),
|
|
5609
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5610
|
+
children: /* @__PURE__ */ jsx(
|
|
5611
|
+
RowContextMenu,
|
|
5612
|
+
{
|
|
5613
|
+
onCopy: cb?.onCopy,
|
|
5614
|
+
onDuplicate: cb?.onDuplicate,
|
|
5615
|
+
actions: extra ?? void 0,
|
|
5616
|
+
i18n: {
|
|
5617
|
+
copy: DEFAULT_I18N.copy,
|
|
5618
|
+
duplicateAction: DEFAULT_I18N.duplicateAction
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
)
|
|
5622
|
+
}
|
|
5623
|
+
);
|
|
5624
|
+
})(),
|
|
5558
5625
|
/* @__PURE__ */ jsx(
|
|
5559
5626
|
"button",
|
|
5560
5627
|
{
|
|
@@ -5598,6 +5665,8 @@ function DefaultItemCards({
|
|
|
5598
5665
|
ctx,
|
|
5599
5666
|
renderCard,
|
|
5600
5667
|
cardSize = "md",
|
|
5668
|
+
rowActions,
|
|
5669
|
+
rowClipboard,
|
|
5601
5670
|
i18n
|
|
5602
5671
|
}) {
|
|
5603
5672
|
const isGallery = variant === "gallery";
|
|
@@ -5610,10 +5679,13 @@ function DefaultItemCards({
|
|
|
5610
5679
|
const id = item.itemId ?? "";
|
|
5611
5680
|
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
5612
5681
|
const open = () => ctx.onOpen(id);
|
|
5682
|
+
const extraActions = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
5683
|
+
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
5613
5684
|
const slotCtx = {
|
|
5614
5685
|
...ctx,
|
|
5615
5686
|
selected: selectedId === id,
|
|
5616
|
-
onSelect: open
|
|
5687
|
+
onSelect: open,
|
|
5688
|
+
actions: extraActions && extraActions.length > 0 ? extraActions : void 0
|
|
5617
5689
|
};
|
|
5618
5690
|
if (renderCard) {
|
|
5619
5691
|
return /* @__PURE__ */ jsx(
|
|
@@ -5640,6 +5712,26 @@ function DefaultItemCards({
|
|
|
5640
5712
|
/* @__PURE__ */ jsx("div", { className: "ra-item-card-title", children: item.label }),
|
|
5641
5713
|
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-card-sub", children: item.subtitle })
|
|
5642
5714
|
] }),
|
|
5715
|
+
(cb?.onCopy || cb?.onDuplicate || extraActions && extraActions.length > 0) && /* @__PURE__ */ jsx(
|
|
5716
|
+
"span",
|
|
5717
|
+
{
|
|
5718
|
+
className: "ra-item-card-menu",
|
|
5719
|
+
onClick: (e) => e.stopPropagation(),
|
|
5720
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5721
|
+
children: /* @__PURE__ */ jsx(
|
|
5722
|
+
RowContextMenu,
|
|
5723
|
+
{
|
|
5724
|
+
onCopy: cb?.onCopy,
|
|
5725
|
+
onDuplicate: cb?.onDuplicate,
|
|
5726
|
+
actions: extraActions,
|
|
5727
|
+
i18n: {
|
|
5728
|
+
copy: DEFAULT_I18N.copy,
|
|
5729
|
+
duplicateAction: DEFAULT_I18N.duplicateAction
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
)
|
|
5733
|
+
}
|
|
5734
|
+
),
|
|
5643
5735
|
/* @__PURE__ */ jsx(
|
|
5644
5736
|
"button",
|
|
5645
5737
|
{
|
|
@@ -5677,6 +5769,8 @@ function ItemListView({
|
|
|
5677
5769
|
renderItemEmpty,
|
|
5678
5770
|
itemColumns,
|
|
5679
5771
|
cardSize = "md",
|
|
5772
|
+
rowActions,
|
|
5773
|
+
rowClipboard,
|
|
5680
5774
|
i18n
|
|
5681
5775
|
}) {
|
|
5682
5776
|
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
|
|
@@ -5747,6 +5841,8 @@ function ItemListView({
|
|
|
5747
5841
|
selectedId: ctx.selectedId,
|
|
5748
5842
|
onOpen: ctx.onOpen,
|
|
5749
5843
|
onDelete: ctx.onDelete,
|
|
5844
|
+
rowActions,
|
|
5845
|
+
rowClipboard,
|
|
5750
5846
|
i18n
|
|
5751
5847
|
}
|
|
5752
5848
|
);
|
|
@@ -5760,6 +5856,8 @@ function ItemListView({
|
|
|
5760
5856
|
ctx,
|
|
5761
5857
|
renderCard: renderItemCard,
|
|
5762
5858
|
cardSize,
|
|
5859
|
+
rowActions,
|
|
5860
|
+
rowClipboard,
|
|
5763
5861
|
i18n
|
|
5764
5862
|
}
|
|
5765
5863
|
);
|
|
@@ -5852,67 +5950,92 @@ function SiblingRail({
|
|
|
5852
5950
|
selectedItemId,
|
|
5853
5951
|
isLoading,
|
|
5854
5952
|
error,
|
|
5953
|
+
onBack,
|
|
5855
5954
|
onSelect,
|
|
5955
|
+
contextKind,
|
|
5956
|
+
contextSummary,
|
|
5856
5957
|
dirtyKeys,
|
|
5857
5958
|
errorKeys,
|
|
5858
5959
|
i18n
|
|
5859
5960
|
}) {
|
|
5860
5961
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
5861
|
-
return /* @__PURE__ */
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
5865
|
-
!isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item, idx) => {
|
|
5866
|
-
const id = item.itemId ?? "";
|
|
5867
|
-
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
5868
|
-
const akey = anchorKey(item.scope);
|
|
5869
|
-
const selected = selectedItemId === id;
|
|
5870
|
-
const isDirty = !!(id && dirtyKeys?.has(id) || akey && dirtyKeys?.has(akey));
|
|
5871
|
-
const hasError = !!(id && errorKeys?.has(id) || akey && errorKeys?.has(akey));
|
|
5872
|
-
const ruleClauses = item.facetRule ? summarizeFacetRule(item.facetRule, ruleLabelLookup) : [];
|
|
5873
|
-
const isTargeted = ruleClauses.length > 0;
|
|
5874
|
-
const ruleSummary = isTargeted ? ruleClauses.map((c) => c.label).join(" \xB7 ") : null;
|
|
5875
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
5962
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
|
|
5963
|
+
(onBack || contextKind) && /* @__PURE__ */ jsxs("div", { className: "ra-sibling-context", children: [
|
|
5964
|
+
onBack && /* @__PURE__ */ jsx(
|
|
5876
5965
|
"button",
|
|
5877
5966
|
{
|
|
5878
5967
|
type: "button",
|
|
5879
|
-
onClick:
|
|
5880
|
-
className: "ra-
|
|
5881
|
-
"
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
5885
|
-
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
5886
|
-
] }),
|
|
5887
|
-
isTargeted && /* @__PURE__ */ jsx(
|
|
5888
|
-
"span",
|
|
5889
|
-
{
|
|
5890
|
-
className: "ra-row-rule-pip",
|
|
5891
|
-
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
5892
|
-
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
5893
|
-
children: /* @__PURE__ */ jsx(SlidersHorizontal, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
5894
|
-
}
|
|
5895
|
-
),
|
|
5896
|
-
hasError ? /* @__PURE__ */ jsx(
|
|
5897
|
-
"span",
|
|
5898
|
-
{
|
|
5899
|
-
className: "ra-error-pip",
|
|
5900
|
-
title: "Save failed",
|
|
5901
|
-
"aria-label": "Save failed"
|
|
5902
|
-
}
|
|
5903
|
-
) : isDirty ? /* @__PURE__ */ jsx(
|
|
5904
|
-
"span",
|
|
5905
|
-
{
|
|
5906
|
-
className: "ra-dirty-pip",
|
|
5907
|
-
title: "Unsaved changes",
|
|
5908
|
-
"aria-label": "Unsaved changes"
|
|
5909
|
-
}
|
|
5910
|
-
) : null
|
|
5911
|
-
]
|
|
5968
|
+
onClick: onBack,
|
|
5969
|
+
className: "ra-sibling-context-back",
|
|
5970
|
+
"aria-label": i18n.backToList,
|
|
5971
|
+
title: i18n.backToList,
|
|
5972
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5", "aria-hidden": "true" })
|
|
5912
5973
|
}
|
|
5913
|
-
)
|
|
5914
|
-
|
|
5915
|
-
|
|
5974
|
+
),
|
|
5975
|
+
contextKind && /* @__PURE__ */ jsxs("div", { className: "ra-sibling-context-label", title: contextSummary ? `${contextKind} \xB7 ${contextSummary}` : contextKind, children: [
|
|
5976
|
+
/* @__PURE__ */ jsx("span", { className: "ra-sibling-context-kind", children: contextKind }),
|
|
5977
|
+
contextSummary && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5978
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ra-sibling-context-sep", children: "\xB7" }),
|
|
5979
|
+
/* @__PURE__ */ jsx("span", { className: "ra-sibling-context-summary", children: contextSummary })
|
|
5980
|
+
] })
|
|
5981
|
+
] })
|
|
5982
|
+
] }),
|
|
5983
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-sibling-body", children: [
|
|
5984
|
+
isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
5985
|
+
!isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
|
|
5986
|
+
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
5987
|
+
!isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item, idx) => {
|
|
5988
|
+
const id = item.itemId ?? "";
|
|
5989
|
+
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
5990
|
+
const akey = anchorKey(item.scope);
|
|
5991
|
+
const selected = selectedItemId === id;
|
|
5992
|
+
const isDirty = !!(id && dirtyKeys?.has(id) || akey && dirtyKeys?.has(akey));
|
|
5993
|
+
const hasError = !!(id && errorKeys?.has(id) || akey && errorKeys?.has(akey));
|
|
5994
|
+
const ruleClauses = item.facetRule ? summarizeFacetRule(item.facetRule, ruleLabelLookup) : [];
|
|
5995
|
+
const isTargeted = ruleClauses.length > 0;
|
|
5996
|
+
const ruleSummary = isTargeted ? ruleClauses.map((c) => c.label).join(" \xB7 ") : null;
|
|
5997
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
5998
|
+
"button",
|
|
5999
|
+
{
|
|
6000
|
+
type: "button",
|
|
6001
|
+
onClick: () => onSelect(id),
|
|
6002
|
+
className: "ra-row",
|
|
6003
|
+
"data-selected": selected,
|
|
6004
|
+
children: [
|
|
6005
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
6006
|
+
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
6007
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
6008
|
+
] }),
|
|
6009
|
+
isTargeted && /* @__PURE__ */ jsx(
|
|
6010
|
+
"span",
|
|
6011
|
+
{
|
|
6012
|
+
className: "ra-row-rule-pip",
|
|
6013
|
+
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
6014
|
+
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
6015
|
+
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
6016
|
+
}
|
|
6017
|
+
),
|
|
6018
|
+
hasError ? /* @__PURE__ */ jsx(
|
|
6019
|
+
"span",
|
|
6020
|
+
{
|
|
6021
|
+
className: "ra-error-pip",
|
|
6022
|
+
title: "Save failed",
|
|
6023
|
+
"aria-label": "Save failed"
|
|
6024
|
+
}
|
|
6025
|
+
) : isDirty ? /* @__PURE__ */ jsx(
|
|
6026
|
+
"span",
|
|
6027
|
+
{
|
|
6028
|
+
className: "ra-dirty-pip",
|
|
6029
|
+
title: "Unsaved changes",
|
|
6030
|
+
"aria-label": "Unsaved changes"
|
|
6031
|
+
}
|
|
6032
|
+
) : null
|
|
6033
|
+
]
|
|
6034
|
+
}
|
|
6035
|
+
) }, key);
|
|
6036
|
+
}) })
|
|
6037
|
+
] })
|
|
6038
|
+
] });
|
|
5916
6039
|
}
|
|
5917
6040
|
var TONE_ICON = {
|
|
5918
6041
|
info: Lightbulb,
|
|
@@ -6850,6 +6973,60 @@ var SaveAllProgress = ({
|
|
|
6850
6973
|
}
|
|
6851
6974
|
);
|
|
6852
6975
|
};
|
|
6976
|
+
function PreviewReopenPill({ anchorRef, onClick, ariaLabel, title, children }) {
|
|
6977
|
+
const [pos, setPos] = useState(null);
|
|
6978
|
+
const rafRef = useRef(null);
|
|
6979
|
+
useLayoutEffect(() => {
|
|
6980
|
+
const el = anchorRef.current;
|
|
6981
|
+
if (!el || typeof window === "undefined") return;
|
|
6982
|
+
const measure = () => {
|
|
6983
|
+
if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
|
|
6984
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
6985
|
+
const rect = el.getBoundingClientRect();
|
|
6986
|
+
if (rect.width === 0 && rect.height === 0) return;
|
|
6987
|
+
setPos({
|
|
6988
|
+
top: rect.top + rect.height / 2,
|
|
6989
|
+
right: Math.max(0, window.innerWidth - rect.right)
|
|
6990
|
+
});
|
|
6991
|
+
});
|
|
6992
|
+
};
|
|
6993
|
+
measure();
|
|
6994
|
+
const ro = new ResizeObserver(measure);
|
|
6995
|
+
ro.observe(el);
|
|
6996
|
+
ro.observe(document.body);
|
|
6997
|
+
window.addEventListener("resize", measure);
|
|
6998
|
+
window.addEventListener("scroll", measure, true);
|
|
6999
|
+
return () => {
|
|
7000
|
+
ro.disconnect();
|
|
7001
|
+
window.removeEventListener("resize", measure);
|
|
7002
|
+
window.removeEventListener("scroll", measure, true);
|
|
7003
|
+
if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
|
|
7004
|
+
};
|
|
7005
|
+
}, [anchorRef]);
|
|
7006
|
+
if (typeof document === "undefined" || !pos) return null;
|
|
7007
|
+
return createPortal(
|
|
7008
|
+
/* @__PURE__ */ jsx(
|
|
7009
|
+
"button",
|
|
7010
|
+
{
|
|
7011
|
+
type: "button",
|
|
7012
|
+
className: "ra-shell ra-preview-reopen ra-preview-reopen--floating",
|
|
7013
|
+
onClick,
|
|
7014
|
+
"aria-label": ariaLabel,
|
|
7015
|
+
title,
|
|
7016
|
+
style: {
|
|
7017
|
+
position: "fixed",
|
|
7018
|
+
top: pos.top,
|
|
7019
|
+
right: pos.right,
|
|
7020
|
+
// Pull half the pill width out into the gutter so it visually
|
|
7021
|
+
// anchors *to* the editor edge rather than sitting inside it.
|
|
7022
|
+
transform: "translate(50%, -50%)"
|
|
7023
|
+
},
|
|
7024
|
+
children
|
|
7025
|
+
}
|
|
7026
|
+
),
|
|
7027
|
+
document.body
|
|
7028
|
+
);
|
|
7029
|
+
}
|
|
6853
7030
|
var EditorMountPool = ({
|
|
6854
7031
|
renderSlot,
|
|
6855
7032
|
keepMountedHidden = true,
|
|
@@ -7144,6 +7321,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7144
7321
|
unsaved,
|
|
7145
7322
|
clipboard,
|
|
7146
7323
|
actions,
|
|
7324
|
+
recordActions,
|
|
7147
7325
|
icons: iconsOverride,
|
|
7148
7326
|
// Deep linking
|
|
7149
7327
|
deepLink
|
|
@@ -7600,6 +7778,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7600
7778
|
i18n
|
|
7601
7779
|
]);
|
|
7602
7780
|
const onLeftSelectRef = useRef(null);
|
|
7781
|
+
const onCreateItemDraftRef = useRef(null);
|
|
7782
|
+
const previewReopenAnchorRef = useRef(null);
|
|
7603
7783
|
const { runWithGuard } = useDirtyNavigation({
|
|
7604
7784
|
strategy: dirtyStrategy,
|
|
7605
7785
|
isDirty: editorCtx.isDirty,
|
|
@@ -7654,19 +7834,37 @@ function RecordsAdminShellInner(props) {
|
|
|
7654
7834
|
onTelemetry,
|
|
7655
7835
|
onCopyOverride,
|
|
7656
7836
|
onPasteOverride,
|
|
7657
|
-
onLeftSelectRef
|
|
7837
|
+
onLeftSelectRef,
|
|
7838
|
+
onCreateItemDraftRef
|
|
7658
7839
|
});
|
|
7659
7840
|
const editorClipboard = shellClipboard.editorClipboard;
|
|
7660
7841
|
const rowClipboard = shellClipboard.rowClipboard;
|
|
7842
|
+
const wrappedRecordActions = recordActions ? (record) => {
|
|
7843
|
+
const list = recordActions(record, record.scope);
|
|
7844
|
+
if (!list || list.length === 0) return list ?? void 0;
|
|
7845
|
+
return list.map((a) => ({
|
|
7846
|
+
...a,
|
|
7847
|
+
onAction: () => {
|
|
7848
|
+
onTelemetry?.({
|
|
7849
|
+
type: "recordAction.invoke",
|
|
7850
|
+
recordType,
|
|
7851
|
+
key: a.key,
|
|
7852
|
+
ref: anchorKey(record.scope)
|
|
7853
|
+
});
|
|
7854
|
+
return a.onAction();
|
|
7855
|
+
}
|
|
7856
|
+
}));
|
|
7857
|
+
} : void 0;
|
|
7661
7858
|
const baseScopeRef = editingScope?.raw ?? "";
|
|
7662
7859
|
const itemNounLabel = itemNoun || "item";
|
|
7663
7860
|
const {
|
|
7664
7861
|
onItemOpen,
|
|
7862
|
+
onItemCreate,
|
|
7665
7863
|
onItemBack,
|
|
7666
7864
|
onItemPrev,
|
|
7667
7865
|
onItemNext,
|
|
7668
7866
|
itemPosition,
|
|
7669
|
-
itemViewCtx} = useShellNavigation({
|
|
7867
|
+
itemViewCtx: baseItemViewCtx} = useShellNavigation({
|
|
7670
7868
|
isCollection,
|
|
7671
7869
|
runWithGuard,
|
|
7672
7870
|
selectedItemId,
|
|
@@ -7686,8 +7884,10 @@ function RecordsAdminShellInner(props) {
|
|
|
7686
7884
|
hooks: props.hooks,
|
|
7687
7885
|
lastAppliedDLRef
|
|
7688
7886
|
});
|
|
7887
|
+
const itemViewCtx = baseItemViewCtx;
|
|
7689
7888
|
const renderEditorWithPreview = () => {
|
|
7690
7889
|
if (!editingTargetScope) return null;
|
|
7890
|
+
const previewAnchorRef = previewReopenAnchorRef;
|
|
7691
7891
|
const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
|
|
7692
7892
|
const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
7693
7893
|
PreviewScopePicker,
|
|
@@ -7789,15 +7989,14 @@ function RecordsAdminShellInner(props) {
|
|
|
7789
7989
|
if (previewMode === "side") {
|
|
7790
7990
|
if (!sidePreviewOpen) {
|
|
7791
7991
|
return withNav(
|
|
7792
|
-
/* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
|
|
7992
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-full", ref: previewAnchorRef, children: [
|
|
7793
7993
|
baseEditor(),
|
|
7794
7994
|
/* @__PURE__ */ jsxs(
|
|
7795
|
-
|
|
7995
|
+
PreviewReopenPill,
|
|
7796
7996
|
{
|
|
7797
|
-
|
|
7798
|
-
className: "ra-preview-reopen",
|
|
7997
|
+
anchorRef: previewAnchorRef,
|
|
7799
7998
|
onClick: () => setSidePreviewOpen(true),
|
|
7800
|
-
|
|
7999
|
+
ariaLabel: i18n.openPreview,
|
|
7801
8000
|
title: i18n.openPreview,
|
|
7802
8001
|
children: [
|
|
7803
8002
|
/* @__PURE__ */ jsx(Eye, { "aria-hidden": "true" }),
|
|
@@ -8151,6 +8350,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8151
8350
|
});
|
|
8152
8351
|
};
|
|
8153
8352
|
onLeftSelectRef.current = onLeftSelect;
|
|
8353
|
+
onCreateItemDraftRef.current = onItemCreate;
|
|
8154
8354
|
return /* @__PURE__ */ jsx(RuleLabelLookupProvider, { value: ruleLabelLookup, children: /* @__PURE__ */ jsxs(
|
|
8155
8355
|
"div",
|
|
8156
8356
|
{
|
|
@@ -8179,7 +8379,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8179
8379
|
}
|
|
8180
8380
|
);
|
|
8181
8381
|
})(),
|
|
8182
|
-
/* @__PURE__ */ jsxs("div", { className: "px-
|
|
8382
|
+
/* @__PURE__ */ jsxs("div", { className: "px-2 pt-2 space-y-2", children: [
|
|
8183
8383
|
intro && !dismissed && !(headerWillRender && resolvedReopenAffordance === "header") && /* @__PURE__ */ jsx(
|
|
8184
8384
|
IntroCard,
|
|
8185
8385
|
{
|
|
@@ -8318,6 +8518,8 @@ function RecordsAdminShellInner(props) {
|
|
|
8318
8518
|
onSelect: onItemOpen,
|
|
8319
8519
|
dirtyKeys,
|
|
8320
8520
|
errorKeys,
|
|
8521
|
+
contextKind: activeScope === "rule" ? "Rule" : activeScope === "product" ? "Product" : activeScope === "collection" ? "Global" : activeScope === "all" ? "All records" : activeScope === "variant" ? "Variant" : activeScope === "batch" ? "Batch" : activeScope === "facet" ? "Facet" : void 0,
|
|
8522
|
+
contextSummary: activeScope === "rule" ? activeRuleSummary : activeScope === "product" ? editorHeaderLabel ?? null : null,
|
|
8321
8523
|
i18n
|
|
8322
8524
|
}
|
|
8323
8525
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -8491,6 +8693,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8491
8693
|
),
|
|
8492
8694
|
renderGroupActions: renderRuleGroupActions,
|
|
8493
8695
|
rowClipboard,
|
|
8696
|
+
rowActions: wrappedRecordActions,
|
|
8494
8697
|
i18n
|
|
8495
8698
|
}
|
|
8496
8699
|
),
|
|
@@ -8589,6 +8792,8 @@ function RecordsAdminShellInner(props) {
|
|
|
8589
8792
|
itemColumns,
|
|
8590
8793
|
cardSize: itemCardSize,
|
|
8591
8794
|
ruleSummary: activeRuleSummary,
|
|
8795
|
+
rowActions: wrappedRecordActions,
|
|
8796
|
+
rowClipboard,
|
|
8592
8797
|
i18n
|
|
8593
8798
|
}
|
|
8594
8799
|
),
|
|
@@ -8675,7 +8880,41 @@ var RecordBrowser = ({
|
|
|
8675
8880
|
scopesLoading,
|
|
8676
8881
|
i18n
|
|
8677
8882
|
}) => {
|
|
8678
|
-
|
|
8883
|
+
const rootRef = useRef(null);
|
|
8884
|
+
const searchRef = useRef(null);
|
|
8885
|
+
useEffect(() => {
|
|
8886
|
+
const root = rootRef.current;
|
|
8887
|
+
if (!root) return;
|
|
8888
|
+
const handler = (e) => {
|
|
8889
|
+
if (e.key !== "/" || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
8890
|
+
const target = e.target;
|
|
8891
|
+
if (!target || !root.contains(target)) return;
|
|
8892
|
+
const tag = target.tagName;
|
|
8893
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable) return;
|
|
8894
|
+
e.preventDefault();
|
|
8895
|
+
searchRef.current?.focus();
|
|
8896
|
+
searchRef.current?.select();
|
|
8897
|
+
};
|
|
8898
|
+
root.addEventListener("keydown", handler);
|
|
8899
|
+
return () => root.removeEventListener("keydown", handler);
|
|
8900
|
+
}, []);
|
|
8901
|
+
const onSearchKeyDown = (e) => {
|
|
8902
|
+
if (e.key === "Escape") {
|
|
8903
|
+
if (search) {
|
|
8904
|
+
e.preventDefault();
|
|
8905
|
+
onSearchChange("");
|
|
8906
|
+
} else {
|
|
8907
|
+
e.currentTarget.blur();
|
|
8908
|
+
}
|
|
8909
|
+
} else if (e.key === "ArrowDown") {
|
|
8910
|
+
const first = rootRef.current?.querySelector("button.ra-row-hit");
|
|
8911
|
+
if (first) {
|
|
8912
|
+
e.preventDefault();
|
|
8913
|
+
first.focus();
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8916
|
+
};
|
|
8917
|
+
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "flex flex-col h-full", style: { background: "hsl(var(--ra-surface))" }, children: [
|
|
8679
8918
|
/* @__PURE__ */ jsx(ScopeTabs, { scopes, active: activeScope, onChange: onActiveScopeChange, loading: scopesLoading }),
|
|
8680
8919
|
/* @__PURE__ */ jsxs("div", { className: "p-3 space-y-2.5 border-b", style: { borderColor: "hsl(var(--ra-border))" }, children: [
|
|
8681
8920
|
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
@@ -8683,9 +8922,11 @@ var RecordBrowser = ({
|
|
|
8683
8922
|
/* @__PURE__ */ jsx(
|
|
8684
8923
|
"input",
|
|
8685
8924
|
{
|
|
8925
|
+
ref: searchRef,
|
|
8686
8926
|
type: "text",
|
|
8687
8927
|
value: search,
|
|
8688
8928
|
onChange: (e) => onSearchChange(e.target.value),
|
|
8929
|
+
onKeyDown: onSearchKeyDown,
|
|
8689
8930
|
placeholder: i18n.searchPlaceholder,
|
|
8690
8931
|
className: "w-full pl-8 pr-3 py-1.5 text-xs rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
8691
8932
|
style: {
|
|
@@ -8720,7 +8961,7 @@ var RecordBrowser = ({
|
|
|
8720
8961
|
};
|
|
8721
8962
|
var initials2 = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
|
|
8722
8963
|
var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
|
|
8723
|
-
const { selected, onSelect, isDirty, hasError, onCopy,
|
|
8964
|
+
const { selected, onSelect, isDirty, hasError, onCopy, onDuplicate, actions } = ctx;
|
|
8724
8965
|
const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
|
|
8725
8966
|
return /* @__PURE__ */ jsxs(
|
|
8726
8967
|
"button",
|
|
@@ -8781,20 +9022,15 @@ var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
|
|
|
8781
9022
|
/* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
|
|
8782
9023
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
|
|
8783
9024
|
/* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
|
|
8784
|
-
(onCopy ||
|
|
9025
|
+
(onCopy || onDuplicate || actions && actions.length > 0) && /* @__PURE__ */ jsx(
|
|
8785
9026
|
RowContextMenu,
|
|
8786
9027
|
{
|
|
8787
9028
|
onCopy,
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
pasteWillReplace,
|
|
8791
|
-
pasteSourceLabel: clipboardSourceLabel,
|
|
9029
|
+
onDuplicate,
|
|
9030
|
+
actions,
|
|
8792
9031
|
i18n: {
|
|
8793
9032
|
copy: DEFAULT_I18N.copy,
|
|
8794
|
-
|
|
8795
|
-
pasteFrom: DEFAULT_I18N.pasteFrom,
|
|
8796
|
-
pasteReplace: DEFAULT_I18N.pasteReplace,
|
|
8797
|
-
clipboardEmpty: DEFAULT_I18N.clipboardEmpty
|
|
9033
|
+
duplicateAction: DEFAULT_I18N.duplicateAction
|
|
8798
9034
|
}
|
|
8799
9035
|
}
|
|
8800
9036
|
)
|