@proveanything/smartlinks-utils-ui 0.3.8 → 0.3.11
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-3BLWNYM4.js +28 -0
- package/dist/chunk-3BLWNYM4.js.map +1 -0
- package/dist/chunk-TY2UIZ24.js +172 -0
- package/dist/chunk-TY2UIZ24.js.map +1 -0
- package/dist/components/AssetPicker/index.js +1 -1
- package/dist/components/ConditionsEditor/index.js +1 -1
- package/dist/components/FontPicker/index.js +1 -1
- package/dist/components/IconPicker/index.js +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +680 -49
- package/dist/components/RecordsAdmin/index.js +1627 -424
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/records-66QWR67J.js +3 -0
- package/dist/records-66QWR67J.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-NIAIQRFC.js +0 -28
- package/dist/chunk-NIAIQRFC.js.map +0 -1
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import { styleInject } from '../../chunk-
|
|
1
|
+
import { styleInject } from '../../chunk-3BLWNYM4.js';
|
|
2
2
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
3
|
+
import { listRecords, parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, upsertRecord, deleteRecord } from '../../chunk-TY2UIZ24.js';
|
|
4
|
+
export { bulkDelete, bulkUpsert, deleteRecord, getRecordByRef, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-TY2UIZ24.js';
|
|
3
5
|
import { createContext, useMemo, useState, useEffect, useCallback, useRef, useContext, createElement } from 'react';
|
|
4
|
-
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, Globe, Tag, Boxes, Layers, Package, Rows3,
|
|
6
|
+
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, Globe, Tag, Boxes, Layers, Package, Rows3, List, ChevronRight, Eraser, ClipboardPaste, Box, X, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, Search, CornerDownLeft, Circle, AlertCircle, Undo2, Save } from 'lucide-react';
|
|
5
7
|
import { useQueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
|
6
8
|
import { createPortal } from 'react-dom';
|
|
7
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
10
|
|
|
9
11
|
var DEFAULT_ICONS = {
|
|
10
|
-
scope: {
|
|
12
|
+
scope: {
|
|
13
|
+
collection: Globe,
|
|
14
|
+
product: Package,
|
|
15
|
+
variant: Layers,
|
|
16
|
+
batch: Boxes,
|
|
17
|
+
facet: Tag,
|
|
18
|
+
universal: Globe
|
|
19
|
+
},
|
|
11
20
|
status: { own: CheckCircle2, inherited: ArrowDownLeft, missing: CircleDashed },
|
|
12
21
|
action: {
|
|
13
22
|
add: Plus,
|
|
@@ -86,18 +95,49 @@ var DEFAULT_I18N = {
|
|
|
86
95
|
unsavedPromptSave: "Save & continue",
|
|
87
96
|
unsavedBannerBody: "Unsaved changes on {name}",
|
|
88
97
|
presentationList: "List",
|
|
89
|
-
presentationGrid: "Grid",
|
|
90
|
-
presentationGallery: "Gallery",
|
|
91
98
|
presentationCompact: "Compact",
|
|
99
|
+
itemViewTable: "Table",
|
|
100
|
+
itemViewCards: "Cards",
|
|
101
|
+
itemViewGallery: "Gallery",
|
|
92
102
|
newItem: "New item",
|
|
93
103
|
noItemsTitle: "No items yet",
|
|
94
104
|
noItemsBody: "Create your first item to get started.",
|
|
105
|
+
backToList: "Back to list",
|
|
106
|
+
prevItem: "Previous",
|
|
107
|
+
nextItem: "Next",
|
|
108
|
+
itemListTitle: "Items",
|
|
109
|
+
itemColumnLabel: "Name",
|
|
110
|
+
itemColumnUpdated: "Updated",
|
|
111
|
+
itemActions: "Actions",
|
|
112
|
+
backToScopes: "\u2190 All scopes",
|
|
113
|
+
siblingsHeading: "Items in this scope",
|
|
95
114
|
railEmptyTitle: "No records yet",
|
|
96
|
-
railEmptyBody: "Records you create will appear here."
|
|
115
|
+
railEmptyBody: "Records you create will appear here.",
|
|
116
|
+
copy: "Copy",
|
|
117
|
+
paste: "Paste",
|
|
118
|
+
pasteFrom: "Paste from {name}",
|
|
119
|
+
pasteReplace: "Paste (replace)",
|
|
120
|
+
clipboardEmpty: "Nothing to paste",
|
|
121
|
+
copyToast: "Copied {name}. Pick a destination to paste.",
|
|
122
|
+
pasteToast: "Pasted from {name}. Review and Save.",
|
|
123
|
+
pasteConfirmTitle: "Replace existing values?",
|
|
124
|
+
pasteConfirmBody: "{destination} already has saved values. Replace them with the copied values?",
|
|
125
|
+
pasteConfirmReplace: "Replace",
|
|
126
|
+
pasteConfirmCancel: "Cancel",
|
|
127
|
+
pasteWarnTitle: "Cross-scope paste",
|
|
128
|
+
pasteWarnContinue: "Continue"
|
|
97
129
|
};
|
|
98
130
|
|
|
99
131
|
// src/components/RecordsAdmin/types/presentation.ts
|
|
100
|
-
var ALL_PRESENTATIONS = ["list", "
|
|
132
|
+
var ALL_PRESENTATIONS = ["list", "compact"];
|
|
133
|
+
var ALL_ITEM_VIEWS = ["table", "cards", "gallery"];
|
|
134
|
+
|
|
135
|
+
// src/components/RecordsAdmin/types/deepLink.ts
|
|
136
|
+
var DEFAULT_DEEP_LINK_PARAM_NAMES = {
|
|
137
|
+
item: "item",
|
|
138
|
+
scope: "scope",
|
|
139
|
+
view: "view"
|
|
140
|
+
};
|
|
101
141
|
|
|
102
142
|
// src/components/RecordsAdmin/data/refs.ts
|
|
103
143
|
var KIND_KEYS = {
|
|
@@ -126,6 +166,9 @@ var parseRef = (raw) => {
|
|
|
126
166
|
} else {
|
|
127
167
|
parsed.facetId = id;
|
|
128
168
|
}
|
|
169
|
+
} else if (k === "item") {
|
|
170
|
+
parsed.itemId = id;
|
|
171
|
+
continue;
|
|
129
172
|
} else if (k in KIND_KEYS) {
|
|
130
173
|
parsed[KIND_KEYS[k]] = id;
|
|
131
174
|
}
|
|
@@ -143,6 +186,7 @@ var buildRef = (a) => {
|
|
|
143
186
|
if (a.variantId) parts.push(`variant:${a.variantId}`);
|
|
144
187
|
if (a.batchId) parts.push(`batch:${a.batchId}`);
|
|
145
188
|
if (a.proofId) parts.push(`proof:${a.proofId}`);
|
|
189
|
+
if (a.itemId) parts.push(`item:${a.itemId}`);
|
|
146
190
|
return parts.join("/");
|
|
147
191
|
};
|
|
148
192
|
var resolutionChain = (target, supportedScopes) => {
|
|
@@ -159,173 +203,23 @@ var resolutionChain = (target, supportedScopes) => {
|
|
|
159
203
|
if (supportedScopes.includes("facet") && target.facetId) {
|
|
160
204
|
chain.push(buildRef({ facetId: target.facetId, facetValue: target.facetValue }));
|
|
161
205
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// src/components/RecordsAdmin/data/scopeBridge.ts
|
|
166
|
-
var parsedRefToScope = (ref) => {
|
|
167
|
-
const scope = {};
|
|
168
|
-
if (ref.productId) scope.productId = ref.productId;
|
|
169
|
-
if (ref.variantId) scope.variantId = ref.variantId;
|
|
170
|
-
if (ref.batchId) scope.batchId = ref.batchId;
|
|
171
|
-
if (ref.proofId) scope.proofId = ref.proofId;
|
|
172
|
-
if (ref.facetId) {
|
|
173
|
-
scope.facets = [{
|
|
174
|
-
key: ref.facetId,
|
|
175
|
-
valueKeys: ref.facetValue ? [ref.facetValue] : []
|
|
176
|
-
}];
|
|
177
|
-
}
|
|
178
|
-
return scope;
|
|
179
|
-
};
|
|
180
|
-
var parsedRefToTarget = (ref) => {
|
|
181
|
-
const target = {};
|
|
182
|
-
if (ref.productId) target.productId = ref.productId;
|
|
183
|
-
if (ref.variantId) target.variantId = ref.variantId;
|
|
184
|
-
if (ref.batchId) target.batchId = ref.batchId;
|
|
185
|
-
if (ref.proofId) target.proofId = ref.proofId;
|
|
186
|
-
if (ref.facetId && ref.facetValue) {
|
|
187
|
-
target.facets = { [ref.facetId]: [ref.facetValue] };
|
|
188
|
-
}
|
|
189
|
-
return target;
|
|
190
|
-
};
|
|
191
|
-
var scopesEqual = (a, b) => {
|
|
192
|
-
if ((a.productId ?? null) !== (b.productId ?? null)) return false;
|
|
193
|
-
if ((a.variantId ?? null) !== (b.variantId ?? null)) return false;
|
|
194
|
-
if ((a.batchId ?? null) !== (b.batchId ?? null)) return false;
|
|
195
|
-
if ((a.proofId ?? null) !== (b.proofId ?? null)) return false;
|
|
196
|
-
const af = a.facets ?? [];
|
|
197
|
-
const bf = b.facets ?? [];
|
|
198
|
-
if (af.length !== bf.length) return false;
|
|
199
|
-
const norm = (xs) => xs.map((f) => `${f.key}:${[...f.valueKeys].sort().join(",")}`).sort().join("|");
|
|
200
|
-
return norm(af) === norm(bf);
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
// src/components/RecordsAdmin/data/records.ts
|
|
204
|
-
var listRecords = async (ctx, params = {}) => {
|
|
205
|
-
const { limit = 100, offset, ref, refPrefix, q, sort } = params;
|
|
206
|
-
const res = await ctx.SL.app.records.list(
|
|
207
|
-
ctx.collectionId,
|
|
208
|
-
ctx.appId,
|
|
209
|
-
{
|
|
210
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
211
|
-
limit,
|
|
212
|
-
offset,
|
|
213
|
-
ref,
|
|
214
|
-
refPrefix,
|
|
215
|
-
q,
|
|
216
|
-
sort
|
|
217
|
-
},
|
|
218
|
-
true
|
|
219
|
-
);
|
|
220
|
-
return {
|
|
221
|
-
data: res?.data ?? [],
|
|
222
|
-
total: res?.pagination?.total ?? (res?.data?.length ?? 0),
|
|
223
|
-
hasMore: res?.pagination?.hasMore ?? false
|
|
224
|
-
};
|
|
225
|
-
};
|
|
226
|
-
var getRecordByRef = async (ctx, ref) => {
|
|
227
|
-
const res = await ctx.SL.app.records.list(
|
|
228
|
-
ctx.collectionId,
|
|
229
|
-
ctx.appId,
|
|
230
|
-
{ ...ctx.recordType ? { recordType: ctx.recordType } : {}, ref, limit: 1 },
|
|
231
|
-
true
|
|
232
|
-
);
|
|
233
|
-
return res?.data?.[0] ?? null;
|
|
234
|
-
};
|
|
235
|
-
var upsertRecord = async (ctx, write) => {
|
|
236
|
-
const ref = write.ref ?? deriveRefFromScope(write.scope);
|
|
237
|
-
const res = await ctx.SL.app.records.upsert(ctx.collectionId, ctx.appId, {
|
|
238
|
-
ref,
|
|
239
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
240
|
-
scope: write.scope,
|
|
241
|
-
data: write.data,
|
|
242
|
-
status: write.status,
|
|
243
|
-
startsAt: write.startsAt,
|
|
244
|
-
expiresAt: write.expiresAt,
|
|
245
|
-
customId: write.customId,
|
|
246
|
-
sourceSystem: write.sourceSystem
|
|
247
|
-
});
|
|
248
|
-
return { record: res, isCreate: !!res?.created };
|
|
249
|
-
};
|
|
250
|
-
var deleteRecord = async (ctx, ref) => {
|
|
251
|
-
const existing = await getRecordByRef(ctx, ref).catch(() => null);
|
|
252
|
-
if (!existing) return false;
|
|
253
|
-
await ctx.SL.app.records.remove(ctx.collectionId, ctx.appId, existing.id, true);
|
|
254
|
-
return true;
|
|
255
|
-
};
|
|
256
|
-
var restoreRecord = async (ctx, recordId) => ctx.SL.app.records.restore(ctx.collectionId, ctx.appId, recordId);
|
|
257
|
-
var matchRecords = async (ctx, target, opts = {}) => ctx.SL.app.records.match(
|
|
258
|
-
ctx.collectionId,
|
|
259
|
-
ctx.appId,
|
|
260
|
-
{
|
|
261
|
-
target,
|
|
262
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
263
|
-
strategy: opts.strategy ?? "all",
|
|
264
|
-
at: opts.at,
|
|
265
|
-
includeScheduled: opts.includeScheduled,
|
|
266
|
-
includeExpired: opts.includeExpired,
|
|
267
|
-
limit: opts.limit
|
|
268
|
-
},
|
|
269
|
-
true
|
|
270
|
-
);
|
|
271
|
-
var bulkUpsert = async (ctx, entries) => {
|
|
272
|
-
const CHUNK = 500;
|
|
273
|
-
let saved = 0;
|
|
274
|
-
let failed = 0;
|
|
275
|
-
for (let i = 0; i < entries.length; i += CHUNK) {
|
|
276
|
-
const slice = entries.slice(i, i + CHUNK);
|
|
277
|
-
const items = slice.map((e) => ({
|
|
278
|
-
ref: e.ref ?? deriveRefFromScope(e.scope),
|
|
279
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
280
|
-
scope: e.scope,
|
|
281
|
-
data: e.data,
|
|
282
|
-
status: e.status
|
|
283
|
-
}));
|
|
284
|
-
const res = await ctx.SL.app.records.bulkUpsert(ctx.collectionId, ctx.appId, items).catch(() => ({ saved: 0, failed: items.length }));
|
|
285
|
-
saved += res.saved ?? 0;
|
|
286
|
-
failed += res.failed ?? 0;
|
|
206
|
+
if (supportedScopes.includes("collection")) {
|
|
207
|
+
chain.push("");
|
|
287
208
|
}
|
|
288
|
-
return
|
|
209
|
+
return Array.from(new Set(chain));
|
|
289
210
|
};
|
|
290
|
-
var
|
|
291
|
-
if ("
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
);
|
|
297
|
-
return { removed: res.deleted ?? 0 };
|
|
298
|
-
}
|
|
299
|
-
const CHUNK = 1e3;
|
|
300
|
-
let removed = 0;
|
|
301
|
-
for (let i = 0; i < input.refs.length; i += CHUNK) {
|
|
302
|
-
const slice = input.refs.slice(i, i + CHUNK);
|
|
303
|
-
const res = await ctx.SL.app.records.bulkDelete(
|
|
304
|
-
ctx.collectionId,
|
|
305
|
-
ctx.appId,
|
|
306
|
-
{ refs: slice, ...ctx.recordType ? { recordType: ctx.recordType } : {} }
|
|
307
|
-
);
|
|
308
|
-
removed += res.deleted ?? 0;
|
|
211
|
+
var splitItemRef = (raw) => {
|
|
212
|
+
if (!raw) return { scopeRef: "" };
|
|
213
|
+
const segs = raw.split("/").filter(Boolean);
|
|
214
|
+
const last = segs[segs.length - 1];
|
|
215
|
+
if (last && last.startsWith("item:")) {
|
|
216
|
+
return { scopeRef: segs.slice(0, -1).join("/"), itemId: last.slice("item:".length) };
|
|
309
217
|
}
|
|
310
|
-
return {
|
|
218
|
+
return { scopeRef: raw };
|
|
311
219
|
};
|
|
312
|
-
var
|
|
313
|
-
|
|
314
|
-
if (scope.facets && scope.facets.length > 0) {
|
|
315
|
-
const sorted = [...scope.facets].sort((a, b) => a.key.localeCompare(b.key));
|
|
316
|
-
for (const f of sorted) {
|
|
317
|
-
const vals = [...f.valueKeys].sort().join(",");
|
|
318
|
-
parts.push(vals ? `facet:${f.key}=${vals}` : `facet:${f.key}`);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
if (scope.productId) parts.push(`product:${scope.productId}`);
|
|
322
|
-
if (scope.variantId) parts.push(`variant:${scope.variantId}`);
|
|
323
|
-
if (scope.batchId) parts.push(`batch:${scope.batchId}`);
|
|
324
|
-
if (scope.proofId) parts.push(`proof:${scope.proofId}`);
|
|
325
|
-
return parts.join("/");
|
|
220
|
+
var buildItemRef = (scopeRef, itemId) => {
|
|
221
|
+
return scopeRef ? `${scopeRef}/item:${itemId}` : `item:${itemId}`;
|
|
326
222
|
};
|
|
327
|
-
|
|
328
|
-
// src/components/RecordsAdmin/hooks/useRecordList.ts
|
|
329
223
|
var defaultClassify = (r) => {
|
|
330
224
|
if (!r.data) return "empty";
|
|
331
225
|
const keys = Object.keys(r.data);
|
|
@@ -366,7 +260,7 @@ var useRecordList = (args) => {
|
|
|
366
260
|
scopeKind,
|
|
367
261
|
search = "",
|
|
368
262
|
filter = "all",
|
|
369
|
-
classify,
|
|
263
|
+
classify: classify2,
|
|
370
264
|
enabled = true,
|
|
371
265
|
scaffolder,
|
|
372
266
|
contextScope,
|
|
@@ -401,9 +295,9 @@ var useRecordList = (args) => {
|
|
|
401
295
|
const [scaffolded, setScaffolded] = useState(null);
|
|
402
296
|
const rawItems = useMemo(() => {
|
|
403
297
|
const all = query.data?.pages.flatMap((p) => p.data) ?? [];
|
|
404
|
-
const cls =
|
|
298
|
+
const cls = classify2 ?? defaultClassify;
|
|
405
299
|
return all.map(toSummary).filter((s) => matchesScope(scopeKind, s.scope)).filter((s) => matchesContext(s.scope, contextScope)).map((s) => ({ ...s, status: cls(s) }));
|
|
406
|
-
}, [query.data, scopeKind,
|
|
300
|
+
}, [query.data, scopeKind, classify2, contextScope]);
|
|
407
301
|
useEffect(() => {
|
|
408
302
|
if (!scaffolder) {
|
|
409
303
|
setScaffolded(null);
|
|
@@ -1187,7 +1081,7 @@ var ConfirmDialog = ({
|
|
|
1187
1081
|
children: discardLabel
|
|
1188
1082
|
}
|
|
1189
1083
|
),
|
|
1190
|
-
/* @__PURE__ */ jsx(
|
|
1084
|
+
saveLabel ? /* @__PURE__ */ jsx(
|
|
1191
1085
|
"button",
|
|
1192
1086
|
{
|
|
1193
1087
|
type: "button",
|
|
@@ -1196,7 +1090,7 @@ var ConfirmDialog = ({
|
|
|
1196
1090
|
onClick: () => onChoice("save"),
|
|
1197
1091
|
children: saveLabel
|
|
1198
1092
|
}
|
|
1199
|
-
)
|
|
1093
|
+
) : null
|
|
1200
1094
|
] })
|
|
1201
1095
|
]
|
|
1202
1096
|
}
|
|
@@ -1253,7 +1147,124 @@ var useConfirmDialog = () => {
|
|
|
1253
1147
|
)
|
|
1254
1148
|
};
|
|
1255
1149
|
};
|
|
1150
|
+
var DEFAULTS2 = {
|
|
1151
|
+
title: "Replace existing values?",
|
|
1152
|
+
body: "This destination already has saved values. Replace them?",
|
|
1153
|
+
confirmLabel: "Replace",
|
|
1154
|
+
cancelLabel: "Cancel"
|
|
1155
|
+
};
|
|
1156
|
+
var usePasteConfirm = () => {
|
|
1157
|
+
const [open, setOpen] = useState(false);
|
|
1158
|
+
const [state, setState] = useState(DEFAULTS2);
|
|
1159
|
+
const resolverRef = useRef(null);
|
|
1160
|
+
const confirm = useCallback((i18n) => {
|
|
1161
|
+
setState({ ...DEFAULTS2, ...i18n ?? {} });
|
|
1162
|
+
setOpen(true);
|
|
1163
|
+
return new Promise((resolve) => {
|
|
1164
|
+
resolverRef.current = resolve;
|
|
1165
|
+
});
|
|
1166
|
+
}, []);
|
|
1167
|
+
const handleChoice = useCallback((choice) => {
|
|
1168
|
+
setOpen(false);
|
|
1169
|
+
const r = resolverRef.current;
|
|
1170
|
+
resolverRef.current = null;
|
|
1171
|
+
r?.(choice === "discard");
|
|
1172
|
+
}, []);
|
|
1173
|
+
return {
|
|
1174
|
+
confirm,
|
|
1175
|
+
dialog: /* @__PURE__ */ jsx(
|
|
1176
|
+
ConfirmDialog,
|
|
1177
|
+
{
|
|
1178
|
+
open,
|
|
1179
|
+
title: state.title,
|
|
1180
|
+
body: state.body,
|
|
1181
|
+
saveLabel: "",
|
|
1182
|
+
discardLabel: state.confirmLabel,
|
|
1183
|
+
cancelLabel: state.cancelLabel,
|
|
1184
|
+
onChoice: handleChoice
|
|
1185
|
+
}
|
|
1186
|
+
)
|
|
1187
|
+
};
|
|
1188
|
+
};
|
|
1189
|
+
var stores = /* @__PURE__ */ new Map();
|
|
1190
|
+
var storageKey = (key) => `ra:clipboard:${key}`;
|
|
1191
|
+
var getStore = (key) => {
|
|
1192
|
+
let s = stores.get(key);
|
|
1193
|
+
if (!s) {
|
|
1194
|
+
s = { entry: null, listeners: /* @__PURE__ */ new Set() };
|
|
1195
|
+
if (typeof window !== "undefined") {
|
|
1196
|
+
try {
|
|
1197
|
+
const raw = window.sessionStorage.getItem(storageKey(key));
|
|
1198
|
+
if (raw) s.entry = JSON.parse(raw);
|
|
1199
|
+
} catch {
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
stores.set(key, s);
|
|
1203
|
+
}
|
|
1204
|
+
return s;
|
|
1205
|
+
};
|
|
1206
|
+
var persist = (key, entry) => {
|
|
1207
|
+
if (typeof window === "undefined") return;
|
|
1208
|
+
try {
|
|
1209
|
+
if (entry) window.sessionStorage.setItem(storageKey(key), JSON.stringify(entry));
|
|
1210
|
+
else window.sessionStorage.removeItem(storageKey(key));
|
|
1211
|
+
} catch {
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
var notify = (store) => {
|
|
1215
|
+
store.listeners.forEach((l) => l());
|
|
1216
|
+
};
|
|
1217
|
+
var composeKey = (appId, recordType) => `${appId}::${recordType}`;
|
|
1218
|
+
function useRecordClipboard(args) {
|
|
1219
|
+
const key = composeKey(args.appId, args.recordType);
|
|
1220
|
+
const store = getStore(key);
|
|
1221
|
+
const [entry, setEntry] = useState(
|
|
1222
|
+
store.entry
|
|
1223
|
+
);
|
|
1224
|
+
useEffect(() => {
|
|
1225
|
+
const listener = () => setEntry(store.entry);
|
|
1226
|
+
store.listeners.add(listener);
|
|
1227
|
+
listener();
|
|
1228
|
+
return () => {
|
|
1229
|
+
store.listeners.delete(listener);
|
|
1230
|
+
};
|
|
1231
|
+
}, [store]);
|
|
1232
|
+
const set = useCallback((next) => {
|
|
1233
|
+
const full = { ...next, copiedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
1234
|
+
store.entry = full;
|
|
1235
|
+
persist(key, full);
|
|
1236
|
+
notify(store);
|
|
1237
|
+
}, [store, key]);
|
|
1238
|
+
const clear = useCallback(() => {
|
|
1239
|
+
store.entry = null;
|
|
1240
|
+
persist(key, null);
|
|
1241
|
+
notify(store);
|
|
1242
|
+
}, [store, key]);
|
|
1243
|
+
return { entry, hasEntry: entry != null, set, clear };
|
|
1244
|
+
}
|
|
1245
|
+
function checkPasteCompatibility(source, destination) {
|
|
1246
|
+
const from = source.kind;
|
|
1247
|
+
const to = destination.kind;
|
|
1248
|
+
if (from === to) return { status: "allowed" };
|
|
1249
|
+
if ((from === "variant" || from === "batch") && to === "product") {
|
|
1250
|
+
return { status: "warn", reason: "This will overwrite product-level values." };
|
|
1251
|
+
}
|
|
1252
|
+
return { status: "allowed" };
|
|
1253
|
+
}
|
|
1254
|
+
function cloneValue(value) {
|
|
1255
|
+
if (value == null) return value;
|
|
1256
|
+
try {
|
|
1257
|
+
return structuredClone(value);
|
|
1258
|
+
} catch {
|
|
1259
|
+
try {
|
|
1260
|
+
return JSON.parse(JSON.stringify(value));
|
|
1261
|
+
} catch {
|
|
1262
|
+
return value;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1256
1266
|
var LABELS = {
|
|
1267
|
+
collection: "Global",
|
|
1257
1268
|
product: "Products",
|
|
1258
1269
|
facet: "Shared",
|
|
1259
1270
|
variant: "Variants",
|
|
@@ -1332,8 +1343,90 @@ var StatusDot = ({ source, status, className }) => {
|
|
|
1332
1343
|
else if (source === "inherited" || status === "partial") cls = "ra-status-shared";
|
|
1333
1344
|
return /* @__PURE__ */ jsx("span", { className: cn("ra-status-dot", cls, className), "aria-hidden": "true" });
|
|
1334
1345
|
};
|
|
1346
|
+
var RowContextMenu = ({
|
|
1347
|
+
onCopy,
|
|
1348
|
+
onPaste,
|
|
1349
|
+
canPaste,
|
|
1350
|
+
pasteWillReplace,
|
|
1351
|
+
pasteSourceLabel,
|
|
1352
|
+
i18n
|
|
1353
|
+
}) => {
|
|
1354
|
+
const [open, setOpen] = useState(false);
|
|
1355
|
+
const wrapperRef = useRef(null);
|
|
1356
|
+
useEffect(() => {
|
|
1357
|
+
if (!open) return;
|
|
1358
|
+
const onDoc = (e) => {
|
|
1359
|
+
if (!wrapperRef.current?.contains(e.target)) setOpen(false);
|
|
1360
|
+
};
|
|
1361
|
+
const onKey = (e) => {
|
|
1362
|
+
if (e.key === "Escape") setOpen(false);
|
|
1363
|
+
};
|
|
1364
|
+
document.addEventListener("mousedown", onDoc);
|
|
1365
|
+
document.addEventListener("keydown", onKey);
|
|
1366
|
+
return () => {
|
|
1367
|
+
document.removeEventListener("mousedown", onDoc);
|
|
1368
|
+
document.removeEventListener("keydown", onKey);
|
|
1369
|
+
};
|
|
1370
|
+
}, [open]);
|
|
1371
|
+
if (!onCopy && !onPaste) return null;
|
|
1372
|
+
const pasteLabel = !canPaste ? i18n.clipboardEmpty : pasteSourceLabel ? i18n.pasteFrom.replace("{name}", pasteSourceLabel) : pasteWillReplace ? i18n.pasteReplace : i18n.paste;
|
|
1373
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: "ra-row-menu-wrap relative", children: [
|
|
1374
|
+
/* @__PURE__ */ jsx(
|
|
1375
|
+
"button",
|
|
1376
|
+
{
|
|
1377
|
+
type: "button",
|
|
1378
|
+
className: "ra-row-menu-trigger",
|
|
1379
|
+
"aria-label": "Row actions",
|
|
1380
|
+
"aria-haspopup": "menu",
|
|
1381
|
+
"aria-expanded": open,
|
|
1382
|
+
onClick: (e) => {
|
|
1383
|
+
e.stopPropagation();
|
|
1384
|
+
setOpen((v) => !v);
|
|
1385
|
+
},
|
|
1386
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "w-3.5 h-3.5", "aria-hidden": "true" })
|
|
1387
|
+
}
|
|
1388
|
+
),
|
|
1389
|
+
open && /* @__PURE__ */ jsxs("div", { role: "menu", className: "ra-row-menu", onClick: (e) => e.stopPropagation(), children: [
|
|
1390
|
+
onCopy && /* @__PURE__ */ jsxs(
|
|
1391
|
+
"button",
|
|
1392
|
+
{
|
|
1393
|
+
type: "button",
|
|
1394
|
+
role: "menuitem",
|
|
1395
|
+
className: "ra-row-menu-item",
|
|
1396
|
+
onClick: (e) => {
|
|
1397
|
+
e.stopPropagation();
|
|
1398
|
+
setOpen(false);
|
|
1399
|
+
onCopy();
|
|
1400
|
+
},
|
|
1401
|
+
children: [
|
|
1402
|
+
/* @__PURE__ */ jsx(Copy, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
1403
|
+
/* @__PURE__ */ jsx("span", { children: i18n.copy })
|
|
1404
|
+
]
|
|
1405
|
+
}
|
|
1406
|
+
),
|
|
1407
|
+
onPaste && /* @__PURE__ */ jsxs(
|
|
1408
|
+
"button",
|
|
1409
|
+
{
|
|
1410
|
+
type: "button",
|
|
1411
|
+
role: "menuitem",
|
|
1412
|
+
className: "ra-row-menu-item",
|
|
1413
|
+
disabled: !canPaste,
|
|
1414
|
+
onClick: (e) => {
|
|
1415
|
+
e.stopPropagation();
|
|
1416
|
+
setOpen(false);
|
|
1417
|
+
if (canPaste) onPaste();
|
|
1418
|
+
},
|
|
1419
|
+
children: [
|
|
1420
|
+
/* @__PURE__ */ jsx(ClipboardPaste, { className: "w-3 h-3", "aria-hidden": "true" }),
|
|
1421
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: pasteLabel })
|
|
1422
|
+
]
|
|
1423
|
+
}
|
|
1424
|
+
)
|
|
1425
|
+
] })
|
|
1426
|
+
] });
|
|
1427
|
+
};
|
|
1335
1428
|
var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
1336
|
-
const { selected, onSelect, isDirty } = ctx;
|
|
1429
|
+
const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
|
|
1337
1430
|
const ScopeIcon = record.scope.kind && record.scope.kind !== "collection" ? DEFAULT_ICONS.scope[record.scope.kind] : DEFAULT_ICONS.scope.product;
|
|
1338
1431
|
return /* @__PURE__ */ jsxs(
|
|
1339
1432
|
"button",
|
|
@@ -1358,69 +1451,24 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
1358
1451
|
"aria-label": "Unsaved changes",
|
|
1359
1452
|
className: "ra-status-dot ra-status-shared shrink-0"
|
|
1360
1453
|
}
|
|
1361
|
-
)
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
);
|
|
1365
|
-
};
|
|
1366
|
-
var initials = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
|
|
1367
|
-
var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
|
|
1368
|
-
const { selected, onSelect, isDirty } = ctx;
|
|
1369
|
-
const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
|
|
1370
|
-
return /* @__PURE__ */ jsxs(
|
|
1371
|
-
"button",
|
|
1372
|
-
{
|
|
1373
|
-
type: "button",
|
|
1374
|
-
onClick: onSelect,
|
|
1375
|
-
className: cn(
|
|
1376
|
-
"group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
|
|
1377
|
-
selected && "ring-2"
|
|
1378
|
-
),
|
|
1379
|
-
style: {
|
|
1380
|
-
background: "hsl(var(--ra-surface))",
|
|
1381
|
-
borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
|
|
1382
|
-
boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
|
|
1383
|
-
},
|
|
1384
|
-
children: [
|
|
1385
|
-
/* @__PURE__ */ jsxs(
|
|
1386
|
-
"div",
|
|
1454
|
+
),
|
|
1455
|
+
(onCopy || onPaste) && /* @__PURE__ */ jsx(
|
|
1456
|
+
RowContextMenu,
|
|
1387
1457
|
{
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
"span",
|
|
1401
|
-
{
|
|
1402
|
-
className: "text-2xl ra-display",
|
|
1403
|
-
style: { color: "hsl(var(--ra-muted-text))" },
|
|
1404
|
-
children: initials(record.label)
|
|
1405
|
-
}
|
|
1406
|
-
),
|
|
1407
|
-
/* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
|
|
1408
|
-
isDirty && /* @__PURE__ */ jsx(
|
|
1409
|
-
"span",
|
|
1410
|
-
{
|
|
1411
|
-
title: "Unsaved changes",
|
|
1412
|
-
"aria-label": "Unsaved changes",
|
|
1413
|
-
className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
|
|
1414
|
-
}
|
|
1415
|
-
)
|
|
1416
|
-
]
|
|
1458
|
+
onCopy,
|
|
1459
|
+
onPaste,
|
|
1460
|
+
canPaste,
|
|
1461
|
+
pasteWillReplace,
|
|
1462
|
+
pasteSourceLabel: clipboardSourceLabel,
|
|
1463
|
+
i18n: {
|
|
1464
|
+
copy: DEFAULT_I18N.copy,
|
|
1465
|
+
paste: DEFAULT_I18N.paste,
|
|
1466
|
+
pasteFrom: DEFAULT_I18N.pasteFrom,
|
|
1467
|
+
pasteReplace: DEFAULT_I18N.pasteReplace,
|
|
1468
|
+
clipboardEmpty: DEFAULT_I18N.clipboardEmpty
|
|
1469
|
+
}
|
|
1417
1470
|
}
|
|
1418
|
-
)
|
|
1419
|
-
/* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
|
|
1420
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: record.label }),
|
|
1421
|
-
variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
|
|
1422
|
-
record.badges && record.badges.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-1 mt-1.5 flex-wrap", children: record.badges.slice(0, 3).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)) })
|
|
1423
|
-
] })
|
|
1471
|
+
)
|
|
1424
1472
|
]
|
|
1425
1473
|
}
|
|
1426
1474
|
);
|
|
@@ -1432,14 +1480,18 @@ var RecordList = ({
|
|
|
1432
1480
|
dirtyRef,
|
|
1433
1481
|
presentation = "list",
|
|
1434
1482
|
renderListRow,
|
|
1435
|
-
|
|
1436
|
-
|
|
1483
|
+
groupBy,
|
|
1484
|
+
rowClipboard
|
|
1437
1485
|
}) => {
|
|
1438
|
-
const buildCtx = (item) =>
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1486
|
+
const buildCtx = (item) => {
|
|
1487
|
+
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
1488
|
+
return {
|
|
1489
|
+
selected: item.ref === selectedRef,
|
|
1490
|
+
onSelect: () => onSelect(item),
|
|
1491
|
+
isDirty: !!dirtyRef && item.ref === dirtyRef,
|
|
1492
|
+
...cb ?? {}
|
|
1493
|
+
};
|
|
1494
|
+
};
|
|
1443
1495
|
const groups = useMemo(() => {
|
|
1444
1496
|
if (!groupBy) return null;
|
|
1445
1497
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -1455,20 +1507,6 @@ var RecordList = ({
|
|
|
1455
1507
|
return orderedKeys.map((k) => buckets.get(k));
|
|
1456
1508
|
}, [items, groupBy]);
|
|
1457
1509
|
const renderItems = (rows) => {
|
|
1458
|
-
if (presentation === "grid" || presentation === "gallery") {
|
|
1459
|
-
const minColPx = presentation === "gallery" ? 200 : 120;
|
|
1460
|
-
return /* @__PURE__ */ jsx(
|
|
1461
|
-
"div",
|
|
1462
|
-
{
|
|
1463
|
-
className: "grid gap-2 p-2",
|
|
1464
|
-
style: { gridTemplateColumns: `repeat(auto-fill, minmax(${minColPx}px, 1fr))` },
|
|
1465
|
-
children: rows.map((item) => {
|
|
1466
|
-
const ctx = buildCtx(item);
|
|
1467
|
-
return /* @__PURE__ */ jsx("div", { children: renderCard ? renderCard(item, ctx) : /* @__PURE__ */ jsx(DefaultRecordCard, { record: item, ctx, variant: presentation }) }, item.ref);
|
|
1468
|
-
})
|
|
1469
|
-
}
|
|
1470
|
-
);
|
|
1471
|
-
}
|
|
1472
1510
|
const compact = presentation === "compact";
|
|
1473
1511
|
return /* @__PURE__ */ jsx("ul", { children: rows.map((item) => {
|
|
1474
1512
|
const ctx = buildCtx(item);
|
|
@@ -1551,18 +1589,12 @@ var ErrorState = ({ error }) => /* @__PURE__ */ jsxs("div", { className: "ra-emp
|
|
|
1551
1589
|
] });
|
|
1552
1590
|
var ICONS = {
|
|
1553
1591
|
list: List,
|
|
1554
|
-
grid: LayoutGrid,
|
|
1555
|
-
gallery: Image,
|
|
1556
1592
|
compact: Rows3
|
|
1557
1593
|
};
|
|
1558
1594
|
var labelFor = (p, i18n) => {
|
|
1559
1595
|
switch (p) {
|
|
1560
1596
|
case "list":
|
|
1561
1597
|
return i18n.presentationList;
|
|
1562
|
-
case "grid":
|
|
1563
|
-
return i18n.presentationGrid;
|
|
1564
|
-
case "gallery":
|
|
1565
|
-
return i18n.presentationGallery;
|
|
1566
1598
|
case "compact":
|
|
1567
1599
|
return i18n.presentationCompact;
|
|
1568
1600
|
}
|
|
@@ -1601,6 +1633,7 @@ var PresentationSwitcher = ({ options, value, onChange, i18n }) => {
|
|
|
1601
1633
|
);
|
|
1602
1634
|
};
|
|
1603
1635
|
var KEY_PREFIX = "smartlinks-ui:records-admin:presentation";
|
|
1636
|
+
var ITEM_VIEW_KEY_PREFIX = "smartlinks-ui:records-admin:item-view";
|
|
1604
1637
|
var safeRead = (key) => {
|
|
1605
1638
|
try {
|
|
1606
1639
|
return typeof window === "undefined" ? null : window.localStorage.getItem(key);
|
|
@@ -1632,46 +1665,235 @@ function usePresentationPref(args) {
|
|
|
1632
1665
|
}, [key]);
|
|
1633
1666
|
return [value, set];
|
|
1634
1667
|
}
|
|
1635
|
-
|
|
1636
|
-
const
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
|
-
const segs = segmentsFor(scope);
|
|
1645
|
-
if (segs.length === 0) return null;
|
|
1646
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": "Scope", className: "flex items-center gap-1 text-xs flex-wrap", style: { color: "hsl(var(--ra-muted-text))" }, children: segs.map((s, i) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
1647
|
-
i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3 opacity-50" }),
|
|
1648
|
-
/* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--ra-text))" }, children: s.label })
|
|
1649
|
-
] }, s.key)) });
|
|
1650
|
-
};
|
|
1651
|
-
var BulkActionsMenu = ({
|
|
1652
|
-
i18n,
|
|
1653
|
-
onApplyToMany,
|
|
1654
|
-
onCopyFrom,
|
|
1655
|
-
onClearMany,
|
|
1656
|
-
onImportCsv,
|
|
1657
|
-
onExportCsv
|
|
1658
|
-
}) => {
|
|
1659
|
-
const [open, setOpen] = useState(false);
|
|
1660
|
-
const ref = useRef(null);
|
|
1668
|
+
function useItemViewPref(args) {
|
|
1669
|
+
const { appId, recordType, options, defaultValue } = args;
|
|
1670
|
+
const key = `${ITEM_VIEW_KEY_PREFIX}:${appId}:${recordType ?? "_default"}`;
|
|
1671
|
+
const initial = () => {
|
|
1672
|
+
const stored = safeRead(key);
|
|
1673
|
+
if (stored && options.includes(stored)) return stored;
|
|
1674
|
+
return options.includes(defaultValue) ? defaultValue : options[0];
|
|
1675
|
+
};
|
|
1676
|
+
const [value, setValue] = useState(initial);
|
|
1661
1677
|
useEffect(() => {
|
|
1662
|
-
if (!
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1678
|
+
if (!options.includes(value)) setValue(options[0]);
|
|
1679
|
+
}, [options, value]);
|
|
1680
|
+
const set = useCallback((next) => {
|
|
1681
|
+
setValue(next);
|
|
1682
|
+
safeWrite(key, next);
|
|
1683
|
+
}, [key]);
|
|
1684
|
+
return [value, set];
|
|
1685
|
+
}
|
|
1686
|
+
var QK_BASE2 = ["records-admin", "collection-items"];
|
|
1687
|
+
var defaultToSummary = (rec, base) => {
|
|
1688
|
+
const data = rec.data;
|
|
1689
|
+
if (!data) return base;
|
|
1690
|
+
const label = data.title ?? data.name ?? data.label ?? data.question ?? base.label;
|
|
1691
|
+
const subtitle = data.subtitle ?? data.summary ?? data.description ?? base.subtitle;
|
|
1692
|
+
const thumbnail = data.thumbnail ?? data.image ?? data.cover ?? base.thumbnail;
|
|
1693
|
+
return { ...base, label, subtitle, thumbnail };
|
|
1694
|
+
};
|
|
1695
|
+
function useCollectionItems(args) {
|
|
1696
|
+
const {
|
|
1697
|
+
ctx,
|
|
1698
|
+
scope,
|
|
1699
|
+
pageSize = 100,
|
|
1700
|
+
toSummary: toSummary2 = defaultToSummary,
|
|
1701
|
+
enabled = true
|
|
1702
|
+
} = args;
|
|
1703
|
+
const queryClient = useQueryClient();
|
|
1704
|
+
const scopeRef = scope?.raw ?? "";
|
|
1705
|
+
const refPrefix = scopeRef ? `${scopeRef}/item:` : "item:";
|
|
1706
|
+
const queryKey = useMemo(
|
|
1707
|
+
() => [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType, scopeRef],
|
|
1708
|
+
[ctx.collectionId, ctx.appId, ctx.recordType, scopeRef]
|
|
1709
|
+
);
|
|
1710
|
+
const query = useInfiniteQuery({
|
|
1711
|
+
queryKey,
|
|
1712
|
+
enabled: enabled && !!scope,
|
|
1713
|
+
initialPageParam: 0,
|
|
1714
|
+
queryFn: async ({ pageParam }) => {
|
|
1715
|
+
const offset = pageParam;
|
|
1716
|
+
const { data, total, hasMore } = await listRecords(ctx, {
|
|
1717
|
+
limit: pageSize,
|
|
1718
|
+
offset,
|
|
1719
|
+
refPrefix
|
|
1720
|
+
});
|
|
1721
|
+
return { data, total, hasMore, nextOffset: offset + data.length };
|
|
1722
|
+
},
|
|
1723
|
+
getNextPageParam: (last) => last.hasMore ? last.nextOffset : void 0,
|
|
1724
|
+
staleTime: 15e3
|
|
1725
|
+
});
|
|
1726
|
+
const items = useMemo(() => {
|
|
1727
|
+
const all = query.data?.pages.flatMap((p) => p.data) ?? [];
|
|
1728
|
+
return all.map((rec) => {
|
|
1729
|
+
const ref = rec.ref ?? "";
|
|
1730
|
+
const parsed = parseRef(ref);
|
|
1731
|
+
const { itemId } = splitItemRef(ref);
|
|
1732
|
+
if (!itemId) return null;
|
|
1733
|
+
const base = {
|
|
1734
|
+
id: rec.id,
|
|
1735
|
+
ref,
|
|
1736
|
+
scope: parsed,
|
|
1737
|
+
data: rec.data ?? null,
|
|
1738
|
+
status: rec.data ? "configured" : "empty",
|
|
1739
|
+
label: itemId,
|
|
1740
|
+
updatedAt: rec.updatedAt,
|
|
1741
|
+
itemId
|
|
1742
|
+
};
|
|
1743
|
+
return toSummary2(rec, base);
|
|
1744
|
+
}).filter((x) => x !== null);
|
|
1745
|
+
}, [query.data, toSummary2]);
|
|
1746
|
+
const refetch = useCallback(() => {
|
|
1747
|
+
queryClient.invalidateQueries({ queryKey });
|
|
1748
|
+
}, [queryClient, queryKey]);
|
|
1749
|
+
return {
|
|
1750
|
+
items,
|
|
1751
|
+
total: query.data?.pages[query.data.pages.length - 1]?.total ?? items.length,
|
|
1752
|
+
isLoading: query.isLoading,
|
|
1753
|
+
error: query.error ?? null,
|
|
1754
|
+
hasNextPage: query.hasNextPage,
|
|
1755
|
+
isFetchingNextPage: query.isFetchingNextPage,
|
|
1756
|
+
fetchNextPage: query.fetchNextPage,
|
|
1757
|
+
refetch
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
// src/components/RecordsAdmin/data/deepLinkAdapter.ts
|
|
1762
|
+
var findQueryHost = (loc) => {
|
|
1763
|
+
if (loc.search && loc.search.length > 1) return "search";
|
|
1764
|
+
if (loc.hash && loc.hash.includes("?")) return "hash";
|
|
1765
|
+
return "search";
|
|
1766
|
+
};
|
|
1767
|
+
var getQueryString = (loc) => {
|
|
1768
|
+
const host = findQueryHost(loc);
|
|
1769
|
+
if (host === "search") return loc.search.startsWith("?") ? loc.search.slice(1) : loc.search;
|
|
1770
|
+
const idx = loc.hash.indexOf("?");
|
|
1771
|
+
return idx >= 0 ? loc.hash.slice(idx + 1) : "";
|
|
1772
|
+
};
|
|
1773
|
+
var buildUrl = (loc, nextQuery) => {
|
|
1774
|
+
const host = findQueryHost(loc);
|
|
1775
|
+
const qs = nextQuery ? `?${nextQuery}` : "";
|
|
1776
|
+
if (host === "search") {
|
|
1777
|
+
return `${loc.pathname}${qs}${loc.hash}`;
|
|
1778
|
+
}
|
|
1779
|
+
const hashPath = loc.hash.includes("?") ? loc.hash.slice(0, loc.hash.indexOf("?")) : loc.hash;
|
|
1780
|
+
return `${loc.pathname}${loc.search}${hashPath}${qs}`;
|
|
1781
|
+
};
|
|
1782
|
+
var createDefaultDeepLinkAdapter = (paramNames) => ({
|
|
1783
|
+
read() {
|
|
1784
|
+
if (typeof window === "undefined") return {};
|
|
1785
|
+
const params = new URLSearchParams(getQueryString(window.location));
|
|
1786
|
+
return {
|
|
1787
|
+
item: params.get(paramNames.item),
|
|
1788
|
+
scope: params.get(paramNames.scope),
|
|
1789
|
+
view: params.get(paramNames.view)
|
|
1790
|
+
};
|
|
1791
|
+
},
|
|
1792
|
+
write(partial, mode) {
|
|
1793
|
+
if (typeof window === "undefined") return;
|
|
1794
|
+
const params = new URLSearchParams(getQueryString(window.location));
|
|
1795
|
+
const apply = (key, value) => {
|
|
1796
|
+
if (value == null || value === "") params.delete(key);
|
|
1797
|
+
else params.set(key, value);
|
|
1798
|
+
};
|
|
1799
|
+
if ("item" in partial) apply(paramNames.item, partial.item);
|
|
1800
|
+
if ("scope" in partial) apply(paramNames.scope, partial.scope);
|
|
1801
|
+
if ("view" in partial) apply(paramNames.view, partial.view);
|
|
1802
|
+
const nextUrl = buildUrl(window.location, params.toString());
|
|
1803
|
+
if (mode === "push") window.history.pushState({}, "", nextUrl);
|
|
1804
|
+
else window.history.replaceState({}, "", nextUrl);
|
|
1805
|
+
},
|
|
1806
|
+
subscribe(listener) {
|
|
1807
|
+
if (typeof window === "undefined") return () => {
|
|
1808
|
+
};
|
|
1809
|
+
window.addEventListener("popstate", listener);
|
|
1810
|
+
window.addEventListener("hashchange", listener);
|
|
1811
|
+
return () => {
|
|
1812
|
+
window.removeEventListener("popstate", listener);
|
|
1813
|
+
window.removeEventListener("hashchange", listener);
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
});
|
|
1817
|
+
|
|
1818
|
+
// src/components/RecordsAdmin/hooks/useDeepLinkState.ts
|
|
1819
|
+
var SMART_PUSH = ["item.open", "item.close", "scope"];
|
|
1820
|
+
var classify = (mode, kind) => {
|
|
1821
|
+
if (mode === "push") return "push";
|
|
1822
|
+
if (mode === "replace") return "replace";
|
|
1823
|
+
return SMART_PUSH.includes(kind) ? "push" : "replace";
|
|
1824
|
+
};
|
|
1825
|
+
function useDeepLinkState(options) {
|
|
1826
|
+
const enabled = !!options?.enabled;
|
|
1827
|
+
const history = options?.history ?? "smart";
|
|
1828
|
+
const paramNames = useMemo(() => ({
|
|
1829
|
+
...DEFAULT_DEEP_LINK_PARAM_NAMES,
|
|
1830
|
+
...options?.paramNames ?? {}
|
|
1831
|
+
}), [options?.paramNames]);
|
|
1832
|
+
const defaultAdapterRef = useRef(null);
|
|
1833
|
+
const adapter = useMemo(() => {
|
|
1834
|
+
if (!enabled) return null;
|
|
1835
|
+
if (options?.adapter) return options.adapter;
|
|
1836
|
+
if (!defaultAdapterRef.current) {
|
|
1837
|
+
defaultAdapterRef.current = createDefaultDeepLinkAdapter(paramNames);
|
|
1838
|
+
}
|
|
1839
|
+
return defaultAdapterRef.current;
|
|
1840
|
+
}, [enabled, options?.adapter, paramNames]);
|
|
1841
|
+
const [urlState, setUrlState] = useState(
|
|
1842
|
+
() => adapter ? adapter.read() : {}
|
|
1843
|
+
);
|
|
1844
|
+
useEffect(() => {
|
|
1845
|
+
if (!adapter) return;
|
|
1846
|
+
setUrlState(adapter.read());
|
|
1847
|
+
return adapter.subscribe(() => setUrlState(adapter.read()));
|
|
1848
|
+
}, [adapter]);
|
|
1849
|
+
const emit = useCallback((partial, kind) => {
|
|
1850
|
+
if (!adapter) return;
|
|
1851
|
+
const mode = classify(history, kind);
|
|
1852
|
+
adapter.write(partial, mode);
|
|
1853
|
+
setUrlState((prev) => ({ ...prev, ...partial }));
|
|
1854
|
+
}, [adapter, history]);
|
|
1855
|
+
return { urlState, emit, paramNames, enabled };
|
|
1856
|
+
}
|
|
1857
|
+
var segmentsFor = (s) => {
|
|
1858
|
+
const out = [];
|
|
1859
|
+
if (s.facetId) out.push({ label: s.facetValue ? `${s.facetId}: ${s.facetValue}` : `Facet: ${s.facetId}`, key: "facet" });
|
|
1860
|
+
if (s.productId) out.push({ label: `Product: ${s.productId}`, key: "product" });
|
|
1861
|
+
if (s.variantId) out.push({ label: `Variant: ${s.variantId}`, key: "variant" });
|
|
1862
|
+
if (s.batchId) out.push({ label: `Batch: ${s.batchId}`, key: "batch" });
|
|
1863
|
+
return out;
|
|
1864
|
+
};
|
|
1865
|
+
var ScopeBreadcrumb = ({ scope }) => {
|
|
1866
|
+
const segs = segmentsFor(scope);
|
|
1867
|
+
if (segs.length === 0) return null;
|
|
1868
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": "Scope", className: "flex items-center gap-1 text-xs flex-wrap", style: { color: "hsl(var(--ra-muted-text))" }, children: segs.map((s, i) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
1869
|
+
i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3 opacity-50" }),
|
|
1870
|
+
/* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--ra-text))" }, children: s.label })
|
|
1871
|
+
] }, s.key)) });
|
|
1872
|
+
};
|
|
1873
|
+
var BulkActionsMenu = ({
|
|
1874
|
+
i18n,
|
|
1875
|
+
onApplyToMany,
|
|
1876
|
+
onCopyFrom,
|
|
1877
|
+
onClearMany,
|
|
1878
|
+
onImportCsv,
|
|
1879
|
+
onExportCsv
|
|
1880
|
+
}) => {
|
|
1881
|
+
const [open, setOpen] = useState(false);
|
|
1882
|
+
const ref = useRef(null);
|
|
1883
|
+
useEffect(() => {
|
|
1884
|
+
if (!open) return;
|
|
1885
|
+
const onDocClick = (e) => {
|
|
1886
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
1887
|
+
};
|
|
1888
|
+
document.addEventListener("mousedown", onDocClick);
|
|
1889
|
+
return () => document.removeEventListener("mousedown", onDocClick);
|
|
1890
|
+
}, [open]);
|
|
1891
|
+
const items = [
|
|
1892
|
+
onApplyToMany && { key: "apply", label: i18n.applyToMany, onClick: onApplyToMany, icon: Layers },
|
|
1893
|
+
onCopyFrom && { key: "copy", label: i18n.copyFrom, onClick: onCopyFrom, icon: Copy },
|
|
1894
|
+
onImportCsv && { key: "imp", label: i18n.importCsv, onClick: onImportCsv, icon: Upload, divider: true },
|
|
1895
|
+
onExportCsv && { key: "exp", label: i18n.exportCsv, onClick: onExportCsv, icon: Download },
|
|
1896
|
+
onClearMany && { key: "clear", label: i18n.clear, onClick: onClearMany, icon: Eraser, tone: "danger", divider: true }
|
|
1675
1897
|
].filter(Boolean);
|
|
1676
1898
|
if (items.length === 0) return null;
|
|
1677
1899
|
return /* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
|
|
@@ -1721,8 +1943,10 @@ var DeleteButton = ({
|
|
|
1721
1943
|
label = "Delete record",
|
|
1722
1944
|
confirmLabel = "Confirm delete",
|
|
1723
1945
|
revertMs = 3e3,
|
|
1724
|
-
disabled
|
|
1946
|
+
disabled,
|
|
1947
|
+
icon
|
|
1725
1948
|
}) => {
|
|
1949
|
+
const Icon = icon ?? Trash2;
|
|
1726
1950
|
const [armed, setArmed] = useState(false);
|
|
1727
1951
|
const [busy, setBusy] = useState(false);
|
|
1728
1952
|
const timerRef = useRef(null);
|
|
@@ -1783,7 +2007,7 @@ var DeleteButton = ({
|
|
|
1783
2007
|
color: "hsl(var(--ra-danger, var(--ra-text)))"
|
|
1784
2008
|
},
|
|
1785
2009
|
children: [
|
|
1786
|
-
/* @__PURE__ */ jsx(
|
|
2010
|
+
/* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5" }),
|
|
1787
2011
|
label
|
|
1788
2012
|
]
|
|
1789
2013
|
}
|
|
@@ -1799,8 +2023,17 @@ function RecordEditor({
|
|
|
1799
2023
|
onBeforeDelete,
|
|
1800
2024
|
headerLabel,
|
|
1801
2025
|
headerSubtitle,
|
|
1802
|
-
headerMeta
|
|
2026
|
+
headerMeta,
|
|
2027
|
+
clipboard,
|
|
2028
|
+
actionLabels,
|
|
2029
|
+
actionIcons
|
|
1803
2030
|
}) {
|
|
2031
|
+
const saveLabel = actionLabels?.save ?? i18n.save;
|
|
2032
|
+
const discardLabel = actionLabels?.discard ?? i18n.discard;
|
|
2033
|
+
const deleteLabel = actionLabels?.delete ?? i18n.delete;
|
|
2034
|
+
const SaveIcon = actionIcons?.save;
|
|
2035
|
+
const DiscardIcon = actionIcons?.discard;
|
|
2036
|
+
const DeleteIcon = actionIcons?.delete;
|
|
1804
2037
|
const sourceLabel = ctx.source === "self" ? "Customised" : ctx.source === "inherited" ? "Inherited" : null;
|
|
1805
2038
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
1806
2039
|
/* @__PURE__ */ jsxs(
|
|
@@ -1878,15 +2111,18 @@ function RecordEditor({
|
|
|
1878
2111
|
style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" },
|
|
1879
2112
|
children: [
|
|
1880
2113
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1881
|
-
/* @__PURE__ */
|
|
2114
|
+
/* @__PURE__ */ jsxs(
|
|
1882
2115
|
"button",
|
|
1883
2116
|
{
|
|
1884
2117
|
type: "button",
|
|
1885
2118
|
onClick: ctx.reset,
|
|
1886
2119
|
disabled: !ctx.isDirty || !!ctx.isSaving,
|
|
1887
|
-
className: "text-xs px-3 py-1.5 rounded-md border transition-opacity disabled:opacity-40 hover:bg-[hsl(var(--ra-muted))]",
|
|
2120
|
+
className: "text-xs px-3 py-1.5 rounded-md border transition-opacity disabled:opacity-40 hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1.5",
|
|
1888
2121
|
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
1889
|
-
children:
|
|
2122
|
+
children: [
|
|
2123
|
+
DiscardIcon && /* @__PURE__ */ jsx(DiscardIcon, { className: "h-4 w-4" }),
|
|
2124
|
+
discardLabel
|
|
2125
|
+
]
|
|
1890
2126
|
}
|
|
1891
2127
|
),
|
|
1892
2128
|
ctx.canRemove && /* @__PURE__ */ jsx(
|
|
@@ -1894,10 +2130,45 @@ function RecordEditor({
|
|
|
1894
2130
|
{
|
|
1895
2131
|
onConfirm: () => ctx.remove(),
|
|
1896
2132
|
onBeforeDelete,
|
|
1897
|
-
label:
|
|
1898
|
-
confirmLabel: i18n.confirmDelete
|
|
2133
|
+
label: deleteLabel,
|
|
2134
|
+
confirmLabel: i18n.confirmDelete,
|
|
2135
|
+
icon: DeleteIcon
|
|
1899
2136
|
}
|
|
1900
2137
|
),
|
|
2138
|
+
clipboard && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2139
|
+
/* @__PURE__ */ jsxs(
|
|
2140
|
+
"button",
|
|
2141
|
+
{
|
|
2142
|
+
type: "button",
|
|
2143
|
+
onClick: clipboard.onCopy,
|
|
2144
|
+
disabled: !clipboard.canCopy || !!ctx.isSaving,
|
|
2145
|
+
title: i18n.copy,
|
|
2146
|
+
"aria-label": i18n.copy,
|
|
2147
|
+
className: "text-xs px-2.5 py-1.5 rounded-md border transition-opacity disabled:opacity-40 hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1.5",
|
|
2148
|
+
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
2149
|
+
children: [
|
|
2150
|
+
/* @__PURE__ */ jsx(Copy, { className: "w-3 h-3" }),
|
|
2151
|
+
i18n.copy
|
|
2152
|
+
]
|
|
2153
|
+
}
|
|
2154
|
+
),
|
|
2155
|
+
/* @__PURE__ */ jsxs(
|
|
2156
|
+
"button",
|
|
2157
|
+
{
|
|
2158
|
+
type: "button",
|
|
2159
|
+
onClick: clipboard.onPaste,
|
|
2160
|
+
disabled: !clipboard.canPaste || !!ctx.isSaving,
|
|
2161
|
+
title: !clipboard.canPaste ? i18n.clipboardEmpty : clipboard.pasteSourceLabel ? i18n.pasteFrom.replace("{name}", clipboard.pasteSourceLabel) : i18n.paste,
|
|
2162
|
+
"aria-label": i18n.paste,
|
|
2163
|
+
className: "text-xs px-2.5 py-1.5 rounded-md border transition-opacity disabled:opacity-40 hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1.5",
|
|
2164
|
+
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
2165
|
+
children: [
|
|
2166
|
+
/* @__PURE__ */ jsx(ClipboardPaste, { className: "w-3 h-3" }),
|
|
2167
|
+
clipboard.pasteWillReplace ? i18n.pasteReplace : i18n.paste
|
|
2168
|
+
]
|
|
2169
|
+
}
|
|
2170
|
+
)
|
|
2171
|
+
] }),
|
|
1901
2172
|
footerExtra,
|
|
1902
2173
|
ctx.saveError != null && !ctx.isSaving && /* @__PURE__ */ jsx(
|
|
1903
2174
|
"span",
|
|
@@ -1909,7 +2180,7 @@ function RecordEditor({
|
|
|
1909
2180
|
}
|
|
1910
2181
|
)
|
|
1911
2182
|
] }),
|
|
1912
|
-
/* @__PURE__ */
|
|
2183
|
+
/* @__PURE__ */ jsxs(
|
|
1913
2184
|
"button",
|
|
1914
2185
|
{
|
|
1915
2186
|
type: "button",
|
|
@@ -1918,9 +2189,12 @@ function RecordEditor({
|
|
|
1918
2189
|
});
|
|
1919
2190
|
},
|
|
1920
2191
|
disabled: !ctx.isDirty || !!ctx.isSaving,
|
|
1921
|
-
className: "text-xs px-3 py-1.5 rounded-md font-medium transition-opacity disabled:opacity-40",
|
|
2192
|
+
className: "text-xs px-3 py-1.5 rounded-md font-medium transition-opacity disabled:opacity-40 inline-flex items-center gap-1.5",
|
|
1922
2193
|
style: { background: "hsl(var(--ra-accent))", color: "hsl(var(--ra-surface))" },
|
|
1923
|
-
children:
|
|
2194
|
+
children: [
|
|
2195
|
+
SaveIcon && !ctx.isSaving && /* @__PURE__ */ jsx(SaveIcon, { className: "h-4 w-4" }),
|
|
2196
|
+
ctx.isSaving ? i18n.saving ?? "Saving\u2026" : saveLabel
|
|
2197
|
+
]
|
|
1924
2198
|
}
|
|
1925
2199
|
)
|
|
1926
2200
|
]
|
|
@@ -1945,16 +2219,18 @@ var ProductDrillDown = ({
|
|
|
1945
2219
|
batches,
|
|
1946
2220
|
variantsLoading,
|
|
1947
2221
|
batchesLoading,
|
|
1948
|
-
children
|
|
2222
|
+
children,
|
|
2223
|
+
hideSingleTab
|
|
1949
2224
|
}) => {
|
|
1950
2225
|
const tabs = ["product"];
|
|
1951
2226
|
if (showVariants) tabs.push("variant");
|
|
1952
2227
|
if (showBatches) tabs.push("batch");
|
|
2228
|
+
const showTabStrip = tabs.length > 1 || !hideSingleTab;
|
|
1953
2229
|
const childList = active === "variant" ? variants : active === "batch" ? batches : [];
|
|
1954
2230
|
const childLoading = active === "variant" ? variantsLoading : active === "batch" ? batchesLoading : false;
|
|
1955
2231
|
const childEmptyLabel = active === "variant" ? "No variants" : "No batches";
|
|
1956
2232
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
1957
|
-
/* @__PURE__ */ jsx(
|
|
2233
|
+
showTabStrip && /* @__PURE__ */ jsx(
|
|
1958
2234
|
"div",
|
|
1959
2235
|
{
|
|
1960
2236
|
className: "flex items-center gap-1 px-4 pt-3 border-b",
|
|
@@ -2367,6 +2643,394 @@ var PreviewScopePicker = ({
|
|
|
2367
2643
|
)
|
|
2368
2644
|
] });
|
|
2369
2645
|
};
|
|
2646
|
+
var ICONS2 = {
|
|
2647
|
+
table: Table,
|
|
2648
|
+
cards: LayoutGrid,
|
|
2649
|
+
gallery: Image
|
|
2650
|
+
};
|
|
2651
|
+
var labelFor2 = (v, i18n) => {
|
|
2652
|
+
if (v === "table") return i18n.itemViewTable;
|
|
2653
|
+
if (v === "cards") return i18n.itemViewCards;
|
|
2654
|
+
return i18n.itemViewGallery;
|
|
2655
|
+
};
|
|
2656
|
+
var ItemViewSwitcher = ({ options, value, onChange, i18n }) => {
|
|
2657
|
+
if (options.length < 2) return null;
|
|
2658
|
+
return /* @__PURE__ */ jsx("div", { role: "tablist", className: "ra-tabs", "aria-label": "Item view", style: { padding: "0.15rem" }, children: options.map((opt) => {
|
|
2659
|
+
const Icon = ICONS2[opt];
|
|
2660
|
+
const active = value === opt;
|
|
2661
|
+
return /* @__PURE__ */ jsxs(
|
|
2662
|
+
"button",
|
|
2663
|
+
{
|
|
2664
|
+
type: "button",
|
|
2665
|
+
role: "tab",
|
|
2666
|
+
"aria-selected": active,
|
|
2667
|
+
onClick: () => onChange(opt),
|
|
2668
|
+
className: "ra-tab",
|
|
2669
|
+
title: labelFor2(opt, i18n),
|
|
2670
|
+
style: { padding: "0.3rem 0.55rem" },
|
|
2671
|
+
children: [
|
|
2672
|
+
/* @__PURE__ */ jsx(Icon, { className: cn("ra-tab-icon w-3.5 h-3.5") }),
|
|
2673
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labelFor2(opt, i18n) })
|
|
2674
|
+
]
|
|
2675
|
+
},
|
|
2676
|
+
opt
|
|
2677
|
+
);
|
|
2678
|
+
}) });
|
|
2679
|
+
};
|
|
2680
|
+
var formatDate = (iso) => {
|
|
2681
|
+
if (!iso) return "\u2014";
|
|
2682
|
+
try {
|
|
2683
|
+
const d = new Date(iso);
|
|
2684
|
+
return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
2685
|
+
} catch {
|
|
2686
|
+
return iso;
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
function DefaultItemTable({
|
|
2690
|
+
items,
|
|
2691
|
+
columns,
|
|
2692
|
+
selectedId,
|
|
2693
|
+
onOpen,
|
|
2694
|
+
onDelete,
|
|
2695
|
+
i18n
|
|
2696
|
+
}) {
|
|
2697
|
+
const cols = columns ?? [];
|
|
2698
|
+
const useFallback = cols.length === 0;
|
|
2699
|
+
return /* @__PURE__ */ jsx("div", { className: "ra-item-table-wrap", children: /* @__PURE__ */ jsxs("table", { className: "ra-item-table", children: [
|
|
2700
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2701
|
+
useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2702
|
+
/* @__PURE__ */ jsx("th", { children: i18n.itemColumnLabel }),
|
|
2703
|
+
/* @__PURE__ */ jsx("th", { style: { width: "12rem" }, children: i18n.itemColumnUpdated })
|
|
2704
|
+
] }) : cols.map((c) => /* @__PURE__ */ jsx("th", { style: { width: c.width, textAlign: c.align ?? "left" }, children: c.header }, c.key)),
|
|
2705
|
+
/* @__PURE__ */ jsx(
|
|
2706
|
+
"th",
|
|
2707
|
+
{
|
|
2708
|
+
style: { width: "6.5rem", textAlign: "right" },
|
|
2709
|
+
"aria-label": i18n.itemActions
|
|
2710
|
+
}
|
|
2711
|
+
)
|
|
2712
|
+
] }) }),
|
|
2713
|
+
/* @__PURE__ */ jsx("tbody", { children: items.map((item) => {
|
|
2714
|
+
const id = item.itemId ?? "";
|
|
2715
|
+
const isSelected = !!selectedId && selectedId === id;
|
|
2716
|
+
return /* @__PURE__ */ jsxs(
|
|
2717
|
+
"tr",
|
|
2718
|
+
{
|
|
2719
|
+
"data-selected": isSelected,
|
|
2720
|
+
onClick: () => onOpen(id),
|
|
2721
|
+
className: "ra-item-row",
|
|
2722
|
+
children: [
|
|
2723
|
+
useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2724
|
+
/* @__PURE__ */ jsxs("td", { children: [
|
|
2725
|
+
/* @__PURE__ */ jsx("div", { className: "ra-item-row-title", children: item.label }),
|
|
2726
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-row-sub", children: item.subtitle })
|
|
2727
|
+
] }),
|
|
2728
|
+
/* @__PURE__ */ jsx("td", { className: "ra-item-row-meta", children: formatDate(item.updatedAt) })
|
|
2729
|
+
] }) : cols.map((c) => /* @__PURE__ */ jsx("td", { style: { textAlign: c.align ?? "left" }, children: c.render(item) }, c.key)),
|
|
2730
|
+
/* @__PURE__ */ jsxs("td", { className: "ra-item-row-actions", children: [
|
|
2731
|
+
/* @__PURE__ */ jsx(
|
|
2732
|
+
"button",
|
|
2733
|
+
{
|
|
2734
|
+
type: "button",
|
|
2735
|
+
className: "ra-row-action",
|
|
2736
|
+
onClick: (e) => {
|
|
2737
|
+
e.stopPropagation();
|
|
2738
|
+
onOpen(id);
|
|
2739
|
+
},
|
|
2740
|
+
"aria-label": "Edit",
|
|
2741
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "w-3.5 h-3.5" })
|
|
2742
|
+
}
|
|
2743
|
+
),
|
|
2744
|
+
/* @__PURE__ */ jsx(
|
|
2745
|
+
"button",
|
|
2746
|
+
{
|
|
2747
|
+
type: "button",
|
|
2748
|
+
className: "ra-row-action",
|
|
2749
|
+
"data-tone": "danger",
|
|
2750
|
+
onClick: (e) => {
|
|
2751
|
+
e.stopPropagation();
|
|
2752
|
+
onDelete(id);
|
|
2753
|
+
},
|
|
2754
|
+
"aria-label": i18n.delete,
|
|
2755
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
|
|
2756
|
+
}
|
|
2757
|
+
)
|
|
2758
|
+
] })
|
|
2759
|
+
]
|
|
2760
|
+
},
|
|
2761
|
+
item.ref
|
|
2762
|
+
);
|
|
2763
|
+
}) })
|
|
2764
|
+
] }) });
|
|
2765
|
+
}
|
|
2766
|
+
var initials = (label) => label.split(/\s+/).slice(0, 2).map((s) => s[0]?.toUpperCase() ?? "").join("") || "?";
|
|
2767
|
+
function DefaultItemCards({
|
|
2768
|
+
items,
|
|
2769
|
+
variant,
|
|
2770
|
+
selectedId,
|
|
2771
|
+
ctx,
|
|
2772
|
+
renderCard,
|
|
2773
|
+
i18n
|
|
2774
|
+
}) {
|
|
2775
|
+
const isGallery = variant === "gallery";
|
|
2776
|
+
return /* @__PURE__ */ jsx("div", { className: isGallery ? "ra-item-gallery" : "ra-item-cards", children: items.map((item) => {
|
|
2777
|
+
const id = item.itemId ?? "";
|
|
2778
|
+
const slotCtx = {
|
|
2779
|
+
...ctx,
|
|
2780
|
+
selected: selectedId === id
|
|
2781
|
+
};
|
|
2782
|
+
if (renderCard) {
|
|
2783
|
+
return /* @__PURE__ */ jsx(
|
|
2784
|
+
"div",
|
|
2785
|
+
{
|
|
2786
|
+
onClick: () => ctx.onOpen(id),
|
|
2787
|
+
className: "ra-item-card-wrap",
|
|
2788
|
+
"data-selected": slotCtx.selected,
|
|
2789
|
+
children: renderCard(item, slotCtx)
|
|
2790
|
+
},
|
|
2791
|
+
item.ref
|
|
2792
|
+
);
|
|
2793
|
+
}
|
|
2794
|
+
return /* @__PURE__ */ jsxs(
|
|
2795
|
+
"button",
|
|
2796
|
+
{
|
|
2797
|
+
type: "button",
|
|
2798
|
+
onClick: () => ctx.onOpen(id),
|
|
2799
|
+
className: `ra-item-card ${isGallery ? "ra-item-card--gallery" : ""}`,
|
|
2800
|
+
"data-selected": slotCtx.selected,
|
|
2801
|
+
children: [
|
|
2802
|
+
/* @__PURE__ */ jsx("div", { className: `ra-item-card-thumb ${isGallery ? "ra-item-card-thumb--gallery" : ""}`, children: item.thumbnail ? /* @__PURE__ */ jsx("img", { src: item.thumbnail, alt: "", loading: "lazy" }) : /* @__PURE__ */ jsx("span", { className: "ra-item-card-initials", children: initials(item.label) }) }),
|
|
2803
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-item-card-body", children: [
|
|
2804
|
+
/* @__PURE__ */ jsx("div", { className: "ra-item-card-title", children: item.label }),
|
|
2805
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-card-sub", children: item.subtitle })
|
|
2806
|
+
] }),
|
|
2807
|
+
/* @__PURE__ */ jsx(
|
|
2808
|
+
"button",
|
|
2809
|
+
{
|
|
2810
|
+
type: "button",
|
|
2811
|
+
className: "ra-row-action ra-item-card-delete",
|
|
2812
|
+
"data-tone": "danger",
|
|
2813
|
+
onClick: (e) => {
|
|
2814
|
+
e.stopPropagation();
|
|
2815
|
+
ctx.onDelete(id);
|
|
2816
|
+
},
|
|
2817
|
+
"aria-label": i18n.delete,
|
|
2818
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
|
|
2819
|
+
}
|
|
2820
|
+
)
|
|
2821
|
+
]
|
|
2822
|
+
},
|
|
2823
|
+
item.ref
|
|
2824
|
+
);
|
|
2825
|
+
}) });
|
|
2826
|
+
}
|
|
2827
|
+
function ItemListView({
|
|
2828
|
+
items,
|
|
2829
|
+
isLoading,
|
|
2830
|
+
error,
|
|
2831
|
+
ctx,
|
|
2832
|
+
itemNoun,
|
|
2833
|
+
view,
|
|
2834
|
+
views,
|
|
2835
|
+
onViewChange,
|
|
2836
|
+
renderItemList,
|
|
2837
|
+
renderItemCard,
|
|
2838
|
+
renderItemEmpty,
|
|
2839
|
+
itemColumns,
|
|
2840
|
+
i18n
|
|
2841
|
+
}) {
|
|
2842
|
+
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
|
|
2843
|
+
const toolbar = /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar", children: [
|
|
2844
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-title", children: [
|
|
2845
|
+
/* @__PURE__ */ jsx("h2", { className: "ra-display", style: { fontSize: "0.95rem", margin: 0 }, children: i18n.itemListTitle }),
|
|
2846
|
+
/* @__PURE__ */ jsx("span", { className: "ra-item-toolbar-count", children: items.length })
|
|
2847
|
+
] }),
|
|
2848
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-actions", children: [
|
|
2849
|
+
!renderItemList && /* @__PURE__ */ jsx(
|
|
2850
|
+
ItemViewSwitcher,
|
|
2851
|
+
{
|
|
2852
|
+
options: views,
|
|
2853
|
+
value: view,
|
|
2854
|
+
onChange: onViewChange,
|
|
2855
|
+
i18n
|
|
2856
|
+
}
|
|
2857
|
+
),
|
|
2858
|
+
/* @__PURE__ */ jsxs(
|
|
2859
|
+
"button",
|
|
2860
|
+
{
|
|
2861
|
+
type: "button",
|
|
2862
|
+
onClick: ctx.onCreate,
|
|
2863
|
+
className: "ra-btn",
|
|
2864
|
+
"data-variant": "primary",
|
|
2865
|
+
children: [
|
|
2866
|
+
/* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
|
|
2867
|
+
newLabel
|
|
2868
|
+
]
|
|
2869
|
+
}
|
|
2870
|
+
)
|
|
2871
|
+
] })
|
|
2872
|
+
] });
|
|
2873
|
+
let body;
|
|
2874
|
+
if (isLoading) {
|
|
2875
|
+
body = /* @__PURE__ */ jsx(LoadingState, {});
|
|
2876
|
+
} else if (error) {
|
|
2877
|
+
body = /* @__PURE__ */ jsx(ErrorState, { error });
|
|
2878
|
+
} else if (items.length === 0) {
|
|
2879
|
+
body = renderItemEmpty ? renderItemEmpty(ctx) : /* @__PURE__ */ jsx(
|
|
2880
|
+
EmptyState,
|
|
2881
|
+
{
|
|
2882
|
+
title: i18n.noItemsTitle,
|
|
2883
|
+
body: i18n.noItemsBody,
|
|
2884
|
+
action: /* @__PURE__ */ jsxs(
|
|
2885
|
+
"button",
|
|
2886
|
+
{
|
|
2887
|
+
type: "button",
|
|
2888
|
+
onClick: ctx.onCreate,
|
|
2889
|
+
className: "ra-btn",
|
|
2890
|
+
"data-variant": "primary",
|
|
2891
|
+
children: [
|
|
2892
|
+
/* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
|
|
2893
|
+
newLabel
|
|
2894
|
+
]
|
|
2895
|
+
}
|
|
2896
|
+
)
|
|
2897
|
+
}
|
|
2898
|
+
);
|
|
2899
|
+
} else if (renderItemList) {
|
|
2900
|
+
body = renderItemList(items, ctx);
|
|
2901
|
+
} else if (view === "table") {
|
|
2902
|
+
body = /* @__PURE__ */ jsx(
|
|
2903
|
+
DefaultItemTable,
|
|
2904
|
+
{
|
|
2905
|
+
items,
|
|
2906
|
+
columns: itemColumns,
|
|
2907
|
+
selectedId: ctx.selectedId,
|
|
2908
|
+
onOpen: ctx.onOpen,
|
|
2909
|
+
onDelete: ctx.onDelete,
|
|
2910
|
+
i18n
|
|
2911
|
+
}
|
|
2912
|
+
);
|
|
2913
|
+
} else {
|
|
2914
|
+
body = /* @__PURE__ */ jsx(
|
|
2915
|
+
DefaultItemCards,
|
|
2916
|
+
{
|
|
2917
|
+
items,
|
|
2918
|
+
variant: view,
|
|
2919
|
+
selectedId: ctx.selectedId,
|
|
2920
|
+
ctx,
|
|
2921
|
+
renderCard: renderItemCard,
|
|
2922
|
+
i18n
|
|
2923
|
+
}
|
|
2924
|
+
);
|
|
2925
|
+
}
|
|
2926
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-item-list", children: [
|
|
2927
|
+
toolbar,
|
|
2928
|
+
/* @__PURE__ */ jsx("div", { className: "ra-item-list-body", children: body })
|
|
2929
|
+
] });
|
|
2930
|
+
}
|
|
2931
|
+
var EditorItemNav = ({
|
|
2932
|
+
label,
|
|
2933
|
+
position,
|
|
2934
|
+
total,
|
|
2935
|
+
onBack,
|
|
2936
|
+
onPrev,
|
|
2937
|
+
onNext,
|
|
2938
|
+
canPrev,
|
|
2939
|
+
canNext,
|
|
2940
|
+
i18n
|
|
2941
|
+
}) => /* @__PURE__ */ jsxs("div", { className: "ra-item-nav", children: [
|
|
2942
|
+
/* @__PURE__ */ jsxs(
|
|
2943
|
+
"button",
|
|
2944
|
+
{
|
|
2945
|
+
type: "button",
|
|
2946
|
+
onClick: onBack,
|
|
2947
|
+
className: "ra-btn",
|
|
2948
|
+
"data-variant": "ghost",
|
|
2949
|
+
children: [
|
|
2950
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
|
|
2951
|
+
i18n.backToList
|
|
2952
|
+
]
|
|
2953
|
+
}
|
|
2954
|
+
),
|
|
2955
|
+
typeof position === "number" && typeof total === "number" && total > 0 && /* @__PURE__ */ jsxs("span", { className: "ra-item-nav-position", "aria-label": label, children: [
|
|
2956
|
+
position,
|
|
2957
|
+
" / ",
|
|
2958
|
+
total
|
|
2959
|
+
] }),
|
|
2960
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-item-nav-arrows", children: [
|
|
2961
|
+
/* @__PURE__ */ jsx(
|
|
2962
|
+
"button",
|
|
2963
|
+
{
|
|
2964
|
+
type: "button",
|
|
2965
|
+
onClick: onPrev,
|
|
2966
|
+
disabled: !canPrev,
|
|
2967
|
+
className: "ra-row-action",
|
|
2968
|
+
"aria-label": i18n.prevItem,
|
|
2969
|
+
title: i18n.prevItem,
|
|
2970
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
|
|
2971
|
+
}
|
|
2972
|
+
),
|
|
2973
|
+
/* @__PURE__ */ jsx(
|
|
2974
|
+
"button",
|
|
2975
|
+
{
|
|
2976
|
+
type: "button",
|
|
2977
|
+
onClick: onNext,
|
|
2978
|
+
disabled: !canNext,
|
|
2979
|
+
className: "ra-row-action",
|
|
2980
|
+
"aria-label": i18n.nextItem,
|
|
2981
|
+
title: i18n.nextItem,
|
|
2982
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
|
|
2983
|
+
}
|
|
2984
|
+
)
|
|
2985
|
+
] })
|
|
2986
|
+
] });
|
|
2987
|
+
function SiblingRail({
|
|
2988
|
+
items,
|
|
2989
|
+
selectedItemId,
|
|
2990
|
+
isLoading,
|
|
2991
|
+
error,
|
|
2992
|
+
onBack,
|
|
2993
|
+
onSelect,
|
|
2994
|
+
i18n
|
|
2995
|
+
}) {
|
|
2996
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
|
|
2997
|
+
/* @__PURE__ */ jsxs(
|
|
2998
|
+
"button",
|
|
2999
|
+
{
|
|
3000
|
+
type: "button",
|
|
3001
|
+
onClick: onBack,
|
|
3002
|
+
className: "ra-sibling-back",
|
|
3003
|
+
children: [
|
|
3004
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
|
|
3005
|
+
i18n.backToScopes
|
|
3006
|
+
]
|
|
3007
|
+
}
|
|
3008
|
+
),
|
|
3009
|
+
/* @__PURE__ */ jsx("div", { className: "ra-sibling-heading", children: i18n.siblingsHeading }),
|
|
3010
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-sibling-body", children: [
|
|
3011
|
+
isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
3012
|
+
!isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
|
|
3013
|
+
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
3014
|
+
!isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item) => {
|
|
3015
|
+
const id = item.itemId ?? "";
|
|
3016
|
+
const selected = selectedItemId === id;
|
|
3017
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
3018
|
+
"button",
|
|
3019
|
+
{
|
|
3020
|
+
type: "button",
|
|
3021
|
+
onClick: () => onSelect(id),
|
|
3022
|
+
className: "ra-row",
|
|
3023
|
+
"data-selected": selected,
|
|
3024
|
+
children: /* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
3025
|
+
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
3026
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
3027
|
+
] })
|
|
3028
|
+
}
|
|
3029
|
+
) }, item.ref);
|
|
3030
|
+
}) })
|
|
3031
|
+
] })
|
|
3032
|
+
] });
|
|
3033
|
+
}
|
|
2370
3034
|
var TONE_ICON = {
|
|
2371
3035
|
info: Lightbulb,
|
|
2372
3036
|
success: CheckCircle2,
|
|
@@ -2395,8 +3059,9 @@ var IntroCard = ({ title, body, onDismiss, tone = "info", action }) => {
|
|
|
2395
3059
|
)
|
|
2396
3060
|
] });
|
|
2397
3061
|
};
|
|
2398
|
-
var UtilityRow = ({ label, introHidden, onShowIntro }) => {
|
|
3062
|
+
var UtilityRow = ({ label, customLabel, introHidden, onShowIntro }) => {
|
|
2399
3063
|
if (!introHidden || !onShowIntro) return null;
|
|
3064
|
+
const text = customLabel ?? `How ${label.toLowerCase()} works`;
|
|
2400
3065
|
return /* @__PURE__ */ jsx(
|
|
2401
3066
|
"div",
|
|
2402
3067
|
{
|
|
@@ -2412,9 +3077,7 @@ var UtilityRow = ({ label, introHidden, onShowIntro }) => {
|
|
|
2412
3077
|
style: { padding: "0.25rem 0.55rem", fontSize: "0.7rem" },
|
|
2413
3078
|
children: [
|
|
2414
3079
|
/* @__PURE__ */ jsx(HelpCircle, { className: "w-3 h-3" }),
|
|
2415
|
-
|
|
2416
|
-
label.toLowerCase(),
|
|
2417
|
-
" works"
|
|
3080
|
+
text
|
|
2418
3081
|
]
|
|
2419
3082
|
}
|
|
2420
3083
|
)
|
|
@@ -2433,7 +3096,8 @@ function ShellHeader({
|
|
|
2433
3096
|
stats,
|
|
2434
3097
|
statsItems,
|
|
2435
3098
|
statsTitle,
|
|
2436
|
-
statsIcon
|
|
3099
|
+
statsIcon,
|
|
3100
|
+
trailingSlot
|
|
2437
3101
|
}) {
|
|
2438
3102
|
let iconNode = null;
|
|
2439
3103
|
if (showHeaderIcon) {
|
|
@@ -2488,7 +3152,10 @@ function ShellHeader({
|
|
|
2488
3152
|
]
|
|
2489
3153
|
}
|
|
2490
3154
|
) : null,
|
|
2491
|
-
headerActions ? /* @__PURE__ */
|
|
3155
|
+
headerActions || trailingSlot ? /* @__PURE__ */ jsxs("div", { className: "ra-header-actions", children: [
|
|
3156
|
+
headerActions,
|
|
3157
|
+
trailingSlot
|
|
3158
|
+
] }) : null
|
|
2492
3159
|
] })
|
|
2493
3160
|
] });
|
|
2494
3161
|
}
|
|
@@ -2503,8 +3170,12 @@ var UnsavedBanner = ({
|
|
|
2503
3170
|
discardLabel,
|
|
2504
3171
|
bodyTemplate,
|
|
2505
3172
|
savingLabel,
|
|
2506
|
-
errorLabel
|
|
3173
|
+
errorLabel,
|
|
3174
|
+
SaveIcon,
|
|
3175
|
+
DiscardIcon
|
|
2507
3176
|
}) => {
|
|
3177
|
+
const SI = SaveIcon ?? Save;
|
|
3178
|
+
const DI = DiscardIcon ?? Undo2;
|
|
2508
3179
|
const name = label ?? context ?? "this record";
|
|
2509
3180
|
const message = bodyTemplate.replace("{name}", name);
|
|
2510
3181
|
return /* @__PURE__ */ jsxs("div", { className: "ra-unsaved-banner", role: "status", "aria-live": "polite", children: [
|
|
@@ -2526,7 +3197,7 @@ var UnsavedBanner = ({
|
|
|
2526
3197
|
onClick: onDiscard,
|
|
2527
3198
|
disabled: isSaving,
|
|
2528
3199
|
children: [
|
|
2529
|
-
/* @__PURE__ */ jsx(
|
|
3200
|
+
/* @__PURE__ */ jsx(DI, { className: "w-3 h-3" }),
|
|
2530
3201
|
discardLabel
|
|
2531
3202
|
]
|
|
2532
3203
|
}
|
|
@@ -2539,7 +3210,7 @@ var UnsavedBanner = ({
|
|
|
2539
3210
|
onClick: onSave,
|
|
2540
3211
|
disabled: isSaving,
|
|
2541
3212
|
children: [
|
|
2542
|
-
/* @__PURE__ */ jsx(
|
|
3213
|
+
/* @__PURE__ */ jsx(SI, { className: "w-3 h-3" }),
|
|
2543
3214
|
isSaving ? savingLabel ?? "Saving\u2026" : saveLabel
|
|
2544
3215
|
]
|
|
2545
3216
|
}
|
|
@@ -2547,6 +3218,25 @@ var UnsavedBanner = ({
|
|
|
2547
3218
|
] })
|
|
2548
3219
|
] });
|
|
2549
3220
|
};
|
|
3221
|
+
var ClipboardToast = ({ message, variant = "copy", onDismiss }) => {
|
|
3222
|
+
useEffect(() => {
|
|
3223
|
+
const t = window.setTimeout(onDismiss, 2500);
|
|
3224
|
+
return () => window.clearTimeout(t);
|
|
3225
|
+
}, [message, onDismiss]);
|
|
3226
|
+
const Icon = variant === "paste" ? ClipboardPaste : Copy;
|
|
3227
|
+
return /* @__PURE__ */ jsxs(
|
|
3228
|
+
"div",
|
|
3229
|
+
{
|
|
3230
|
+
role: "status",
|
|
3231
|
+
"aria-live": "polite",
|
|
3232
|
+
className: "ra-clipboard-toast",
|
|
3233
|
+
children: [
|
|
3234
|
+
/* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5 shrink-0", "aria-hidden": "true" }),
|
|
3235
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: message })
|
|
3236
|
+
]
|
|
3237
|
+
}
|
|
3238
|
+
);
|
|
3239
|
+
};
|
|
2550
3240
|
|
|
2551
3241
|
// src/components/RecordsAdmin/data/csv.ts
|
|
2552
3242
|
var escapeCell = (s) => {
|
|
@@ -2656,7 +3346,7 @@ var downloadBlob = (blob, filename) => {
|
|
|
2656
3346
|
styleInject(':root {\n --ra-status-own: var(--ra-emerald, 142 71% 45%);\n --ra-status-shared: var(--ra-amber, 38 92% 50%);\n --ra-status-missing: var(--muted-foreground, 220 9% 46%);\n --ra-accent: var(--primary, 222 47% 11%);\n --ra-surface: var(--card, 0 0% 100%);\n --ra-border: var(--border, 220 13% 91%);\n --ra-text: var(--foreground, 222 47% 11%);\n --ra-muted: var(--muted, 220 14% 96%);\n --ra-muted-text: var(--muted-foreground, 220 9% 46%);\n --ra-radius: var(--radius, 0.625rem);\n --ra-dot-size: 0.5rem;\n --ra-page-bg: var(--background, 220 14% 98%);\n --ra-card-shadow: 0 1px 2px hsl(var(--ra-accent) / 0.04), 0 4px 12px hsl(var(--ra-accent) / 0.05);\n --ra-card-shadow-hover: 0 2px 4px hsl(var(--ra-accent) / 0.06), 0 8px 24px hsl(var(--ra-accent) / 0.08);\n --ra-row-hover: hsl(var(--ra-accent) / 0.05);\n --ra-row-active-bg: hsl(var(--ra-accent) / 0.10);\n --ra-row-active-bd: hsl(var(--ra-accent) / 0.45);\n --ra-focus-ring: hsl(var(--ra-accent) / 0.35);\n --ra-font-display: var(--font-display, var(--font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif));\n --ra-font-ui: var(--font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);\n --ra-title-weight: 600;\n --ra-display-weight: 700;\n --ra-info: var(--ra-blue, 214 95% 55%);\n --ra-success: var(--ra-emerald, 142 71% 45%);\n --ra-warning: var(--ra-amber, 38 92% 50%);\n --ra-danger: var(--destructive, 0 72% 51%);\n}\n.ra-status-dot {\n display: inline-block;\n width: var(--ra-dot-size);\n height: var(--ra-dot-size);\n border-radius: 9999px;\n flex-shrink: 0;\n}\n.ra-status-own {\n background: hsl(var(--ra-status-own));\n}\n.ra-status-shared {\n background: hsl(var(--ra-status-shared));\n}\n.ra-status-missing {\n background: hsl(var(--ra-status-missing) / 0.4);\n border: 1px solid hsl(var(--ra-status-missing) / 0.6);\n}\n.ra-row-active {\n background: var(--ra-row-active-bg);\n border-color: var(--ra-row-active-bd) !important;\n}\n');
|
|
2657
3347
|
|
|
2658
3348
|
// src/components/RecordsAdmin/shell/shell.css
|
|
2659
|
-
styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(--ra-page-bg));\n font-family: var(--ra-font-ui);\n}\n.ra-shell *,\n.ra-shell *::before,\n.ra-shell *::after {\n box-sizing: border-box;\n}\n.ra-shell .ra-card {\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-card-hover {\n transition:\n box-shadow .18s ease,\n transform .18s ease,\n border-color .18s ease;\n}\n.ra-shell .ra-card-hover:hover {\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-display {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-title {\n font-weight: var(--ra-title-weight);\n}\n.ra-shell :where(button, [role=button], input, select, textarea, a):focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n border-radius: calc(var(--ra-radius) * 0.6);\n}\n.ra-shell .ra-header {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.65rem 0.9rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-accent) / 0.12);\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.08),\n hsl(var(--ra-accent) / 0.02) 60%,\n hsl(var(--ra-surface)) 100%);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-header__main {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n.ra-shell .ra-header-aside {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-header-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: calc(var(--ra-radius) * 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n border: 1px solid hsl(var(--ra-accent) / 0.18);\n}\n.ra-shell .ra-header-text {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-header-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n line-height: 1.2;\n color: hsl(var(--ra-text));\n letter-spacing: -0.01em;\n margin: 0;\n}\n.ra-shell .ra-header-subtitle {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-header-stats {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n padding: 0.15rem 0.4rem;\n border-radius: calc(var(--ra-radius) * 0.75);\n background: hsl(var(--ra-surface) / 0.7);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-header-stats--titled {\n flex-direction: column;\n align-items: stretch;\n padding: 0.4rem 0.55rem;\n gap: 0.3rem;\n}\n.ra-shell .ra-header-stats .ra-stats-items {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n}\n.ra-shell .ra-header-stats .ra-stats-heading {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n color: hsl(var(--ra-muted-text));\n font-size: 0.65rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon {\n display: inline-flex;\n align-items: center;\n color: hsl(var(--ra-text));\n opacity: 0.75;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon > svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0.15rem 0.45rem;\n min-width: 2.5rem;\n}\n.ra-shell .ra-stat-value {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n line-height: 1;\n}\n.ra-shell .ra-stat-label {\n font-size: 0.6rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-stat-divider {\n width: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-header-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.ra-shell .ra-tabs {\n display: flex;\n gap: 0.25rem;\n padding: 0.25rem;\n background: hsl(var(--ra-muted));\n border-radius: calc(var(--ra-radius) * 0.85);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-tab {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.7rem;\n border-radius: calc(var(--ra-radius) * 0.65);\n font-size: 0.78rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n transition:\n background .15s ease,\n color .15s ease,\n transform .15s ease;\n white-space: nowrap;\n}\n.ra-shell .ra-tab:hover {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-tab[aria-selected=true] {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n box-shadow: var(--ra-card-shadow);\n font-weight: var(--ra-title-weight);\n}\n.ra-shell .ra-tab[aria-selected=true] .ra-tab-icon {\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-tab[disabled] {\n opacity: .5;\n cursor: not-allowed;\n}\n.ra-shell .ra-tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 0.35rem;\n height: 1.1rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n font-size: 0.625rem;\n font-weight: 600;\n line-height: 1;\n}\n.ra-shell .ra-tab[aria-selected=false] .ra-tab-count {\n background: hsl(var(--ra-muted-text) / 0.15);\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.4rem;\n}\n.ra-shell[data-density=compact] .ra-header {\n padding: 0.75rem 1rem;\n}\n.ra-shell[data-density=compact] .ra-header-icon {\n width: 2.25rem;\n height: 2.25rem;\n}\n.ra-shell .ra-row {\n display: flex;\n align-items: center;\n gap: 0.65rem;\n width: 100%;\n text-align: left;\n padding: 0.65rem 0.85rem;\n border-left: 3px solid transparent;\n background: transparent;\n border-bottom: 1px solid transparent;\n transition: background .12s ease, border-color .12s ease;\n cursor: pointer;\n color: hsl(var(--ra-text));\n font-family: inherit;\n}\n.ra-shell .ra-row + .ra-row {\n border-top: 1px solid hsl(var(--ra-border) / 0.6);\n}\n.ra-shell .ra-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n border-left-color: var(--ra-row-active-bd);\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-icon {\n background: hsl(var(--ra-accent) / 0.15);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-row-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n line-height: 1.25;\n color: hsl(var(--ra-text));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-actions {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n margin-left: auto;\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-row:hover .ra-row-actions,\n.ra-shell .ra-row:focus-within .ra-row-actions {\n opacity: 1;\n}\n.ra-shell .ra-row-action {\n width: 1.6rem;\n height: 1.6rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .15s ease, color .15s ease;\n}\n.ra-shell .ra-row-action:hover {\n background: hsl(var(--ra-accent) / 0.10);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-action[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.12);\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0.15rem 0.5rem;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 500;\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n white-space: nowrap;\n max-width: 14rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-chip[data-tone=success] {\n background: hsl(var(--ra-success) / 0.12);\n color: hsl(var(--ra-success));\n border-color: hsl(var(--ra-success) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=warning] {\n background: hsl(var(--ra-warning) / 0.14);\n color: hsl(var(--ra-warning));\n border-color: hsl(var(--ra-warning) / 0.35);\n}\n.ra-shell .ra-chip[data-tone=info] {\n background: hsl(var(--ra-info) / 0.10);\n color: hsl(var(--ra-info));\n border-color: hsl(var(--ra-info) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=danger] {\n background: hsl(var(--ra-danger) / 0.10);\n color: hsl(var(--ra-danger));\n border-color: hsl(var(--ra-danger) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=muted] {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-style: dashed;\n}\n.ra-shell .ra-group {\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-group:last-child {\n border-bottom: 0;\n}\n.ra-shell .ra-group-summary {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.6);\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-group-summary:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-group-summary .ra-group-chevron {\n transition: transform .15s ease;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-chevron {\n transform: rotate(-90deg);\n}\n.ra-shell .ra-group-name {\n flex: 1;\n text-align: left;\n}\n.ra-shell .ra-group-count {\n font-size: 0.65rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.4rem;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-body {\n display: none;\n}\n.ra-shell .ra-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2.5rem 1.5rem;\n gap: 0.75rem;\n}\n.ra-shell .ra-empty-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.08);\n color: hsl(var(--ra-accent));\n margin-bottom: 0.25rem;\n}\n.ra-shell .ra-empty-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n color: hsl(var(--ra-text));\n margin: 0;\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-empty-body {\n font-size: 0.8125rem;\n color: hsl(var(--ra-muted-text));\n max-width: 22rem;\n line-height: 1.45;\n}\n.ra-shell .ra-empty-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n flex-wrap: wrap;\n justify-content: center;\n}\n.ra-shell .ra-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.45rem 0.85rem;\n border-radius: calc(var(--ra-radius) * 0.7);\n font-size: 0.8125rem;\n font-weight: 500;\n border: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n cursor: pointer;\n transition:\n background .15s ease,\n border-color .15s ease,\n box-shadow .15s ease,\n transform .1s ease;\n}\n.ra-shell .ra-btn:hover {\n background: hsl(var(--ra-muted));\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-btn:active {\n transform: translateY(1px);\n}\n.ra-shell .ra-btn[data-variant=primary] {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-surface));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-btn[data-variant=primary]:hover {\n background: hsl(var(--ra-accent) / 0.92);\n}\n.ra-shell .ra-btn[data-variant=ghost] {\n background: transparent;\n border-color: transparent;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-btn[data-variant=ghost]:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-btn[data-variant=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-btn[data-variant=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n border-color: hsl(var(--ra-danger) / 0.40);\n}\n.ra-shell .ra-intro {\n position: relative;\n display: flex;\n gap: 0.85rem;\n padding: 0.9rem 1rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-info) / 0.30);\n background: hsl(var(--ra-info) / 0.08);\n margin-bottom: 1rem;\n}\n.ra-shell .ra-intro[data-tone=success] {\n border-color: hsl(var(--ra-success) / 0.30);\n background: hsl(var(--ra-success) / 0.08);\n}\n.ra-shell .ra-intro[data-tone=warning] {\n border-color: hsl(var(--ra-warning) / 0.35);\n background: hsl(var(--ra-warning) / 0.10);\n}\n.ra-shell .ra-intro-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-info) / 0.18);\n color: hsl(var(--ra-info));\n}\n.ra-shell .ra-intro[data-tone=success] .ra-intro-icon {\n background: hsl(var(--ra-success) / 0.18);\n color: hsl(var(--ra-success));\n}\n.ra-shell .ra-intro[data-tone=warning] .ra-intro-icon {\n background: hsl(var(--ra-warning) / 0.20);\n color: hsl(var(--ra-warning));\n}\n.ra-shell .ra-intro-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-intro-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n color: hsl(var(--ra-text));\n margin: 0 0 0.2rem 0;\n}\n.ra-shell .ra-intro-text {\n font-size: 0.8125rem;\n color: hsl(var(--ra-text) / 0.85);\n line-height: 1.45;\n}\n.ra-shell .ra-intro-dismiss {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.6rem;\n height: 1.6rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 0;\n color: hsl(var(--ra-muted-text));\n cursor: pointer;\n}\n.ra-shell .ra-intro-dismiss:hover {\n background: hsl(var(--ra-text) / 0.06);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-bulk-menu {\n min-width: 12rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow-hover);\n padding: 0.3rem;\n z-index: 60;\n}\n.ra-shell .ra-bulk-item {\n display: flex;\n align-items: center;\n gap: 0.55rem;\n width: 100%;\n padding: 0.45rem 0.6rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-bulk-item:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-bulk-item[data-tone=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-bulk-item[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n}\n.ra-shell .ra-bulk-divider {\n height: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-preview-rail {\n background: hsl(var(--ra-surface));\n border-left: 1px solid hsl(var(--ra-border));\n box-shadow: -4px 0 16px hsl(var(--ra-accent) / 0.04);\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.ra-shell .ra-preview-rail-header {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background:\n linear-gradient(\n 180deg,\n hsl(var(--ra-surface)) 0%,\n hsl(var(--ra-surface) / 0.92) 100%);\n border-bottom: 1px solid hsl(var(--ra-border));\n backdrop-filter: blur(6px);\n}\n.ra-shell .ra-preview-rail-title {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-preview-rail-body {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n}\n.ra-confirm-root {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n}\n.ra-confirm-root .ra-confirm-backdrop {\n position: absolute;\n inset: 0;\n background: hsl(0 0% 0% / 0.45);\n backdrop-filter: blur(2px);\n animation: ra-confirm-fade .12s ease-out;\n}\n.ra-confirm-root .ra-confirm-card {\n position: relative;\n width: min(440px, 100%);\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08), 0 24px 48px -12px hsl(0 0% 0% / 0.32);\n padding: 1.25rem;\n animation: ra-confirm-pop .14s ease-out;\n}\n.ra-confirm-root .ra-confirm-header {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n margin-bottom: 0.5rem;\n}\n.ra-confirm-root .ra-confirm-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 999px;\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.12);\n color: hsl(var(--ra-warning, 38 92% 50%));\n}\n.ra-confirm-root .ra-confirm-title {\n font-family: var(--ra-font-display);\n font-weight: 600;\n font-size: 1rem;\n margin: 0;\n}\n.ra-confirm-root .ra-confirm-body {\n font-size: 0.875rem;\n color: hsl(var(--ra-muted-text));\n margin: 0 0 1.1rem;\n line-height: 1.45;\n}\n.ra-confirm-root .ra-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.ra-confirm-root .ra-confirm-btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.45rem 0.85rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease;\n}\n.ra-confirm-root .ra-confirm-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-confirm-root .ra-confirm-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-confirm-root .ra-confirm-btn-ghost:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-confirm-root .ra-confirm-btn-danger {\n background: transparent;\n color: hsl(var(--ra-danger, 0 72% 51%));\n border-color: hsl(var(--ra-danger, 0 72% 51%) / 0.45);\n}\n.ra-confirm-root .ra-confirm-btn-danger:hover {\n background: hsl(var(--ra-danger, 0 72% 51%) / 0.08);\n border-color: hsl(var(--ra-danger, 0 72% 51%));\n}\n.ra-confirm-root .ra-confirm-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-confirm-root .ra-confirm-btn-primary:hover {\n filter: brightness(0.95);\n}\n@keyframes ra-confirm-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes ra-confirm-pop {\n from {\n opacity: 0;\n transform: translateY(4px) scale(.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ra-shell .ra-unsaved-banner {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 0.75rem;\n border: 1px solid hsl(var(--ra-warning, 38 92% 50%) / 0.35);\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.08);\n border-radius: var(--ra-radius);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n animation: ra-unsaved-slide .14s ease-out;\n}\n.ra-shell .ra-unsaved-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-warning, 38 92% 50%));\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ra-shell .ra-unsaved-context {\n color: hsl(var(--ra-muted-text));\n font-weight: 400;\n}\n.ra-shell .ra-unsaved-error {\n color: hsl(var(--ra-danger, 0 72% 51%));\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: 500;\n}\n.ra-shell .ra-unsaved-actions {\n display: inline-flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.3rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease,\n opacity .12s ease;\n}\n.ra-shell .ra-unsaved-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ra-shell .ra-unsaved-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-shell .ra-unsaved-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-shell .ra-unsaved-btn-ghost:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-unsaved-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-unsaved-btn-primary:hover:not(:disabled) {\n filter: brightness(0.95);\n}\n@keyframes ra-unsaved-slide {\n from {\n opacity: 0;\n transform: translateY(-3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n");
|
|
3349
|
+
styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(--ra-page-bg));\n font-family: var(--ra-font-ui);\n}\n.ra-shell *,\n.ra-shell *::before,\n.ra-shell *::after {\n box-sizing: border-box;\n}\n.ra-shell .ra-card {\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-card-hover {\n transition:\n box-shadow .18s ease,\n transform .18s ease,\n border-color .18s ease;\n}\n.ra-shell .ra-card-hover:hover {\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-display {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-title {\n font-weight: var(--ra-title-weight);\n}\n.ra-shell :where(button, [role=button], input, select, textarea, a):focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n border-radius: calc(var(--ra-radius) * 0.6);\n}\n.ra-shell .ra-header {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.65rem 0.9rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-accent) / 0.12);\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.08),\n hsl(var(--ra-accent) / 0.02) 60%,\n hsl(var(--ra-surface)) 100%);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-header__main {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n.ra-shell .ra-header-aside {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-header-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: calc(var(--ra-radius) * 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n border: 1px solid hsl(var(--ra-accent) / 0.18);\n}\n.ra-shell .ra-header-text {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-header-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n line-height: 1.2;\n color: hsl(var(--ra-text));\n letter-spacing: -0.01em;\n margin: 0;\n}\n.ra-shell .ra-header-subtitle {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-header-stats {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n padding: 0.15rem 0.4rem;\n border-radius: calc(var(--ra-radius) * 0.75);\n background: hsl(var(--ra-surface) / 0.7);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-header-stats--titled {\n flex-direction: column;\n align-items: stretch;\n padding: 0.4rem 0.55rem;\n gap: 0.3rem;\n}\n.ra-shell .ra-header-stats .ra-stats-items {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n}\n.ra-shell .ra-header-stats .ra-stats-heading {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n color: hsl(var(--ra-muted-text));\n font-size: 0.65rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon {\n display: inline-flex;\n align-items: center;\n color: hsl(var(--ra-text));\n opacity: 0.75;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon > svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0.15rem 0.45rem;\n min-width: 2.5rem;\n}\n.ra-shell .ra-stat-value {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n line-height: 1;\n}\n.ra-shell .ra-stat-label {\n font-size: 0.6rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-stat-divider {\n width: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-header-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.ra-shell .ra-tabs {\n display: flex;\n gap: 0.25rem;\n padding: 0.25rem;\n background: hsl(var(--ra-muted));\n border-radius: calc(var(--ra-radius) * 0.85);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-tab {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.7rem;\n border-radius: calc(var(--ra-radius) * 0.65);\n font-size: 0.78rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n transition:\n background .15s ease,\n color .15s ease,\n transform .15s ease;\n white-space: nowrap;\n}\n.ra-shell .ra-tab:hover {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-tab[aria-selected=true] {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n box-shadow: var(--ra-card-shadow);\n font-weight: var(--ra-title-weight);\n}\n.ra-shell .ra-tab[aria-selected=true] .ra-tab-icon {\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-tab[disabled] {\n opacity: .5;\n cursor: not-allowed;\n}\n.ra-shell .ra-tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 0.35rem;\n height: 1.1rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n font-size: 0.625rem;\n font-weight: 600;\n line-height: 1;\n}\n.ra-shell .ra-tab[aria-selected=false] .ra-tab-count {\n background: hsl(var(--ra-muted-text) / 0.15);\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.4rem;\n}\n.ra-shell[data-density=compact] .ra-header {\n padding: 0.75rem 1rem;\n}\n.ra-shell[data-density=compact] .ra-header-icon {\n width: 2.25rem;\n height: 2.25rem;\n}\n.ra-shell .ra-row {\n display: flex;\n align-items: center;\n gap: 0.65rem;\n width: 100%;\n text-align: left;\n padding: 0.65rem 0.85rem;\n border-left: 3px solid transparent;\n background: transparent;\n border-bottom: 1px solid transparent;\n transition: background .12s ease, border-color .12s ease;\n cursor: pointer;\n color: hsl(var(--ra-text));\n font-family: inherit;\n}\n.ra-shell .ra-row + .ra-row {\n border-top: 1px solid hsl(var(--ra-border) / 0.6);\n}\n.ra-shell .ra-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n border-left-color: var(--ra-row-active-bd);\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-icon {\n background: hsl(var(--ra-accent) / 0.15);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-row-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n line-height: 1.25;\n color: hsl(var(--ra-text));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-actions {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n margin-left: auto;\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-row:hover .ra-row-actions,\n.ra-shell .ra-row:focus-within .ra-row-actions {\n opacity: 1;\n}\n.ra-shell .ra-row-action {\n width: 1.6rem;\n height: 1.6rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .15s ease, color .15s ease;\n}\n.ra-shell .ra-row-action:hover {\n background: hsl(var(--ra-accent) / 0.10);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-action[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.12);\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0.15rem 0.5rem;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 500;\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n white-space: nowrap;\n max-width: 14rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-chip[data-tone=success] {\n background: hsl(var(--ra-success) / 0.12);\n color: hsl(var(--ra-success));\n border-color: hsl(var(--ra-success) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=warning] {\n background: hsl(var(--ra-warning) / 0.14);\n color: hsl(var(--ra-warning));\n border-color: hsl(var(--ra-warning) / 0.35);\n}\n.ra-shell .ra-chip[data-tone=info] {\n background: hsl(var(--ra-info) / 0.10);\n color: hsl(var(--ra-info));\n border-color: hsl(var(--ra-info) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=danger] {\n background: hsl(var(--ra-danger) / 0.10);\n color: hsl(var(--ra-danger));\n border-color: hsl(var(--ra-danger) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=muted] {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-style: dashed;\n}\n.ra-shell .ra-group {\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-group:last-child {\n border-bottom: 0;\n}\n.ra-shell .ra-group-summary {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.6);\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-group-summary:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-group-summary .ra-group-chevron {\n transition: transform .15s ease;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-chevron {\n transform: rotate(-90deg);\n}\n.ra-shell .ra-group-name {\n flex: 1;\n text-align: left;\n}\n.ra-shell .ra-group-count {\n font-size: 0.65rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.4rem;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-body {\n display: none;\n}\n.ra-shell .ra-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2.5rem 1.5rem;\n gap: 0.75rem;\n}\n.ra-shell .ra-empty-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.08);\n color: hsl(var(--ra-accent));\n margin-bottom: 0.25rem;\n}\n.ra-shell .ra-empty-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n color: hsl(var(--ra-text));\n margin: 0;\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-empty-body {\n font-size: 0.8125rem;\n color: hsl(var(--ra-muted-text));\n max-width: 22rem;\n line-height: 1.45;\n}\n.ra-shell .ra-empty-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n flex-wrap: wrap;\n justify-content: center;\n}\n.ra-shell .ra-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.45rem 0.85rem;\n border-radius: calc(var(--ra-radius) * 0.7);\n font-size: 0.8125rem;\n font-weight: 500;\n border: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n cursor: pointer;\n transition:\n background .15s ease,\n border-color .15s ease,\n box-shadow .15s ease,\n transform .1s ease;\n}\n.ra-shell .ra-btn:hover {\n background: hsl(var(--ra-muted));\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-btn:active {\n transform: translateY(1px);\n}\n.ra-shell .ra-btn[data-variant=primary] {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-surface));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-btn[data-variant=primary]:hover {\n background: hsl(var(--ra-accent) / 0.92);\n}\n.ra-shell .ra-btn[data-variant=ghost] {\n background: transparent;\n border-color: transparent;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-btn[data-variant=ghost]:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-btn[data-variant=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-btn[data-variant=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n border-color: hsl(var(--ra-danger) / 0.40);\n}\n.ra-shell .ra-intro {\n position: relative;\n display: flex;\n gap: 0.85rem;\n padding: 0.9rem 1rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-info) / 0.30);\n background: hsl(var(--ra-info) / 0.08);\n margin-bottom: 1rem;\n}\n.ra-shell .ra-intro[data-tone=success] {\n border-color: hsl(var(--ra-success) / 0.30);\n background: hsl(var(--ra-success) / 0.08);\n}\n.ra-shell .ra-intro[data-tone=warning] {\n border-color: hsl(var(--ra-warning) / 0.35);\n background: hsl(var(--ra-warning) / 0.10);\n}\n.ra-shell .ra-intro-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-info) / 0.18);\n color: hsl(var(--ra-info));\n}\n.ra-shell .ra-intro[data-tone=success] .ra-intro-icon {\n background: hsl(var(--ra-success) / 0.18);\n color: hsl(var(--ra-success));\n}\n.ra-shell .ra-intro[data-tone=warning] .ra-intro-icon {\n background: hsl(var(--ra-warning) / 0.20);\n color: hsl(var(--ra-warning));\n}\n.ra-shell .ra-intro-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-intro-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n color: hsl(var(--ra-text));\n margin: 0 0 0.2rem 0;\n}\n.ra-shell .ra-intro-text {\n font-size: 0.8125rem;\n color: hsl(var(--ra-text) / 0.85);\n line-height: 1.45;\n}\n.ra-shell .ra-intro-dismiss {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.6rem;\n height: 1.6rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 0;\n color: hsl(var(--ra-muted-text));\n cursor: pointer;\n}\n.ra-shell .ra-intro-dismiss:hover {\n background: hsl(var(--ra-text) / 0.06);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-bulk-menu {\n min-width: 12rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow-hover);\n padding: 0.3rem;\n z-index: 60;\n}\n.ra-shell .ra-bulk-item {\n display: flex;\n align-items: center;\n gap: 0.55rem;\n width: 100%;\n padding: 0.45rem 0.6rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-bulk-item:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-bulk-item[data-tone=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-bulk-item[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n}\n.ra-shell .ra-bulk-divider {\n height: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-preview-rail {\n background: hsl(var(--ra-surface));\n border-left: 1px solid hsl(var(--ra-border));\n box-shadow: -4px 0 16px hsl(var(--ra-accent) / 0.04);\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.ra-shell .ra-preview-rail-header {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background:\n linear-gradient(\n 180deg,\n hsl(var(--ra-surface)) 0%,\n hsl(var(--ra-surface) / 0.92) 100%);\n border-bottom: 1px solid hsl(var(--ra-border));\n backdrop-filter: blur(6px);\n}\n.ra-shell .ra-preview-rail-title {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-preview-rail-body {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n}\n.ra-confirm-root {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n}\n.ra-confirm-root .ra-confirm-backdrop {\n position: absolute;\n inset: 0;\n background: hsl(0 0% 0% / 0.45);\n backdrop-filter: blur(2px);\n animation: ra-confirm-fade .12s ease-out;\n}\n.ra-confirm-root .ra-confirm-card {\n position: relative;\n width: min(440px, 100%);\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08), 0 24px 48px -12px hsl(0 0% 0% / 0.32);\n padding: 1.25rem;\n animation: ra-confirm-pop .14s ease-out;\n}\n.ra-confirm-root .ra-confirm-header {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n margin-bottom: 0.5rem;\n}\n.ra-confirm-root .ra-confirm-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 999px;\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.12);\n color: hsl(var(--ra-warning, 38 92% 50%));\n}\n.ra-confirm-root .ra-confirm-title {\n font-family: var(--ra-font-display);\n font-weight: 600;\n font-size: 1rem;\n margin: 0;\n}\n.ra-confirm-root .ra-confirm-body {\n font-size: 0.875rem;\n color: hsl(var(--ra-muted-text));\n margin: 0 0 1.1rem;\n line-height: 1.45;\n}\n.ra-confirm-root .ra-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.ra-confirm-root .ra-confirm-btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.45rem 0.85rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease;\n}\n.ra-confirm-root .ra-confirm-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-confirm-root .ra-confirm-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-confirm-root .ra-confirm-btn-ghost:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-confirm-root .ra-confirm-btn-danger {\n background: transparent;\n color: hsl(var(--ra-danger, 0 72% 51%));\n border-color: hsl(var(--ra-danger, 0 72% 51%) / 0.45);\n}\n.ra-confirm-root .ra-confirm-btn-danger:hover {\n background: hsl(var(--ra-danger, 0 72% 51%) / 0.08);\n border-color: hsl(var(--ra-danger, 0 72% 51%));\n}\n.ra-confirm-root .ra-confirm-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-confirm-root .ra-confirm-btn-primary:hover {\n filter: brightness(0.95);\n}\n@keyframes ra-confirm-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes ra-confirm-pop {\n from {\n opacity: 0;\n transform: translateY(4px) scale(.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ra-shell .ra-unsaved-banner {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 0.75rem;\n border: 1px solid hsl(var(--ra-warning, 38 92% 50%) / 0.35);\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.08);\n border-radius: var(--ra-radius);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n animation: ra-unsaved-slide .14s ease-out;\n}\n.ra-shell .ra-unsaved-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-warning, 38 92% 50%));\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ra-shell .ra-unsaved-context {\n color: hsl(var(--ra-muted-text));\n font-weight: 400;\n}\n.ra-shell .ra-unsaved-error {\n color: hsl(var(--ra-danger, 0 72% 51%));\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: 500;\n}\n.ra-shell .ra-unsaved-actions {\n display: inline-flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.3rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease,\n opacity .12s ease;\n}\n.ra-shell .ra-unsaved-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ra-shell .ra-unsaved-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-shell .ra-unsaved-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-shell .ra-unsaved-btn-ghost:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-unsaved-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-unsaved-btn-primary:hover:not(:disabled) {\n filter: brightness(0.95);\n}\n@keyframes ra-unsaved-slide {\n from {\n opacity: 0;\n transform: translateY(-3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ra-shell .ra-clipboard-toast {\n position: fixed;\n bottom: 1.25rem;\n left: 50%;\n transform: translateX(-50%);\n z-index: 90;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n max-width: min(28rem, calc(100vw - 2rem));\n padding: 0.55rem 0.85rem;\n border-radius: 999px;\n background: hsl(var(--ra-text));\n color: hsl(var(--ra-surface));\n font-size: 0.75rem;\n line-height: 1;\n box-shadow: 0 8px 24px -10px hsl(0 0% 0% / 0.45);\n animation: ra-clipboard-pop 0.18s ease-out both;\n pointer-events: none;\n}\n@keyframes ra-clipboard-pop {\n from {\n opacity: 0;\n transform: translate(-50%, 6px);\n }\n to {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n}\n.ra-shell .ra-row-menu-wrap {\n display: inline-flex;\n align-items: center;\n margin-left: 0.25rem;\n}\n.ra-shell .ra-row-menu-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n border-radius: 0.35rem;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n opacity: 0;\n transition:\n opacity .15s ease,\n background .15s ease,\n color .15s ease;\n border: 1px solid transparent;\n}\n.ra-shell .ra-row:hover .ra-row-menu-trigger,\n.ra-shell .ra-card-hover:hover .ra-row-menu-trigger,\n.ra-shell .ra-row-menu-trigger:focus-visible,\n.ra-shell .ra-row-menu-trigger[aria-expanded=true] {\n opacity: 1;\n}\n.ra-shell .ra-row-menu-trigger:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-menu {\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n z-index: 50;\n min-width: 11rem;\n padding: 0.25rem;\n border-radius: 0.5rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n box-shadow: 0 12px 28px -10px hsl(0 0% 0% / 0.25);\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n}\n.ra-shell .ra-row-menu-item {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.4rem 0.55rem;\n border-radius: 0.35rem;\n font-size: 0.75rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n text-align: left;\n width: 100%;\n cursor: pointer;\n}\n.ra-shell .ra-row-menu-item:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-row-menu-item:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ra-shell .ra-item-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.ra-shell .ra-item-list-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 1rem 1.25rem 1.5rem;\n}\n.ra-shell .ra-item-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n padding: 0.75rem 1.25rem;\n border-bottom: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n}\n.ra-shell .ra-item-toolbar-title {\n display: flex;\n align-items: baseline;\n gap: 0.5rem;\n min-width: 0;\n}\n.ra-shell .ra-item-toolbar-count {\n font-size: 0.7rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-muted));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.45rem;\n}\n.ra-shell .ra-item-toolbar-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-item-table-wrap {\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n background: hsl(var(--ra-surface));\n overflow: hidden;\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-item-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-item-table thead th {\n text-align: left;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n padding: 0.65rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.55);\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-item-table tbody td {\n padding: 0.65rem 0.85rem;\n border-bottom: 1px solid hsl(var(--ra-border) / 0.7);\n vertical-align: middle;\n}\n.ra-shell .ra-item-table tbody tr:last-child td {\n border-bottom: 0;\n}\n.ra-shell .ra-item-row {\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-item-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-item-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n}\n.ra-shell .ra-item-row-title {\n font-weight: var(--ra-title-weight);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-item-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-item-row-meta {\n font-size: 0.78rem;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-item-row-actions {\n text-align: right;\n white-space: nowrap;\n}\n.ra-shell .ra-item-row-actions .ra-row-action + .ra-row-action {\n margin-left: 0.15rem;\n}\n.ra-shell .ra-item-cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 0.85rem;\n}\n.ra-shell .ra-item-gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 1rem;\n}\n.ra-shell .ra-item-card {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n text-align: left;\n padding: 0;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n overflow: hidden;\n cursor: pointer;\n transition:\n box-shadow .18s ease,\n transform .12s ease,\n border-color .15s ease;\n box-shadow: var(--ra-card-shadow);\n font-family: inherit;\n color: inherit;\n}\n.ra-shell .ra-item-card:hover {\n box-shadow: var(--ra-card-shadow-hover);\n border-color: hsl(var(--ra-accent) / 0.30);\n}\n.ra-shell .ra-item-card[data-selected=true] {\n border-color: hsl(var(--ra-accent) / 0.55);\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-item-card-thumb {\n width: 100%;\n aspect-ratio: 1 / 1;\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.12),\n hsl(var(--ra-accent) / 0.04));\n display: flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-accent));\n overflow: hidden;\n}\n.ra-shell .ra-item-card-thumb--gallery {\n aspect-ratio: 16 / 9;\n}\n.ra-shell .ra-item-card-thumb img {\n width: 100%;\n height: 100%;\n -o-object-fit: cover;\n object-fit: cover;\n}\n.ra-shell .ra-item-card-initials {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1.5rem;\n letter-spacing: 0.02em;\n}\n.ra-shell .ra-item-card-body {\n padding: 0.65rem 0.8rem 0.85rem;\n min-width: 0;\n}\n.ra-shell .ra-item-card-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.85rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-item-card-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-item-card-delete {\n position: absolute;\n top: 0.4rem;\n right: 0.4rem;\n background: hsl(var(--ra-surface) / 0.85);\n backdrop-filter: blur(4px);\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-item-card:hover .ra-item-card-delete,\n.ra-shell .ra-item-card:focus-within .ra-item-card-delete {\n opacity: 1;\n}\n.ra-shell .ra-item-nav {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 1.25rem;\n border-bottom: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n}\n.ra-shell .ra-item-nav-position {\n font-size: 0.72rem;\n color: hsl(var(--ra-muted-text));\n font-variant-numeric: tabular-nums;\n}\n.ra-shell .ra-item-nav-arrows {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n}\n.ra-shell .ra-item-nav-arrows .ra-row-action[disabled] {\n opacity: 0.35;\n cursor: not-allowed;\n}\n.ra-shell .ra-sibling-rail {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.ra-shell .ra-sibling-back {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.6rem 0.85rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-muted) / 0.5);\n border: 0;\n border-bottom: 1px solid hsl(var(--ra-border));\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-sibling-back:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-sibling-heading {\n padding: 0.6rem 0.85rem 0.4rem;\n font-size: 0.65rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-sibling-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n.ra-shell .ra-sibling-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n");
|
|
2660
3350
|
var TOP_LEVEL_SCOPES = ["facet", "product"];
|
|
2661
3351
|
var defaultItemId = () => {
|
|
2662
3352
|
const time = Date.now().toString(36);
|
|
@@ -2689,7 +3379,7 @@ function RecordsAdminShell(props) {
|
|
|
2689
3379
|
renderPreview,
|
|
2690
3380
|
intro,
|
|
2691
3381
|
csvSchema,
|
|
2692
|
-
classify,
|
|
3382
|
+
classify: classify2,
|
|
2693
3383
|
defaultData,
|
|
2694
3384
|
i18n: i18nOverride,
|
|
2695
3385
|
onTelemetry,
|
|
@@ -2705,7 +3395,6 @@ function RecordsAdminShell(props) {
|
|
|
2705
3395
|
disableBeforeUnload = false,
|
|
2706
3396
|
presentations = ["list"],
|
|
2707
3397
|
defaultPresentation,
|
|
2708
|
-
renderCard,
|
|
2709
3398
|
renderListRow,
|
|
2710
3399
|
renderEmpty,
|
|
2711
3400
|
cardinality = "singleton",
|
|
@@ -2724,10 +3413,35 @@ function RecordsAdminShell(props) {
|
|
|
2724
3413
|
icons: iconsOverride,
|
|
2725
3414
|
groupBy,
|
|
2726
3415
|
renderEmptyState,
|
|
2727
|
-
density = "comfortable"
|
|
3416
|
+
density = "comfortable",
|
|
3417
|
+
enableClipboard = true,
|
|
3418
|
+
onCopy: onCopyOverride,
|
|
3419
|
+
onPaste: onPasteOverride,
|
|
3420
|
+
actionLabels,
|
|
3421
|
+
actionIcons,
|
|
3422
|
+
editorTabs = "off",
|
|
3423
|
+
// Right-pane item view (collection cardinality)
|
|
3424
|
+
itemViews = ["table"],
|
|
3425
|
+
defaultItemView,
|
|
3426
|
+
itemColumns,
|
|
3427
|
+
renderItemList,
|
|
3428
|
+
renderItemCard,
|
|
3429
|
+
renderItemEmpty,
|
|
3430
|
+
collectionRailMode = "siblings",
|
|
3431
|
+
// Deep linking
|
|
3432
|
+
deepLink
|
|
2728
3433
|
} = props;
|
|
2729
3434
|
const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
|
|
2730
3435
|
const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
|
|
3436
|
+
const deepLinkState = useDeepLinkState(deepLink);
|
|
3437
|
+
const lastAppliedDLRef = useRef("");
|
|
3438
|
+
const multiOpenWarnedRef = useRef(false);
|
|
3439
|
+
if (editorTabs === "multi" && !multiOpenWarnedRef.current) {
|
|
3440
|
+
multiOpenWarnedRef.current = true;
|
|
3441
|
+
console.warn(
|
|
3442
|
+
'[RecordsAdminShell] editorTabs="multi" is reserved for a future release and currently behaves like "off". Track in records-admin-shell.md.'
|
|
3443
|
+
);
|
|
3444
|
+
}
|
|
2731
3445
|
const [presentation, setPresentation] = usePresentationPref({
|
|
2732
3446
|
appId,
|
|
2733
3447
|
recordType,
|
|
@@ -2738,6 +3452,25 @@ function RecordsAdminShell(props) {
|
|
|
2738
3452
|
onTelemetry?.({ type: "presentation.change", recordType, from: presentation, to: next });
|
|
2739
3453
|
setPresentation(next);
|
|
2740
3454
|
}, [onTelemetry, recordType, presentation, setPresentation]);
|
|
3455
|
+
const [itemView, setItemView] = useItemViewPref({
|
|
3456
|
+
appId,
|
|
3457
|
+
recordType,
|
|
3458
|
+
options: itemViews,
|
|
3459
|
+
defaultValue: defaultItemView ?? itemViews[0] ?? "table"
|
|
3460
|
+
});
|
|
3461
|
+
const onItemViewChange = useCallback((next) => {
|
|
3462
|
+
onTelemetry?.({
|
|
3463
|
+
type: "item.view.change",
|
|
3464
|
+
recordType,
|
|
3465
|
+
scopeRef: "",
|
|
3466
|
+
// populated below if a scope is active
|
|
3467
|
+
from: itemView,
|
|
3468
|
+
to: next
|
|
3469
|
+
});
|
|
3470
|
+
setItemView(next);
|
|
3471
|
+
deepLinkState.emit({ view: next }, "view");
|
|
3472
|
+
}, [onTelemetry, recordType, itemView, setItemView, deepLinkState]);
|
|
3473
|
+
const [selectedItemId, setSelectedItemId] = useState(null);
|
|
2741
3474
|
const ctx = useMemo(
|
|
2742
3475
|
() => ({ SL, collectionId, appId, recordType }),
|
|
2743
3476
|
[SL, collectionId, appId, recordType]
|
|
@@ -2796,6 +3529,15 @@ function RecordsAdminShell(props) {
|
|
|
2796
3529
|
}
|
|
2797
3530
|
}, [contextScope?.batchId]);
|
|
2798
3531
|
const { dismissed, dismiss, undismiss } = useIntroDismissed(SL, collectionId, appId, recordType);
|
|
3532
|
+
const headerWillRender = useMemo(() => {
|
|
3533
|
+
const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
|
|
3534
|
+
return showHeader === true || showHeader !== false && headerCustomised;
|
|
3535
|
+
}, [showHeader, title, subtitle, headerIcon, headerActions, showStats, statsItems, statsTitle, statsIcon]);
|
|
3536
|
+
const resolvedReopenAffordance = useMemo(() => {
|
|
3537
|
+
const requested = intro?.reopenAffordance ?? "header";
|
|
3538
|
+
if (requested === "header" && !headerWillRender) return "footer";
|
|
3539
|
+
return requested;
|
|
3540
|
+
}, [intro?.reopenAffordance, headerWillRender]);
|
|
2799
3541
|
const productBrowse = useProductBrowse({
|
|
2800
3542
|
SL,
|
|
2801
3543
|
collectionId,
|
|
@@ -2807,7 +3549,7 @@ function RecordsAdminShell(props) {
|
|
|
2807
3549
|
scopeKind: activeScope,
|
|
2808
3550
|
search,
|
|
2809
3551
|
filter,
|
|
2810
|
-
classify,
|
|
3552
|
+
classify: classify2,
|
|
2811
3553
|
contextScope,
|
|
2812
3554
|
enabled: activeScope === "facet" && !probe.isLoading
|
|
2813
3555
|
});
|
|
@@ -2862,19 +3604,82 @@ function RecordsAdminShell(props) {
|
|
|
2862
3604
|
}
|
|
2863
3605
|
return parseRef(buildRef({ productId: selectedProductId }));
|
|
2864
3606
|
}, [activeScope, selectedFacetRef, selectedProductId, drillTab, selectedVariantId, selectedBatchId]);
|
|
3607
|
+
const isCollection = cardinality === "collection";
|
|
3608
|
+
const editingItemRef = useMemo(() => {
|
|
3609
|
+
if (!isCollection) return null;
|
|
3610
|
+
if (!selectedItemId) return null;
|
|
3611
|
+
const baseRef = editingScope?.raw ?? "";
|
|
3612
|
+
return buildItemRef(baseRef, selectedItemId);
|
|
3613
|
+
}, [isCollection, selectedItemId, editingScope]);
|
|
3614
|
+
const editingTargetScope = useMemo(() => {
|
|
3615
|
+
if (!isCollection) return editingScope;
|
|
3616
|
+
if (!editingItemRef) return null;
|
|
3617
|
+
return parseRef(editingItemRef);
|
|
3618
|
+
}, [isCollection, editingScope, editingItemRef]);
|
|
3619
|
+
const skipNextItemResetRef = useRef(false);
|
|
3620
|
+
useEffect(() => {
|
|
3621
|
+
if (skipNextItemResetRef.current) {
|
|
3622
|
+
skipNextItemResetRef.current = false;
|
|
3623
|
+
return;
|
|
3624
|
+
}
|
|
3625
|
+
setSelectedItemId(null);
|
|
3626
|
+
}, [editingScope?.raw]);
|
|
3627
|
+
const collectionItems = useCollectionItems({
|
|
3628
|
+
ctx,
|
|
3629
|
+
scope: isCollection ? editingScope : null,
|
|
3630
|
+
enabled: isCollection
|
|
3631
|
+
});
|
|
3632
|
+
useEffect(() => {
|
|
3633
|
+
if (!deepLinkState.enabled) return;
|
|
3634
|
+
if (selectedItemId) return;
|
|
3635
|
+
deepLinkState.emit({ scope: editingScope?.raw ?? null, item: null }, "scope");
|
|
3636
|
+
lastAppliedDLRef.current = `${""}|${editingScope?.raw ?? ""}|${itemView}`;
|
|
3637
|
+
}, [deepLinkState.enabled, editingScope?.raw, selectedItemId, itemView]);
|
|
3638
|
+
useEffect(() => {
|
|
3639
|
+
if (!deepLinkState.enabled) return;
|
|
3640
|
+
const { item, scope, view } = deepLinkState.urlState;
|
|
3641
|
+
const sig = `${item ?? ""}|${scope ?? ""}|${view ?? ""}`;
|
|
3642
|
+
if (sig === lastAppliedDLRef.current) return;
|
|
3643
|
+
lastAppliedDLRef.current = sig;
|
|
3644
|
+
if (view && itemViews.includes(view) && view !== itemView) {
|
|
3645
|
+
setItemView(view);
|
|
3646
|
+
}
|
|
3647
|
+
const railRef = item ? item.includes("item:") ? item.slice(0, item.lastIndexOf("item:")).replace(/\/$/, "") : "" : scope ?? "";
|
|
3648
|
+
const itemId = item ? item.includes("item:") ? item.slice(item.lastIndexOf("item:") + "item:".length) : item : null;
|
|
3649
|
+
const parsed = railRef ? parseRef(railRef) : null;
|
|
3650
|
+
if (parsed?.productId) {
|
|
3651
|
+
if (activeScope !== "product") setActiveScope("product");
|
|
3652
|
+
if (selectedProductId !== parsed.productId) setSelectedProductId(parsed.productId);
|
|
3653
|
+
const nextDrill = parsed.batchId ? "batch" : parsed.variantId ? "variant" : "product";
|
|
3654
|
+
if (drillTab !== nextDrill) setDrillTab(nextDrill);
|
|
3655
|
+
if (parsed.variantId && selectedVariantId !== parsed.variantId) setSelectedVariantId(parsed.variantId);
|
|
3656
|
+
if (parsed.batchId && selectedBatchId !== parsed.batchId) setSelectedBatchId(parsed.batchId);
|
|
3657
|
+
} else if (parsed?.facetId) {
|
|
3658
|
+
if (activeScope !== "facet") setActiveScope("facet");
|
|
3659
|
+
if (selectedFacetRef !== railRef) setSelectedFacetRef(railRef);
|
|
3660
|
+
} else {
|
|
3661
|
+
if (selectedFacetRef) setSelectedFacetRef(void 0);
|
|
3662
|
+
}
|
|
3663
|
+
if (itemId !== selectedItemId) {
|
|
3664
|
+
if (railRef && railRef !== editingScope?.raw) {
|
|
3665
|
+
skipNextItemResetRef.current = true;
|
|
3666
|
+
}
|
|
3667
|
+
setSelectedItemId(itemId);
|
|
3668
|
+
}
|
|
3669
|
+
}, [deepLinkState.enabled, deepLinkState.urlState]);
|
|
2865
3670
|
const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
|
|
2866
3671
|
const resolved = useResolvedRecord({
|
|
2867
3672
|
SL,
|
|
2868
3673
|
appId,
|
|
2869
3674
|
recordType,
|
|
2870
3675
|
collectionId,
|
|
2871
|
-
productId:
|
|
2872
|
-
variantId:
|
|
2873
|
-
batchId:
|
|
2874
|
-
facetId:
|
|
2875
|
-
facetValue:
|
|
3676
|
+
productId: editingTargetScope?.productId,
|
|
3677
|
+
variantId: editingTargetScope?.variantId,
|
|
3678
|
+
batchId: editingTargetScope?.batchId,
|
|
3679
|
+
facetId: editingTargetScope?.facetId,
|
|
3680
|
+
facetValue: editingTargetScope?.facetValue,
|
|
2876
3681
|
supportedScopes: supportedForResolution,
|
|
2877
|
-
enabled: !!
|
|
3682
|
+
enabled: !!editingTargetScope
|
|
2878
3683
|
});
|
|
2879
3684
|
const refetchAll = useCallback(() => {
|
|
2880
3685
|
productBrowse.refetch();
|
|
@@ -2882,20 +3687,23 @@ function RecordsAdminShell(props) {
|
|
|
2882
3687
|
facetBrowse.refetch();
|
|
2883
3688
|
variantChildren.refetch();
|
|
2884
3689
|
batchChildren.refetch();
|
|
2885
|
-
|
|
3690
|
+
if (isCollection) collectionItems.refetch();
|
|
3691
|
+
}, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren, isCollection, collectionItems]);
|
|
2886
3692
|
const editorCtx = useRecordEditor({
|
|
2887
3693
|
ctx,
|
|
2888
|
-
scope:
|
|
3694
|
+
scope: editingTargetScope ?? parseRef(""),
|
|
2889
3695
|
resolved: { data: resolved.data, source: resolved.source, sourceRef: resolved.sourceRef, parentValue: resolved.parentValue },
|
|
2890
3696
|
defaultData,
|
|
2891
3697
|
reseed: dirtyStrategy === "keep" ? "preserve-dirty" : "always",
|
|
2892
3698
|
onSaved: () => {
|
|
2893
|
-
onTelemetry?.({ type: "record.save", recordType, ref:
|
|
3699
|
+
onTelemetry?.({ type: "record.save", recordType, ref: editingTargetScope?.raw ?? "", isCreate: resolved.source !== "self" });
|
|
2894
3700
|
refetchAll();
|
|
2895
3701
|
},
|
|
2896
3702
|
onDeleted: () => {
|
|
2897
|
-
onTelemetry?.({ type: "record.delete", recordType, ref:
|
|
2898
|
-
if (
|
|
3703
|
+
onTelemetry?.({ type: "record.delete", recordType, ref: editingTargetScope?.raw ?? "" });
|
|
3704
|
+
if (isCollection && selectedItemId) {
|
|
3705
|
+
setSelectedItemId(null);
|
|
3706
|
+
} else if (activeScope === "facet") {
|
|
2899
3707
|
setSelectedFacetRef(void 0);
|
|
2900
3708
|
} else if (drillTab === "variant") {
|
|
2901
3709
|
setSelectedVariantId(void 0);
|
|
@@ -2915,6 +3723,12 @@ function RecordsAdminShell(props) {
|
|
|
2915
3723
|
disableParentMessage: dirtyStrategy === "keep"
|
|
2916
3724
|
});
|
|
2917
3725
|
const dirtyConfirm = useConfirmDialog();
|
|
3726
|
+
const pasteConfirm = usePasteConfirm();
|
|
3727
|
+
const clipboard = useRecordClipboard({
|
|
3728
|
+
appId,
|
|
3729
|
+
recordType: recordType ?? "__default"
|
|
3730
|
+
});
|
|
3731
|
+
const [clipboardNotice, setClipboardNotice] = useState(null);
|
|
2918
3732
|
const { runWithGuard } = useDirtyNavigation({
|
|
2919
3733
|
strategy: dirtyStrategy,
|
|
2920
3734
|
isDirty: editorCtx.isDirty,
|
|
@@ -2991,15 +3805,259 @@ function RecordsAdminShell(props) {
|
|
|
2991
3805
|
}
|
|
2992
3806
|
return void 0;
|
|
2993
3807
|
}, [activeScope, editingScope, selectedProductId, productBrowse.items]);
|
|
3808
|
+
const copyCurrent = useCallback(() => {
|
|
3809
|
+
if (!enableClipboard || !editingScope) return;
|
|
3810
|
+
const sourceValue = onCopyOverride ? onCopyOverride({ value: editorCtx.value, scope: editingScope }) : cloneValue(editorCtx.value);
|
|
3811
|
+
clipboard.set({
|
|
3812
|
+
value: sourceValue,
|
|
3813
|
+
sourceScope: editingScope.kind,
|
|
3814
|
+
sourceRef: editingScope.raw,
|
|
3815
|
+
sourceLabel: editorHeaderLabel
|
|
3816
|
+
});
|
|
3817
|
+
onTelemetry?.({ type: "clipboard.copy", recordType, sourceRef: editingScope.raw });
|
|
3818
|
+
setClipboardNotice({
|
|
3819
|
+
message: i18n.copyToast.replace("{name}", editorHeaderLabel ?? editingScope.raw),
|
|
3820
|
+
variant: "copy"
|
|
3821
|
+
});
|
|
3822
|
+
}, [
|
|
3823
|
+
enableClipboard,
|
|
3824
|
+
editingScope,
|
|
3825
|
+
onCopyOverride,
|
|
3826
|
+
editorCtx.value,
|
|
3827
|
+
clipboard,
|
|
3828
|
+
editorHeaderLabel,
|
|
3829
|
+
onTelemetry,
|
|
3830
|
+
recordType,
|
|
3831
|
+
i18n.copyToast
|
|
3832
|
+
]);
|
|
3833
|
+
const pasteCurrent = useCallback(async () => {
|
|
3834
|
+
if (!enableClipboard || !editingScope || !clipboard.entry) return;
|
|
3835
|
+
const compat = checkPasteCompatibility(
|
|
3836
|
+
{ kind: clipboard.entry.sourceScope, raw: clipboard.entry.sourceRef },
|
|
3837
|
+
editingScope
|
|
3838
|
+
);
|
|
3839
|
+
if (compat.status === "denied") {
|
|
3840
|
+
setClipboardNotice({ message: compat.reason ?? "Paste not allowed here", variant: "paste" });
|
|
3841
|
+
return;
|
|
3842
|
+
}
|
|
3843
|
+
if (compat.status === "warn") {
|
|
3844
|
+
const ok = await pasteConfirm.confirm({
|
|
3845
|
+
title: i18n.pasteWarnTitle,
|
|
3846
|
+
body: compat.reason ?? "",
|
|
3847
|
+
confirmLabel: i18n.pasteWarnContinue,
|
|
3848
|
+
cancelLabel: i18n.pasteConfirmCancel
|
|
3849
|
+
});
|
|
3850
|
+
if (!ok) return;
|
|
3851
|
+
}
|
|
3852
|
+
const willReplace = resolved.source === "self";
|
|
3853
|
+
if (willReplace) {
|
|
3854
|
+
const ok = await pasteConfirm.confirm({
|
|
3855
|
+
title: i18n.pasteConfirmTitle,
|
|
3856
|
+
body: i18n.pasteConfirmBody.replace(
|
|
3857
|
+
"{destination}",
|
|
3858
|
+
editorHeaderLabel ?? editingScope.raw
|
|
3859
|
+
),
|
|
3860
|
+
confirmLabel: i18n.pasteConfirmReplace,
|
|
3861
|
+
cancelLabel: i18n.pasteConfirmCancel
|
|
3862
|
+
});
|
|
3863
|
+
if (!ok) return;
|
|
3864
|
+
}
|
|
3865
|
+
const sourceParsed = { kind: clipboard.entry.sourceScope, raw: clipboard.entry.sourceRef };
|
|
3866
|
+
const transformed = onPasteOverride ? onPasteOverride(
|
|
3867
|
+
{ value: clipboard.entry.value, sourceScope: sourceParsed },
|
|
3868
|
+
{ scope: editingScope, currentValue: editorCtx.value ?? null }
|
|
3869
|
+
) : cloneValue(clipboard.entry.value);
|
|
3870
|
+
if (transformed === null) return;
|
|
3871
|
+
editorCtx.onChange(transformed);
|
|
3872
|
+
onTelemetry?.({
|
|
3873
|
+
type: "clipboard.paste",
|
|
3874
|
+
recordType,
|
|
3875
|
+
sourceRef: clipboard.entry.sourceRef,
|
|
3876
|
+
destinationRef: editingScope.raw,
|
|
3877
|
+
replaced: willReplace
|
|
3878
|
+
});
|
|
3879
|
+
setClipboardNotice({
|
|
3880
|
+
message: i18n.pasteToast.replace("{name}", clipboard.entry.sourceLabel ?? clipboard.entry.sourceRef),
|
|
3881
|
+
variant: "paste"
|
|
3882
|
+
});
|
|
3883
|
+
}, [
|
|
3884
|
+
enableClipboard,
|
|
3885
|
+
editingScope,
|
|
3886
|
+
clipboard.entry,
|
|
3887
|
+
pasteConfirm,
|
|
3888
|
+
resolved.source,
|
|
3889
|
+
onPasteOverride,
|
|
3890
|
+
editorCtx,
|
|
3891
|
+
onTelemetry,
|
|
3892
|
+
recordType,
|
|
3893
|
+
editorHeaderLabel,
|
|
3894
|
+
i18n.pasteWarnTitle,
|
|
3895
|
+
i18n.pasteWarnContinue,
|
|
3896
|
+
i18n.pasteConfirmCancel,
|
|
3897
|
+
i18n.pasteConfirmTitle,
|
|
3898
|
+
i18n.pasteConfirmBody,
|
|
3899
|
+
i18n.pasteConfirmReplace,
|
|
3900
|
+
i18n.pasteToast
|
|
3901
|
+
]);
|
|
3902
|
+
const editorPasteCompat = useMemo(() => {
|
|
3903
|
+
if (!enableClipboard || !clipboard.entry || !editingScope) return null;
|
|
3904
|
+
if (clipboard.entry.sourceRef === editingScope.raw) return { status: "denied" };
|
|
3905
|
+
return checkPasteCompatibility(
|
|
3906
|
+
{ kind: clipboard.entry.sourceScope, raw: clipboard.entry.sourceRef },
|
|
3907
|
+
editingScope
|
|
3908
|
+
);
|
|
3909
|
+
}, [enableClipboard, clipboard.entry, editingScope]);
|
|
3910
|
+
const editorClipboard = enableClipboard && editingScope ? {
|
|
3911
|
+
onCopy: copyCurrent,
|
|
3912
|
+
onPaste: () => {
|
|
3913
|
+
void pasteCurrent();
|
|
3914
|
+
},
|
|
3915
|
+
canCopy: true,
|
|
3916
|
+
canPaste: !!clipboard.entry && editorPasteCompat?.status !== "denied",
|
|
3917
|
+
pasteSourceLabel: clipboard.entry?.sourceLabel,
|
|
3918
|
+
pasteWillReplace: resolved.source === "self" && !!clipboard.entry
|
|
3919
|
+
} : void 0;
|
|
3920
|
+
const [pendingPasteRef, setPendingPasteRef] = useState(null);
|
|
3921
|
+
useEffect(() => {
|
|
3922
|
+
if (!pendingPasteRef) return;
|
|
3923
|
+
if (!editingScope || editingScope.raw !== pendingPasteRef) return;
|
|
3924
|
+
const t = window.setTimeout(() => {
|
|
3925
|
+
setPendingPasteRef(null);
|
|
3926
|
+
void pasteCurrent();
|
|
3927
|
+
}, 0);
|
|
3928
|
+
return () => window.clearTimeout(t);
|
|
3929
|
+
}, [pendingPasteRef, editingScope, pasteCurrent]);
|
|
3930
|
+
const rowClipboard = enableClipboard ? (record) => {
|
|
3931
|
+
const summaryHasData = record.data != null;
|
|
3932
|
+
const sourceParsed = record.scope;
|
|
3933
|
+
const compat = clipboard.entry ? checkPasteCompatibility(
|
|
3934
|
+
{ kind: clipboard.entry.sourceScope, raw: clipboard.entry.sourceRef },
|
|
3935
|
+
sourceParsed
|
|
3936
|
+
) : null;
|
|
3937
|
+
const sameRef = clipboard.entry?.sourceRef === record.ref;
|
|
3938
|
+
return {
|
|
3939
|
+
onCopy: summaryHasData ? () => {
|
|
3940
|
+
const value = onCopyOverride ? onCopyOverride({ value: record.data, scope: sourceParsed }) : cloneValue(record.data);
|
|
3941
|
+
clipboard.set({
|
|
3942
|
+
value,
|
|
3943
|
+
sourceScope: sourceParsed.kind,
|
|
3944
|
+
sourceRef: record.ref,
|
|
3945
|
+
sourceLabel: record.label
|
|
3946
|
+
});
|
|
3947
|
+
onTelemetry?.({ type: "clipboard.copy", recordType, sourceRef: record.ref });
|
|
3948
|
+
setClipboardNotice({
|
|
3949
|
+
message: i18n.copyToast.replace("{name}", record.label),
|
|
3950
|
+
variant: "copy"
|
|
3951
|
+
});
|
|
3952
|
+
} : void 0,
|
|
3953
|
+
onPaste: () => {
|
|
3954
|
+
onLeftSelectRef.current?.(record);
|
|
3955
|
+
setPendingPasteRef(record.ref);
|
|
3956
|
+
},
|
|
3957
|
+
canPaste: !!clipboard.entry && !sameRef && compat?.status !== "denied",
|
|
3958
|
+
pasteWillReplace: record.status === "configured",
|
|
3959
|
+
clipboardSourceLabel: clipboard.entry?.sourceLabel
|
|
3960
|
+
};
|
|
3961
|
+
} : void 0;
|
|
3962
|
+
const onLeftSelectRef = useRef(null);
|
|
3963
|
+
const baseScopeRef = editingScope?.raw ?? "";
|
|
3964
|
+
const itemNounLabel = itemNoun || "item";
|
|
3965
|
+
const buildItemUrlValue = useCallback((id) => {
|
|
3966
|
+
return baseScopeRef ? `${baseScopeRef}/item:${id}` : id;
|
|
3967
|
+
}, [baseScopeRef]);
|
|
3968
|
+
const onItemOpen = useCallback((itemId) => {
|
|
3969
|
+
if (!isCollection) return;
|
|
3970
|
+
void runWithGuard(() => {
|
|
3971
|
+
setSelectedItemId(itemId);
|
|
3972
|
+
onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId });
|
|
3973
|
+
deepLinkState.emit({ item: buildItemUrlValue(itemId) }, "item.open");
|
|
3974
|
+
});
|
|
3975
|
+
}, [isCollection, runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
|
|
3976
|
+
const onItemCreate = useCallback(() => {
|
|
3977
|
+
if (!isCollection) return;
|
|
3978
|
+
void runWithGuard(() => {
|
|
3979
|
+
const id = generateItemId ? generateItemId() : defaultItemId();
|
|
3980
|
+
setSelectedItemId(id);
|
|
3981
|
+
onTelemetry?.({ type: "item.create", recordType, scopeRef: baseScopeRef });
|
|
3982
|
+
deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.open");
|
|
3983
|
+
});
|
|
3984
|
+
}, [isCollection, runWithGuard, generateItemId, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
|
|
3985
|
+
const onItemDelete = useCallback(async (itemId) => {
|
|
3986
|
+
if (!isCollection) return;
|
|
3987
|
+
const ref = buildItemRef(baseScopeRef, itemId);
|
|
3988
|
+
if (onBeforeDelete) {
|
|
3989
|
+
const ok = await onBeforeDelete(parseRef(ref));
|
|
3990
|
+
if (!ok) return;
|
|
3991
|
+
}
|
|
3992
|
+
try {
|
|
3993
|
+
const { deleteRecord: deleteRecord2 } = await import('../../records-66QWR67J.js');
|
|
3994
|
+
await deleteRecord2(ctx, ref);
|
|
3995
|
+
onTelemetry?.({ type: "item.delete", recordType, scopeRef: baseScopeRef, itemId });
|
|
3996
|
+
if (selectedItemId === itemId) setSelectedItemId(null);
|
|
3997
|
+
if (selectedItemId === itemId) deepLinkState.emit({ item: null }, "item.close");
|
|
3998
|
+
collectionItems.refetch();
|
|
3999
|
+
} catch (err) {
|
|
4000
|
+
console.error("[RecordsAdminShell] item delete failed", err);
|
|
4001
|
+
}
|
|
4002
|
+
}, [
|
|
4003
|
+
isCollection,
|
|
4004
|
+
baseScopeRef,
|
|
4005
|
+
ctx,
|
|
4006
|
+
onBeforeDelete,
|
|
4007
|
+
onTelemetry,
|
|
4008
|
+
recordType,
|
|
4009
|
+
selectedItemId,
|
|
4010
|
+
collectionItems,
|
|
4011
|
+
deepLinkState
|
|
4012
|
+
]);
|
|
4013
|
+
const itemViewCtx = useMemo(() => ({
|
|
4014
|
+
onOpen: onItemOpen,
|
|
4015
|
+
onCreate: onItemCreate,
|
|
4016
|
+
onDelete: (id) => {
|
|
4017
|
+
void onItemDelete(id);
|
|
4018
|
+
},
|
|
4019
|
+
scope: editingScope ?? parseRef(""),
|
|
4020
|
+
selectedId: selectedItemId ?? void 0,
|
|
4021
|
+
isLoading: collectionItems.isLoading
|
|
4022
|
+
}), [onItemOpen, onItemCreate, onItemDelete, editingScope, selectedItemId, collectionItems.isLoading]);
|
|
4023
|
+
const itemPosition = useMemo(() => {
|
|
4024
|
+
if (!isCollection || !selectedItemId) return null;
|
|
4025
|
+
const idx = collectionItems.items.findIndex((it) => it.itemId === selectedItemId);
|
|
4026
|
+
if (idx < 0) return null;
|
|
4027
|
+
return { index: idx, total: collectionItems.items.length };
|
|
4028
|
+
}, [isCollection, selectedItemId, collectionItems.items]);
|
|
4029
|
+
const onItemBack = useCallback(() => {
|
|
4030
|
+
void runWithGuard(() => {
|
|
4031
|
+
setSelectedItemId(null);
|
|
4032
|
+
deepLinkState.emit({ item: null }, "item.close");
|
|
4033
|
+
});
|
|
4034
|
+
}, [runWithGuard, deepLinkState]);
|
|
4035
|
+
const stepToItem = useCallback((id) => {
|
|
4036
|
+
void runWithGuard(() => {
|
|
4037
|
+
setSelectedItemId(id);
|
|
4038
|
+
onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId: id });
|
|
4039
|
+
deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.step");
|
|
4040
|
+
});
|
|
4041
|
+
}, [runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
|
|
4042
|
+
const onItemPrev = useCallback(() => {
|
|
4043
|
+
if (!itemPosition || itemPosition.index <= 0) return;
|
|
4044
|
+
const next = collectionItems.items[itemPosition.index - 1];
|
|
4045
|
+
if (next?.itemId) stepToItem(next.itemId);
|
|
4046
|
+
}, [itemPosition, collectionItems.items, stepToItem]);
|
|
4047
|
+
const onItemNext = useCallback(() => {
|
|
4048
|
+
if (!itemPosition || itemPosition.index >= itemPosition.total - 1) return;
|
|
4049
|
+
const next = collectionItems.items[itemPosition.index + 1];
|
|
4050
|
+
if (next?.itemId) stepToItem(next.itemId);
|
|
4051
|
+
}, [itemPosition, collectionItems.items, stepToItem]);
|
|
2994
4052
|
const renderEditorWithPreview = () => {
|
|
2995
|
-
if (!
|
|
4053
|
+
if (!editingTargetScope) return null;
|
|
2996
4054
|
const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
|
|
2997
4055
|
const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
2998
4056
|
PreviewScopePicker,
|
|
2999
4057
|
{
|
|
3000
4058
|
SL,
|
|
3001
4059
|
collectionId,
|
|
3002
|
-
editingScope,
|
|
4060
|
+
editingScope: editingTargetScope,
|
|
3003
4061
|
value: effectivePreviewScope,
|
|
3004
4062
|
onChange: setPreviewScope,
|
|
3005
4063
|
showVariants: drillVariantsAllowed,
|
|
@@ -3007,6 +4065,20 @@ function RecordsAdminShell(props) {
|
|
|
3007
4065
|
i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
|
|
3008
4066
|
}
|
|
3009
4067
|
) : null;
|
|
4068
|
+
const itemNav = isCollection && selectedItemId && itemPosition ? /* @__PURE__ */ jsx(
|
|
4069
|
+
EditorItemNav,
|
|
4070
|
+
{
|
|
4071
|
+
label: editorHeaderLabel,
|
|
4072
|
+
position: itemPosition.index + 1,
|
|
4073
|
+
total: itemPosition.total,
|
|
4074
|
+
onBack: onItemBack,
|
|
4075
|
+
onPrev: onItemPrev,
|
|
4076
|
+
onNext: onItemNext,
|
|
4077
|
+
canPrev: itemPosition.index > 0,
|
|
4078
|
+
canNext: itemPosition.index < itemPosition.total - 1,
|
|
4079
|
+
i18n
|
|
4080
|
+
}
|
|
4081
|
+
) : null;
|
|
3010
4082
|
const baseEditor = (extraFooter, inlinePreviewBody) => /* @__PURE__ */ jsx(
|
|
3011
4083
|
RecordEditor,
|
|
3012
4084
|
{
|
|
@@ -3015,71 +4087,86 @@ function RecordsAdminShell(props) {
|
|
|
3015
4087
|
bulkActions: { ...csvBulk, i18n },
|
|
3016
4088
|
preview: inlinePreviewBody,
|
|
3017
4089
|
footerExtra: extraFooter,
|
|
3018
|
-
onBeforeDelete: onBeforeDelete &&
|
|
4090
|
+
onBeforeDelete: onBeforeDelete && editingTargetScope ? () => onBeforeDelete(editingTargetScope) : void 0,
|
|
3019
4091
|
headerLabel: editorHeaderLabel,
|
|
3020
4092
|
headerSubtitle: editorHeaderSubtitle,
|
|
3021
4093
|
headerMeta: editorHeaderMeta,
|
|
4094
|
+
clipboard: editorClipboard,
|
|
4095
|
+
actionLabels,
|
|
4096
|
+
actionIcons,
|
|
3022
4097
|
children: renderEditor(editorCtx)
|
|
3023
4098
|
}
|
|
3024
4099
|
);
|
|
3025
|
-
|
|
4100
|
+
const withNav = (node) => itemNav ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
4101
|
+
itemNav,
|
|
4102
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: node })
|
|
4103
|
+
] }) : node;
|
|
4104
|
+
if (!previewBody) return withNav(baseEditor());
|
|
3026
4105
|
if (previewMode === "inline") {
|
|
3027
|
-
return baseEditor(
|
|
4106
|
+
return withNav(baseEditor(
|
|
3028
4107
|
void 0,
|
|
3029
4108
|
/* @__PURE__ */ jsx(InlinePreview, { label: i18n.preview, scopePicker, children: previewBody })
|
|
3030
|
-
);
|
|
4109
|
+
));
|
|
3031
4110
|
}
|
|
3032
4111
|
if (previewMode === "side") {
|
|
3033
4112
|
if (!sidePreviewOpen) {
|
|
3034
|
-
return
|
|
4113
|
+
return withNav(
|
|
4114
|
+
/* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
|
|
4115
|
+
/* @__PURE__ */ jsx(
|
|
4116
|
+
PreviewToggleButton,
|
|
4117
|
+
{
|
|
4118
|
+
onClick: () => setSidePreviewOpen(true),
|
|
4119
|
+
label: i18n.openPreview
|
|
4120
|
+
}
|
|
4121
|
+
)
|
|
4122
|
+
) })
|
|
4123
|
+
);
|
|
4124
|
+
}
|
|
4125
|
+
return withNav(
|
|
4126
|
+
/* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
|
|
4127
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
|
|
3035
4128
|
/* @__PURE__ */ jsx(
|
|
3036
|
-
|
|
4129
|
+
SidePreview,
|
|
3037
4130
|
{
|
|
3038
|
-
|
|
3039
|
-
|
|
4131
|
+
label: i18n.preview,
|
|
4132
|
+
scopePicker,
|
|
4133
|
+
onClose: () => setSidePreviewOpen(false),
|
|
4134
|
+
children: previewBody
|
|
3040
4135
|
}
|
|
3041
4136
|
)
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
4137
|
+
] })
|
|
4138
|
+
);
|
|
4139
|
+
}
|
|
4140
|
+
if (previewMode === "tab") {
|
|
4141
|
+
return withNav(
|
|
3046
4142
|
/* @__PURE__ */ jsx(
|
|
3047
|
-
|
|
4143
|
+
TabbedPreview,
|
|
3048
4144
|
{
|
|
3049
|
-
|
|
4145
|
+
editor: baseEditor(),
|
|
4146
|
+
preview: previewBody,
|
|
3050
4147
|
scopePicker,
|
|
3051
|
-
|
|
3052
|
-
children: previewBody
|
|
4148
|
+
i18n: { editor: i18n.editor, preview: i18n.preview }
|
|
3053
4149
|
}
|
|
3054
4150
|
)
|
|
3055
|
-
] });
|
|
3056
|
-
}
|
|
3057
|
-
if (previewMode === "tab") {
|
|
3058
|
-
return /* @__PURE__ */ jsx(
|
|
3059
|
-
TabbedPreview,
|
|
3060
|
-
{
|
|
3061
|
-
editor: baseEditor(),
|
|
3062
|
-
preview: previewBody,
|
|
3063
|
-
scopePicker,
|
|
3064
|
-
i18n: { editor: i18n.editor, preview: i18n.preview }
|
|
3065
|
-
}
|
|
3066
4151
|
);
|
|
3067
4152
|
}
|
|
3068
|
-
return
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
4153
|
+
return withNav(
|
|
4154
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
|
|
4155
|
+
baseEditor(
|
|
4156
|
+
/* @__PURE__ */ jsx(PreviewToggleButton, { onClick: () => setDrawerOpen(true), label: i18n.openPreview })
|
|
4157
|
+
),
|
|
4158
|
+
/* @__PURE__ */ jsx(
|
|
4159
|
+
DrawerPreview,
|
|
4160
|
+
{
|
|
4161
|
+
open: drawerOpen,
|
|
4162
|
+
onClose: () => setDrawerOpen(false),
|
|
4163
|
+
label: i18n.preview,
|
|
4164
|
+
scopePicker,
|
|
4165
|
+
children: previewBody
|
|
4166
|
+
}
|
|
4167
|
+
)
|
|
4168
|
+
] })
|
|
4169
|
+
);
|
|
3083
4170
|
};
|
|
3084
4171
|
const isProductTab = activeScope === "product";
|
|
3085
4172
|
const productPinned = !!contextScope?.productId;
|
|
@@ -3125,6 +4212,7 @@ function RecordsAdminShell(props) {
|
|
|
3125
4212
|
}
|
|
3126
4213
|
});
|
|
3127
4214
|
};
|
|
4215
|
+
onLeftSelectRef.current = onLeftSelect;
|
|
3128
4216
|
return /* @__PURE__ */ jsxs(
|
|
3129
4217
|
"div",
|
|
3130
4218
|
{
|
|
@@ -3132,6 +4220,15 @@ function RecordsAdminShell(props) {
|
|
|
3132
4220
|
"data-density": density,
|
|
3133
4221
|
children: [
|
|
3134
4222
|
dirtyConfirm.dialog,
|
|
4223
|
+
pasteConfirm.dialog,
|
|
4224
|
+
clipboardNotice && /* @__PURE__ */ jsx(
|
|
4225
|
+
ClipboardToast,
|
|
4226
|
+
{
|
|
4227
|
+
message: clipboardNotice.message,
|
|
4228
|
+
variant: clipboardNotice.variant,
|
|
4229
|
+
onDismiss: () => setClipboardNotice(null)
|
|
4230
|
+
}
|
|
4231
|
+
),
|
|
3135
4232
|
/* @__PURE__ */ jsxs("div", { className: "px-4 pt-4 space-y-3", children: [
|
|
3136
4233
|
intro && !dismissed && /* @__PURE__ */ jsx(
|
|
3137
4234
|
IntroCard,
|
|
@@ -3145,9 +4242,9 @@ function RecordsAdminShell(props) {
|
|
|
3145
4242
|
}
|
|
3146
4243
|
),
|
|
3147
4244
|
(() => {
|
|
3148
|
-
|
|
3149
|
-
const
|
|
3150
|
-
|
|
4245
|
+
if (!headerWillRender) return null;
|
|
4246
|
+
const showHeaderReopen = !!intro && dismissed && resolvedReopenAffordance === "header";
|
|
4247
|
+
const reopenLabel = intro?.reopenLabel ?? `How ${label.toLowerCase()} works`;
|
|
3151
4248
|
return /* @__PURE__ */ jsx(
|
|
3152
4249
|
ShellHeader,
|
|
3153
4250
|
{
|
|
@@ -3165,18 +4262,32 @@ function RecordsAdminShell(props) {
|
|
|
3165
4262
|
},
|
|
3166
4263
|
statsItems,
|
|
3167
4264
|
statsTitle,
|
|
3168
|
-
statsIcon
|
|
4265
|
+
statsIcon,
|
|
4266
|
+
trailingSlot: showHeaderReopen ? /* @__PURE__ */ jsx(
|
|
4267
|
+
"button",
|
|
4268
|
+
{
|
|
4269
|
+
type: "button",
|
|
4270
|
+
onClick: undismiss,
|
|
4271
|
+
className: "ra-btn",
|
|
4272
|
+
"data-variant": "ghost",
|
|
4273
|
+
"aria-label": reopenLabel,
|
|
4274
|
+
title: reopenLabel,
|
|
4275
|
+
style: { width: "2rem", height: "2rem", padding: 0, justifyContent: "center" },
|
|
4276
|
+
children: /* @__PURE__ */ jsx(HelpCircle, { className: "w-4 h-4" })
|
|
4277
|
+
}
|
|
4278
|
+
) : void 0
|
|
3169
4279
|
}
|
|
3170
4280
|
);
|
|
3171
4281
|
})(),
|
|
3172
|
-
/* @__PURE__ */ jsx(
|
|
4282
|
+
resolvedReopenAffordance === "inline" || resolvedReopenAffordance === "footer" ? /* @__PURE__ */ jsx(
|
|
3173
4283
|
UtilityRow,
|
|
3174
4284
|
{
|
|
3175
|
-
label,
|
|
4285
|
+
label: intro?.reopenLabel ? "" : label,
|
|
4286
|
+
customLabel: intro?.reopenLabel,
|
|
3176
4287
|
introHidden: dismissed && !!intro,
|
|
3177
4288
|
onShowIntro: undismiss
|
|
3178
4289
|
}
|
|
3179
|
-
),
|
|
4290
|
+
) : null,
|
|
3180
4291
|
editorCtx.isDirty && /* @__PURE__ */ jsx(
|
|
3181
4292
|
UnsavedBanner,
|
|
3182
4293
|
{
|
|
@@ -3189,8 +4300,10 @@ function RecordsAdminShell(props) {
|
|
|
3189
4300
|
});
|
|
3190
4301
|
},
|
|
3191
4302
|
onDiscard: editorCtx.reset,
|
|
3192
|
-
saveLabel: i18n.save,
|
|
3193
|
-
discardLabel: i18n.discard,
|
|
4303
|
+
saveLabel: actionLabels?.save ?? i18n.save,
|
|
4304
|
+
discardLabel: actionLabels?.discard ?? i18n.discard,
|
|
4305
|
+
SaveIcon: actionIcons?.save,
|
|
4306
|
+
DiscardIcon: actionIcons?.discard,
|
|
3194
4307
|
savingLabel: i18n.saving,
|
|
3195
4308
|
errorLabel: i18n.saveError,
|
|
3196
4309
|
bodyTemplate: i18n.unsavedBannerBody
|
|
@@ -3203,7 +4316,18 @@ function RecordsAdminShell(props) {
|
|
|
3203
4316
|
className: "flex-1 grid border-t overflow-hidden",
|
|
3204
4317
|
style: { gridTemplateColumns: "minmax(260px, 320px) 1fr", borderColor: "hsl(var(--ra-border))", marginTop: "0.75rem" },
|
|
3205
4318
|
children: [
|
|
3206
|
-
/* @__PURE__ */
|
|
4319
|
+
/* @__PURE__ */ jsx("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: isCollection && selectedItemId && collectionRailMode === "siblings" ? /* @__PURE__ */ jsx(
|
|
4320
|
+
SiblingRail,
|
|
4321
|
+
{
|
|
4322
|
+
items: collectionItems.items,
|
|
4323
|
+
selectedItemId,
|
|
4324
|
+
isLoading: collectionItems.isLoading,
|
|
4325
|
+
error: collectionItems.error,
|
|
4326
|
+
onBack: onItemBack,
|
|
4327
|
+
onSelect: onItemOpen,
|
|
4328
|
+
i18n
|
|
4329
|
+
}
|
|
4330
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3207
4331
|
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
|
|
3208
4332
|
ScopeTabs,
|
|
3209
4333
|
{
|
|
@@ -3258,27 +4382,6 @@ function RecordsAdminShell(props) {
|
|
|
3258
4382
|
hideZero: ["partial"],
|
|
3259
4383
|
i18n
|
|
3260
4384
|
}
|
|
3261
|
-
),
|
|
3262
|
-
cardinality === "collection" && !isProductTab && editingScope && /* @__PURE__ */ jsxs(
|
|
3263
|
-
"button",
|
|
3264
|
-
{
|
|
3265
|
-
type: "button",
|
|
3266
|
-
onClick: () => {
|
|
3267
|
-
void runWithGuard(() => {
|
|
3268
|
-
const id = generateItemId ? generateItemId() : defaultItemId();
|
|
3269
|
-
const baseRef = editingScope.raw;
|
|
3270
|
-
const itemRef = baseRef ? `${baseRef}/item:${id}` : `item:${id}`;
|
|
3271
|
-
setSelectedFacetRef(itemRef);
|
|
3272
|
-
onTelemetry?.({ type: "item.create", recordType, scopeRef: baseRef });
|
|
3273
|
-
});
|
|
3274
|
-
},
|
|
3275
|
-
className: "w-full inline-flex items-center justify-center gap-1.5 text-xs py-1.5 rounded-md border transition-colors hover:bg-[hsl(var(--ra-muted))]",
|
|
3276
|
-
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
3277
|
-
children: [
|
|
3278
|
-
/* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
|
|
3279
|
-
i18n.newItem || `New ${itemNoun}`
|
|
3280
|
-
]
|
|
3281
|
-
}
|
|
3282
4385
|
)
|
|
3283
4386
|
] }),
|
|
3284
4387
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
@@ -3302,8 +4405,8 @@ function RecordsAdminShell(props) {
|
|
|
3302
4405
|
dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
|
|
3303
4406
|
presentation: effectivePresentation,
|
|
3304
4407
|
renderListRow,
|
|
3305
|
-
|
|
3306
|
-
|
|
4408
|
+
groupBy: effectiveGroupBy,
|
|
4409
|
+
rowClipboard
|
|
3307
4410
|
}
|
|
3308
4411
|
),
|
|
3309
4412
|
isProductTab && !productPinned && productBrowse.hasNextPage && /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
|
|
@@ -3321,16 +4424,35 @@ function RecordsAdminShell(props) {
|
|
|
3321
4424
|
) })
|
|
3322
4425
|
] })
|
|
3323
4426
|
] })
|
|
3324
|
-
] }),
|
|
4427
|
+
] }) }),
|
|
3325
4428
|
/* @__PURE__ */ jsxs("main", { className: "overflow-hidden", children: [
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
4429
|
+
isCollection && editingScope && !selectedItemId && /* @__PURE__ */ jsx(
|
|
4430
|
+
ItemListView,
|
|
4431
|
+
{
|
|
4432
|
+
items: collectionItems.items,
|
|
4433
|
+
isLoading: collectionItems.isLoading,
|
|
4434
|
+
error: collectionItems.error,
|
|
4435
|
+
ctx: itemViewCtx,
|
|
4436
|
+
itemNoun: itemNounLabel,
|
|
4437
|
+
view: itemView,
|
|
4438
|
+
views: itemViews,
|
|
4439
|
+
onViewChange: onItemViewChange,
|
|
4440
|
+
renderItemList,
|
|
4441
|
+
renderItemCard,
|
|
4442
|
+
renderItemEmpty,
|
|
4443
|
+
itemColumns,
|
|
4444
|
+
i18n
|
|
4445
|
+
}
|
|
4446
|
+
),
|
|
4447
|
+
!isCollection && !editingScope && activeScope === "product" && !selectedProductId && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
|
|
4448
|
+
!isCollection && !editingScope && activeScope === "facet" && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
|
|
4449
|
+
isProductTab && selectedProductId && (!isCollection || selectedItemId) && /* @__PURE__ */ jsx(
|
|
3329
4450
|
ProductDrillDown,
|
|
3330
4451
|
{
|
|
3331
4452
|
productLabel: productBrowse.items.find((p) => p.id === selectedProductId)?.name ?? selectedProductId,
|
|
3332
4453
|
showVariants: drillVariantsAllowed,
|
|
3333
4454
|
showBatches: drillBatchesAllowed,
|
|
4455
|
+
hideSingleTab: editorTabs === "off" || editorTabs === "multi",
|
|
3334
4456
|
active: drillTab,
|
|
3335
4457
|
onChange: (t) => {
|
|
3336
4458
|
void runWithGuard(() => {
|
|
@@ -3352,7 +4474,7 @@ function RecordsAdminShell(props) {
|
|
|
3352
4474
|
batches: batchChildren.items,
|
|
3353
4475
|
variantsLoading: variantChildren.isLoading,
|
|
3354
4476
|
batchesLoading: batchChildren.isLoading,
|
|
3355
|
-
children:
|
|
4477
|
+
children: editingTargetScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
|
|
3356
4478
|
EmptyState,
|
|
3357
4479
|
{
|
|
3358
4480
|
title: drillTab === "variant" ? "Pick a variant" : "Pick a batch",
|
|
@@ -3361,7 +4483,7 @@ function RecordsAdminShell(props) {
|
|
|
3361
4483
|
)
|
|
3362
4484
|
}
|
|
3363
4485
|
),
|
|
3364
|
-
!isProductTab &&
|
|
4486
|
+
!isProductTab && editingTargetScope && (!isCollection || selectedItemId) && renderEditorWithPreview()
|
|
3365
4487
|
] })
|
|
3366
4488
|
]
|
|
3367
4489
|
}
|
|
@@ -3433,6 +4555,87 @@ var RecordBrowser = ({
|
|
|
3433
4555
|
] })
|
|
3434
4556
|
] });
|
|
3435
4557
|
};
|
|
4558
|
+
var initials2 = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
|
|
4559
|
+
var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
|
|
4560
|
+
const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
|
|
4561
|
+
const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
|
|
4562
|
+
return /* @__PURE__ */ jsxs(
|
|
4563
|
+
"button",
|
|
4564
|
+
{
|
|
4565
|
+
type: "button",
|
|
4566
|
+
onClick: onSelect,
|
|
4567
|
+
className: cn(
|
|
4568
|
+
"group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
|
|
4569
|
+
selected && "ring-2"
|
|
4570
|
+
),
|
|
4571
|
+
style: {
|
|
4572
|
+
background: "hsl(var(--ra-surface))",
|
|
4573
|
+
borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
|
|
4574
|
+
boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
|
|
4575
|
+
},
|
|
4576
|
+
children: [
|
|
4577
|
+
/* @__PURE__ */ jsxs(
|
|
4578
|
+
"div",
|
|
4579
|
+
{
|
|
4580
|
+
className: cn(aspect, "relative w-full flex items-center justify-center overflow-hidden"),
|
|
4581
|
+
style: { background: "hsl(var(--ra-muted))" },
|
|
4582
|
+
children: [
|
|
4583
|
+
record.thumbnail ? /* @__PURE__ */ jsx(
|
|
4584
|
+
"img",
|
|
4585
|
+
{
|
|
4586
|
+
src: record.thumbnail,
|
|
4587
|
+
alt: "",
|
|
4588
|
+
loading: "lazy",
|
|
4589
|
+
className: "w-full h-full object-cover"
|
|
4590
|
+
}
|
|
4591
|
+
) : /* @__PURE__ */ jsx(
|
|
4592
|
+
"span",
|
|
4593
|
+
{
|
|
4594
|
+
className: "text-2xl ra-display",
|
|
4595
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
4596
|
+
children: initials2(record.label)
|
|
4597
|
+
}
|
|
4598
|
+
),
|
|
4599
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
|
|
4600
|
+
isDirty && /* @__PURE__ */ jsx(
|
|
4601
|
+
"span",
|
|
4602
|
+
{
|
|
4603
|
+
title: "Unsaved changes",
|
|
4604
|
+
"aria-label": "Unsaved changes",
|
|
4605
|
+
className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
|
|
4606
|
+
}
|
|
4607
|
+
)
|
|
4608
|
+
]
|
|
4609
|
+
}
|
|
4610
|
+
),
|
|
4611
|
+
/* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
|
|
4612
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
|
|
4613
|
+
/* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
|
|
4614
|
+
(onCopy || onPaste) && /* @__PURE__ */ jsx(
|
|
4615
|
+
RowContextMenu,
|
|
4616
|
+
{
|
|
4617
|
+
onCopy,
|
|
4618
|
+
onPaste,
|
|
4619
|
+
canPaste,
|
|
4620
|
+
pasteWillReplace,
|
|
4621
|
+
pasteSourceLabel: clipboardSourceLabel,
|
|
4622
|
+
i18n: {
|
|
4623
|
+
copy: DEFAULT_I18N.copy,
|
|
4624
|
+
paste: DEFAULT_I18N.paste,
|
|
4625
|
+
pasteFrom: DEFAULT_I18N.pasteFrom,
|
|
4626
|
+
pasteReplace: DEFAULT_I18N.pasteReplace,
|
|
4627
|
+
clipboardEmpty: DEFAULT_I18N.clipboardEmpty
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
)
|
|
4631
|
+
] }),
|
|
4632
|
+
variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
|
|
4633
|
+
record.badges && record.badges.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-1 mt-1.5 flex-wrap", children: record.badges.slice(0, 3).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)) })
|
|
4634
|
+
] })
|
|
4635
|
+
]
|
|
4636
|
+
}
|
|
4637
|
+
);
|
|
4638
|
+
};
|
|
3436
4639
|
var Ctx = createContext({});
|
|
3437
4640
|
var InheritanceProvider = ({
|
|
3438
4641
|
parentValue,
|
|
@@ -3763,6 +4966,6 @@ function useMergedRecord(args) {
|
|
|
3763
4966
|
};
|
|
3764
4967
|
}
|
|
3765
4968
|
|
|
3766
|
-
export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_I18N, DEFAULT_ICONS, DefaultRecordCard, DefaultRecordRow, DeleteButton, DrawerPreview, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SidePreview, StatusDot, StatusFilterPills, TabbedPreview, UtilityRow, VariantList, buildRef,
|
|
4969
|
+
export { ALL_ITEM_VIEWS, ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_DEEP_LINK_PARAM_NAMES, DEFAULT_I18N, DEFAULT_ICONS, DefaultItemCards, DefaultItemTable, DefaultRecordCard, DefaultRecordRow, DeleteButton, 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, TabbedPreview, UtilityRow, VariantList, buildItemRef, buildRef, checkPasteCompatibility, cloneValue, createDefaultDeepLinkAdapter, downloadBlob, exportCsv, importCsv, mergeIcons, parseRef, pickHeaderIcon, resolutionChain, resolveRecord, splitItemRef, useCollectedRecords, useCollectionItems, useDeepLinkState, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useItemViewPref, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
|
|
3767
4970
|
//# sourceMappingURL=index.js.map
|
|
3768
4971
|
//# sourceMappingURL=index.js.map
|