@proveanything/smartlinks-utils-ui 0.3.9 → 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 +474 -48
- package/dist/components/RecordsAdmin/index.js +1098 -415
- 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-IGFYMNKL.js +0 -28
- package/dist/chunk-IGFYMNKL.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,12 +95,22 @@ 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
115
|
railEmptyBody: "Records you create will appear here.",
|
|
97
116
|
copy: "Copy",
|
|
@@ -110,7 +129,15 @@ var DEFAULT_I18N = {
|
|
|
110
129
|
};
|
|
111
130
|
|
|
112
131
|
// src/components/RecordsAdmin/types/presentation.ts
|
|
113
|
-
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
|
+
};
|
|
114
141
|
|
|
115
142
|
// src/components/RecordsAdmin/data/refs.ts
|
|
116
143
|
var KIND_KEYS = {
|
|
@@ -139,6 +166,9 @@ var parseRef = (raw) => {
|
|
|
139
166
|
} else {
|
|
140
167
|
parsed.facetId = id;
|
|
141
168
|
}
|
|
169
|
+
} else if (k === "item") {
|
|
170
|
+
parsed.itemId = id;
|
|
171
|
+
continue;
|
|
142
172
|
} else if (k in KIND_KEYS) {
|
|
143
173
|
parsed[KIND_KEYS[k]] = id;
|
|
144
174
|
}
|
|
@@ -156,6 +186,7 @@ var buildRef = (a) => {
|
|
|
156
186
|
if (a.variantId) parts.push(`variant:${a.variantId}`);
|
|
157
187
|
if (a.batchId) parts.push(`batch:${a.batchId}`);
|
|
158
188
|
if (a.proofId) parts.push(`proof:${a.proofId}`);
|
|
189
|
+
if (a.itemId) parts.push(`item:${a.itemId}`);
|
|
159
190
|
return parts.join("/");
|
|
160
191
|
};
|
|
161
192
|
var resolutionChain = (target, supportedScopes) => {
|
|
@@ -172,173 +203,23 @@ var resolutionChain = (target, supportedScopes) => {
|
|
|
172
203
|
if (supportedScopes.includes("facet") && target.facetId) {
|
|
173
204
|
chain.push(buildRef({ facetId: target.facetId, facetValue: target.facetValue }));
|
|
174
205
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// src/components/RecordsAdmin/data/scopeBridge.ts
|
|
179
|
-
var parsedRefToScope = (ref) => {
|
|
180
|
-
const scope = {};
|
|
181
|
-
if (ref.productId) scope.productId = ref.productId;
|
|
182
|
-
if (ref.variantId) scope.variantId = ref.variantId;
|
|
183
|
-
if (ref.batchId) scope.batchId = ref.batchId;
|
|
184
|
-
if (ref.proofId) scope.proofId = ref.proofId;
|
|
185
|
-
if (ref.facetId) {
|
|
186
|
-
scope.facets = [{
|
|
187
|
-
key: ref.facetId,
|
|
188
|
-
valueKeys: ref.facetValue ? [ref.facetValue] : []
|
|
189
|
-
}];
|
|
190
|
-
}
|
|
191
|
-
return scope;
|
|
192
|
-
};
|
|
193
|
-
var parsedRefToTarget = (ref) => {
|
|
194
|
-
const target = {};
|
|
195
|
-
if (ref.productId) target.productId = ref.productId;
|
|
196
|
-
if (ref.variantId) target.variantId = ref.variantId;
|
|
197
|
-
if (ref.batchId) target.batchId = ref.batchId;
|
|
198
|
-
if (ref.proofId) target.proofId = ref.proofId;
|
|
199
|
-
if (ref.facetId && ref.facetValue) {
|
|
200
|
-
target.facets = { [ref.facetId]: [ref.facetValue] };
|
|
201
|
-
}
|
|
202
|
-
return target;
|
|
203
|
-
};
|
|
204
|
-
var scopesEqual = (a, b) => {
|
|
205
|
-
if ((a.productId ?? null) !== (b.productId ?? null)) return false;
|
|
206
|
-
if ((a.variantId ?? null) !== (b.variantId ?? null)) return false;
|
|
207
|
-
if ((a.batchId ?? null) !== (b.batchId ?? null)) return false;
|
|
208
|
-
if ((a.proofId ?? null) !== (b.proofId ?? null)) return false;
|
|
209
|
-
const af = a.facets ?? [];
|
|
210
|
-
const bf = b.facets ?? [];
|
|
211
|
-
if (af.length !== bf.length) return false;
|
|
212
|
-
const norm = (xs) => xs.map((f) => `${f.key}:${[...f.valueKeys].sort().join(",")}`).sort().join("|");
|
|
213
|
-
return norm(af) === norm(bf);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
// src/components/RecordsAdmin/data/records.ts
|
|
217
|
-
var listRecords = async (ctx, params = {}) => {
|
|
218
|
-
const { limit = 100, offset, ref, refPrefix, q, sort } = params;
|
|
219
|
-
const res = await ctx.SL.app.records.list(
|
|
220
|
-
ctx.collectionId,
|
|
221
|
-
ctx.appId,
|
|
222
|
-
{
|
|
223
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
224
|
-
limit,
|
|
225
|
-
offset,
|
|
226
|
-
ref,
|
|
227
|
-
refPrefix,
|
|
228
|
-
q,
|
|
229
|
-
sort
|
|
230
|
-
},
|
|
231
|
-
true
|
|
232
|
-
);
|
|
233
|
-
return {
|
|
234
|
-
data: res?.data ?? [],
|
|
235
|
-
total: res?.pagination?.total ?? (res?.data?.length ?? 0),
|
|
236
|
-
hasMore: res?.pagination?.hasMore ?? false
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
var getRecordByRef = async (ctx, ref) => {
|
|
240
|
-
const res = await ctx.SL.app.records.list(
|
|
241
|
-
ctx.collectionId,
|
|
242
|
-
ctx.appId,
|
|
243
|
-
{ ...ctx.recordType ? { recordType: ctx.recordType } : {}, ref, limit: 1 },
|
|
244
|
-
true
|
|
245
|
-
);
|
|
246
|
-
return res?.data?.[0] ?? null;
|
|
247
|
-
};
|
|
248
|
-
var upsertRecord = async (ctx, write) => {
|
|
249
|
-
const ref = write.ref ?? deriveRefFromScope(write.scope);
|
|
250
|
-
const res = await ctx.SL.app.records.upsert(ctx.collectionId, ctx.appId, {
|
|
251
|
-
ref,
|
|
252
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
253
|
-
scope: write.scope,
|
|
254
|
-
data: write.data,
|
|
255
|
-
status: write.status,
|
|
256
|
-
startsAt: write.startsAt,
|
|
257
|
-
expiresAt: write.expiresAt,
|
|
258
|
-
customId: write.customId,
|
|
259
|
-
sourceSystem: write.sourceSystem
|
|
260
|
-
});
|
|
261
|
-
return { record: res, isCreate: !!res?.created };
|
|
262
|
-
};
|
|
263
|
-
var deleteRecord = async (ctx, ref) => {
|
|
264
|
-
const existing = await getRecordByRef(ctx, ref).catch(() => null);
|
|
265
|
-
if (!existing) return false;
|
|
266
|
-
await ctx.SL.app.records.remove(ctx.collectionId, ctx.appId, existing.id, true);
|
|
267
|
-
return true;
|
|
268
|
-
};
|
|
269
|
-
var restoreRecord = async (ctx, recordId) => ctx.SL.app.records.restore(ctx.collectionId, ctx.appId, recordId);
|
|
270
|
-
var matchRecords = async (ctx, target, opts = {}) => ctx.SL.app.records.match(
|
|
271
|
-
ctx.collectionId,
|
|
272
|
-
ctx.appId,
|
|
273
|
-
{
|
|
274
|
-
target,
|
|
275
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
276
|
-
strategy: opts.strategy ?? "all",
|
|
277
|
-
at: opts.at,
|
|
278
|
-
includeScheduled: opts.includeScheduled,
|
|
279
|
-
includeExpired: opts.includeExpired,
|
|
280
|
-
limit: opts.limit
|
|
281
|
-
},
|
|
282
|
-
true
|
|
283
|
-
);
|
|
284
|
-
var bulkUpsert = async (ctx, entries) => {
|
|
285
|
-
const CHUNK = 500;
|
|
286
|
-
let saved = 0;
|
|
287
|
-
let failed = 0;
|
|
288
|
-
for (let i = 0; i < entries.length; i += CHUNK) {
|
|
289
|
-
const slice = entries.slice(i, i + CHUNK);
|
|
290
|
-
const items = slice.map((e) => ({
|
|
291
|
-
ref: e.ref ?? deriveRefFromScope(e.scope),
|
|
292
|
-
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
293
|
-
scope: e.scope,
|
|
294
|
-
data: e.data,
|
|
295
|
-
status: e.status
|
|
296
|
-
}));
|
|
297
|
-
const res = await ctx.SL.app.records.bulkUpsert(ctx.collectionId, ctx.appId, items).catch(() => ({ saved: 0, failed: items.length }));
|
|
298
|
-
saved += res.saved ?? 0;
|
|
299
|
-
failed += res.failed ?? 0;
|
|
206
|
+
if (supportedScopes.includes("collection")) {
|
|
207
|
+
chain.push("");
|
|
300
208
|
}
|
|
301
|
-
return
|
|
209
|
+
return Array.from(new Set(chain));
|
|
302
210
|
};
|
|
303
|
-
var
|
|
304
|
-
if ("
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
);
|
|
310
|
-
return { removed: res.deleted ?? 0 };
|
|
311
|
-
}
|
|
312
|
-
const CHUNK = 1e3;
|
|
313
|
-
let removed = 0;
|
|
314
|
-
for (let i = 0; i < input.refs.length; i += CHUNK) {
|
|
315
|
-
const slice = input.refs.slice(i, i + CHUNK);
|
|
316
|
-
const res = await ctx.SL.app.records.bulkDelete(
|
|
317
|
-
ctx.collectionId,
|
|
318
|
-
ctx.appId,
|
|
319
|
-
{ refs: slice, ...ctx.recordType ? { recordType: ctx.recordType } : {} }
|
|
320
|
-
);
|
|
321
|
-
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) };
|
|
322
217
|
}
|
|
323
|
-
return {
|
|
218
|
+
return { scopeRef: raw };
|
|
324
219
|
};
|
|
325
|
-
var
|
|
326
|
-
|
|
327
|
-
if (scope.facets && scope.facets.length > 0) {
|
|
328
|
-
const sorted = [...scope.facets].sort((a, b) => a.key.localeCompare(b.key));
|
|
329
|
-
for (const f of sorted) {
|
|
330
|
-
const vals = [...f.valueKeys].sort().join(",");
|
|
331
|
-
parts.push(vals ? `facet:${f.key}=${vals}` : `facet:${f.key}`);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
if (scope.productId) parts.push(`product:${scope.productId}`);
|
|
335
|
-
if (scope.variantId) parts.push(`variant:${scope.variantId}`);
|
|
336
|
-
if (scope.batchId) parts.push(`batch:${scope.batchId}`);
|
|
337
|
-
if (scope.proofId) parts.push(`proof:${scope.proofId}`);
|
|
338
|
-
return parts.join("/");
|
|
220
|
+
var buildItemRef = (scopeRef, itemId) => {
|
|
221
|
+
return scopeRef ? `${scopeRef}/item:${itemId}` : `item:${itemId}`;
|
|
339
222
|
};
|
|
340
|
-
|
|
341
|
-
// src/components/RecordsAdmin/hooks/useRecordList.ts
|
|
342
223
|
var defaultClassify = (r) => {
|
|
343
224
|
if (!r.data) return "empty";
|
|
344
225
|
const keys = Object.keys(r.data);
|
|
@@ -379,7 +260,7 @@ var useRecordList = (args) => {
|
|
|
379
260
|
scopeKind,
|
|
380
261
|
search = "",
|
|
381
262
|
filter = "all",
|
|
382
|
-
classify,
|
|
263
|
+
classify: classify2,
|
|
383
264
|
enabled = true,
|
|
384
265
|
scaffolder,
|
|
385
266
|
contextScope,
|
|
@@ -414,9 +295,9 @@ var useRecordList = (args) => {
|
|
|
414
295
|
const [scaffolded, setScaffolded] = useState(null);
|
|
415
296
|
const rawItems = useMemo(() => {
|
|
416
297
|
const all = query.data?.pages.flatMap((p) => p.data) ?? [];
|
|
417
|
-
const cls =
|
|
298
|
+
const cls = classify2 ?? defaultClassify;
|
|
418
299
|
return all.map(toSummary).filter((s) => matchesScope(scopeKind, s.scope)).filter((s) => matchesContext(s.scope, contextScope)).map((s) => ({ ...s, status: cls(s) }));
|
|
419
|
-
}, [query.data, scopeKind,
|
|
300
|
+
}, [query.data, scopeKind, classify2, contextScope]);
|
|
420
301
|
useEffect(() => {
|
|
421
302
|
if (!scaffolder) {
|
|
422
303
|
setScaffolded(null);
|
|
@@ -1383,6 +1264,7 @@ function cloneValue(value) {
|
|
|
1383
1264
|
}
|
|
1384
1265
|
}
|
|
1385
1266
|
var LABELS = {
|
|
1267
|
+
collection: "Global",
|
|
1386
1268
|
product: "Products",
|
|
1387
1269
|
facet: "Shared",
|
|
1388
1270
|
variant: "Variants",
|
|
@@ -1591,87 +1473,6 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
1591
1473
|
}
|
|
1592
1474
|
);
|
|
1593
1475
|
};
|
|
1594
|
-
var initials = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
|
|
1595
|
-
var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
|
|
1596
|
-
const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
|
|
1597
|
-
const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
|
|
1598
|
-
return /* @__PURE__ */ jsxs(
|
|
1599
|
-
"button",
|
|
1600
|
-
{
|
|
1601
|
-
type: "button",
|
|
1602
|
-
onClick: onSelect,
|
|
1603
|
-
className: cn(
|
|
1604
|
-
"group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
|
|
1605
|
-
selected && "ring-2"
|
|
1606
|
-
),
|
|
1607
|
-
style: {
|
|
1608
|
-
background: "hsl(var(--ra-surface))",
|
|
1609
|
-
borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
|
|
1610
|
-
boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
|
|
1611
|
-
},
|
|
1612
|
-
children: [
|
|
1613
|
-
/* @__PURE__ */ jsxs(
|
|
1614
|
-
"div",
|
|
1615
|
-
{
|
|
1616
|
-
className: cn(aspect, "relative w-full flex items-center justify-center overflow-hidden"),
|
|
1617
|
-
style: { background: "hsl(var(--ra-muted))" },
|
|
1618
|
-
children: [
|
|
1619
|
-
record.thumbnail ? /* @__PURE__ */ jsx(
|
|
1620
|
-
"img",
|
|
1621
|
-
{
|
|
1622
|
-
src: record.thumbnail,
|
|
1623
|
-
alt: "",
|
|
1624
|
-
loading: "lazy",
|
|
1625
|
-
className: "w-full h-full object-cover"
|
|
1626
|
-
}
|
|
1627
|
-
) : /* @__PURE__ */ jsx(
|
|
1628
|
-
"span",
|
|
1629
|
-
{
|
|
1630
|
-
className: "text-2xl ra-display",
|
|
1631
|
-
style: { color: "hsl(var(--ra-muted-text))" },
|
|
1632
|
-
children: initials(record.label)
|
|
1633
|
-
}
|
|
1634
|
-
),
|
|
1635
|
-
/* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
|
|
1636
|
-
isDirty && /* @__PURE__ */ jsx(
|
|
1637
|
-
"span",
|
|
1638
|
-
{
|
|
1639
|
-
title: "Unsaved changes",
|
|
1640
|
-
"aria-label": "Unsaved changes",
|
|
1641
|
-
className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
|
|
1642
|
-
}
|
|
1643
|
-
)
|
|
1644
|
-
]
|
|
1645
|
-
}
|
|
1646
|
-
),
|
|
1647
|
-
/* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
|
|
1648
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
|
|
1649
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
|
|
1650
|
-
(onCopy || onPaste) && /* @__PURE__ */ jsx(
|
|
1651
|
-
RowContextMenu,
|
|
1652
|
-
{
|
|
1653
|
-
onCopy,
|
|
1654
|
-
onPaste,
|
|
1655
|
-
canPaste,
|
|
1656
|
-
pasteWillReplace,
|
|
1657
|
-
pasteSourceLabel: clipboardSourceLabel,
|
|
1658
|
-
i18n: {
|
|
1659
|
-
copy: DEFAULT_I18N.copy,
|
|
1660
|
-
paste: DEFAULT_I18N.paste,
|
|
1661
|
-
pasteFrom: DEFAULT_I18N.pasteFrom,
|
|
1662
|
-
pasteReplace: DEFAULT_I18N.pasteReplace,
|
|
1663
|
-
clipboardEmpty: DEFAULT_I18N.clipboardEmpty
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
)
|
|
1667
|
-
] }),
|
|
1668
|
-
variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
|
|
1669
|
-
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}`)) })
|
|
1670
|
-
] })
|
|
1671
|
-
]
|
|
1672
|
-
}
|
|
1673
|
-
);
|
|
1674
|
-
};
|
|
1675
1476
|
var RecordList = ({
|
|
1676
1477
|
items,
|
|
1677
1478
|
selectedRef,
|
|
@@ -1679,7 +1480,6 @@ var RecordList = ({
|
|
|
1679
1480
|
dirtyRef,
|
|
1680
1481
|
presentation = "list",
|
|
1681
1482
|
renderListRow,
|
|
1682
|
-
renderCard,
|
|
1683
1483
|
groupBy,
|
|
1684
1484
|
rowClipboard
|
|
1685
1485
|
}) => {
|
|
@@ -1707,20 +1507,6 @@ var RecordList = ({
|
|
|
1707
1507
|
return orderedKeys.map((k) => buckets.get(k));
|
|
1708
1508
|
}, [items, groupBy]);
|
|
1709
1509
|
const renderItems = (rows) => {
|
|
1710
|
-
if (presentation === "grid" || presentation === "gallery") {
|
|
1711
|
-
const minColPx = presentation === "gallery" ? 200 : 120;
|
|
1712
|
-
return /* @__PURE__ */ jsx(
|
|
1713
|
-
"div",
|
|
1714
|
-
{
|
|
1715
|
-
className: "grid gap-2 p-2",
|
|
1716
|
-
style: { gridTemplateColumns: `repeat(auto-fill, minmax(${minColPx}px, 1fr))` },
|
|
1717
|
-
children: rows.map((item) => {
|
|
1718
|
-
const ctx = buildCtx(item);
|
|
1719
|
-
return /* @__PURE__ */ jsx("div", { children: renderCard ? renderCard(item, ctx) : /* @__PURE__ */ jsx(DefaultRecordCard, { record: item, ctx, variant: presentation }) }, item.ref);
|
|
1720
|
-
})
|
|
1721
|
-
}
|
|
1722
|
-
);
|
|
1723
|
-
}
|
|
1724
1510
|
const compact = presentation === "compact";
|
|
1725
1511
|
return /* @__PURE__ */ jsx("ul", { children: rows.map((item) => {
|
|
1726
1512
|
const ctx = buildCtx(item);
|
|
@@ -1803,18 +1589,12 @@ var ErrorState = ({ error }) => /* @__PURE__ */ jsxs("div", { className: "ra-emp
|
|
|
1803
1589
|
] });
|
|
1804
1590
|
var ICONS = {
|
|
1805
1591
|
list: List,
|
|
1806
|
-
grid: LayoutGrid,
|
|
1807
|
-
gallery: Image,
|
|
1808
1592
|
compact: Rows3
|
|
1809
1593
|
};
|
|
1810
1594
|
var labelFor = (p, i18n) => {
|
|
1811
1595
|
switch (p) {
|
|
1812
1596
|
case "list":
|
|
1813
1597
|
return i18n.presentationList;
|
|
1814
|
-
case "grid":
|
|
1815
|
-
return i18n.presentationGrid;
|
|
1816
|
-
case "gallery":
|
|
1817
|
-
return i18n.presentationGallery;
|
|
1818
1598
|
case "compact":
|
|
1819
1599
|
return i18n.presentationCompact;
|
|
1820
1600
|
}
|
|
@@ -1853,6 +1633,7 @@ var PresentationSwitcher = ({ options, value, onChange, i18n }) => {
|
|
|
1853
1633
|
);
|
|
1854
1634
|
};
|
|
1855
1635
|
var KEY_PREFIX = "smartlinks-ui:records-admin:presentation";
|
|
1636
|
+
var ITEM_VIEW_KEY_PREFIX = "smartlinks-ui:records-admin:item-view";
|
|
1856
1637
|
var safeRead = (key) => {
|
|
1857
1638
|
try {
|
|
1858
1639
|
return typeof window === "undefined" ? null : window.localStorage.getItem(key);
|
|
@@ -1884,6 +1665,195 @@ function usePresentationPref(args) {
|
|
|
1884
1665
|
}, [key]);
|
|
1885
1666
|
return [value, set];
|
|
1886
1667
|
}
|
|
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);
|
|
1677
|
+
useEffect(() => {
|
|
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
|
+
}
|
|
1887
1857
|
var segmentsFor = (s) => {
|
|
1888
1858
|
const out = [];
|
|
1889
1859
|
if (s.facetId) out.push({ label: s.facetValue ? `${s.facetId}: ${s.facetValue}` : `Facet: ${s.facetId}`, key: "facet" });
|
|
@@ -2673,55 +2643,442 @@ var PreviewScopePicker = ({
|
|
|
2673
2643
|
)
|
|
2674
2644
|
] });
|
|
2675
2645
|
};
|
|
2676
|
-
var
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2646
|
+
var ICONS2 = {
|
|
2647
|
+
table: Table,
|
|
2648
|
+
cards: LayoutGrid,
|
|
2649
|
+
gallery: Image
|
|
2680
2650
|
};
|
|
2681
|
-
var
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
/* @__PURE__ */ jsx(
|
|
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(
|
|
2693
2662
|
"button",
|
|
2694
2663
|
{
|
|
2695
2664
|
type: "button",
|
|
2696
|
-
|
|
2697
|
-
"aria-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
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
|
+
}) });
|
|
2703
2679
|
};
|
|
2704
|
-
var
|
|
2705
|
-
if (!
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
{
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
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",
|
|
2713
2707
|
{
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
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
|
+
}
|
|
3034
|
+
var TONE_ICON = {
|
|
3035
|
+
info: Lightbulb,
|
|
3036
|
+
success: CheckCircle2,
|
|
3037
|
+
warning: AlertTriangle
|
|
3038
|
+
};
|
|
3039
|
+
var IntroCard = ({ title, body, onDismiss, tone = "info", action }) => {
|
|
3040
|
+
const Icon = TONE_ICON[tone] ?? Info;
|
|
3041
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-intro", "data-tone": tone, role: "note", children: [
|
|
3042
|
+
/* @__PURE__ */ jsx("div", { className: "ra-intro-icon", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
|
|
3043
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-intro-body", children: [
|
|
3044
|
+
/* @__PURE__ */ jsx("h4", { className: "ra-intro-title", children: title }),
|
|
3045
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-intro-text", children: [
|
|
3046
|
+
body,
|
|
3047
|
+
action && /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: action })
|
|
3048
|
+
] })
|
|
3049
|
+
] }),
|
|
3050
|
+
/* @__PURE__ */ jsx(
|
|
3051
|
+
"button",
|
|
3052
|
+
{
|
|
3053
|
+
type: "button",
|
|
3054
|
+
onClick: onDismiss,
|
|
3055
|
+
"aria-label": "Dismiss",
|
|
3056
|
+
className: "ra-intro-dismiss",
|
|
3057
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
|
|
3058
|
+
}
|
|
3059
|
+
)
|
|
3060
|
+
] });
|
|
3061
|
+
};
|
|
3062
|
+
var UtilityRow = ({ label, customLabel, introHidden, onShowIntro }) => {
|
|
3063
|
+
if (!introHidden || !onShowIntro) return null;
|
|
3064
|
+
const text = customLabel ?? `How ${label.toLowerCase()} works`;
|
|
3065
|
+
return /* @__PURE__ */ jsx(
|
|
3066
|
+
"div",
|
|
3067
|
+
{
|
|
3068
|
+
className: "flex items-center justify-end gap-2 text-xs",
|
|
3069
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
3070
|
+
children: /* @__PURE__ */ jsxs(
|
|
3071
|
+
"button",
|
|
3072
|
+
{
|
|
3073
|
+
type: "button",
|
|
3074
|
+
onClick: onShowIntro,
|
|
3075
|
+
className: "ra-btn",
|
|
3076
|
+
"data-variant": "ghost",
|
|
3077
|
+
style: { padding: "0.25rem 0.55rem", fontSize: "0.7rem" },
|
|
3078
|
+
children: [
|
|
3079
|
+
/* @__PURE__ */ jsx(HelpCircle, { className: "w-3 h-3" }),
|
|
3080
|
+
text
|
|
3081
|
+
]
|
|
2725
3082
|
}
|
|
2726
3083
|
)
|
|
2727
3084
|
}
|
|
@@ -2739,7 +3096,8 @@ function ShellHeader({
|
|
|
2739
3096
|
stats,
|
|
2740
3097
|
statsItems,
|
|
2741
3098
|
statsTitle,
|
|
2742
|
-
statsIcon
|
|
3099
|
+
statsIcon,
|
|
3100
|
+
trailingSlot
|
|
2743
3101
|
}) {
|
|
2744
3102
|
let iconNode = null;
|
|
2745
3103
|
if (showHeaderIcon) {
|
|
@@ -2794,7 +3152,10 @@ function ShellHeader({
|
|
|
2794
3152
|
]
|
|
2795
3153
|
}
|
|
2796
3154
|
) : null,
|
|
2797
|
-
headerActions ? /* @__PURE__ */
|
|
3155
|
+
headerActions || trailingSlot ? /* @__PURE__ */ jsxs("div", { className: "ra-header-actions", children: [
|
|
3156
|
+
headerActions,
|
|
3157
|
+
trailingSlot
|
|
3158
|
+
] }) : null
|
|
2798
3159
|
] })
|
|
2799
3160
|
] });
|
|
2800
3161
|
}
|
|
@@ -2985,7 +3346,7 @@ var downloadBlob = (blob, filename) => {
|
|
|
2985
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');
|
|
2986
3347
|
|
|
2987
3348
|
// src/components/RecordsAdmin/shell/shell.css
|
|
2988
|
-
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");
|
|
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");
|
|
2989
3350
|
var TOP_LEVEL_SCOPES = ["facet", "product"];
|
|
2990
3351
|
var defaultItemId = () => {
|
|
2991
3352
|
const time = Date.now().toString(36);
|
|
@@ -3018,7 +3379,7 @@ function RecordsAdminShell(props) {
|
|
|
3018
3379
|
renderPreview,
|
|
3019
3380
|
intro,
|
|
3020
3381
|
csvSchema,
|
|
3021
|
-
classify,
|
|
3382
|
+
classify: classify2,
|
|
3022
3383
|
defaultData,
|
|
3023
3384
|
i18n: i18nOverride,
|
|
3024
3385
|
onTelemetry,
|
|
@@ -3034,7 +3395,6 @@ function RecordsAdminShell(props) {
|
|
|
3034
3395
|
disableBeforeUnload = false,
|
|
3035
3396
|
presentations = ["list"],
|
|
3036
3397
|
defaultPresentation,
|
|
3037
|
-
renderCard,
|
|
3038
3398
|
renderListRow,
|
|
3039
3399
|
renderEmpty,
|
|
3040
3400
|
cardinality = "singleton",
|
|
@@ -3059,10 +3419,22 @@ function RecordsAdminShell(props) {
|
|
|
3059
3419
|
onPaste: onPasteOverride,
|
|
3060
3420
|
actionLabels,
|
|
3061
3421
|
actionIcons,
|
|
3062
|
-
editorTabs = "off"
|
|
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
|
|
3063
3433
|
} = props;
|
|
3064
3434
|
const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
|
|
3065
3435
|
const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
|
|
3436
|
+
const deepLinkState = useDeepLinkState(deepLink);
|
|
3437
|
+
const lastAppliedDLRef = useRef("");
|
|
3066
3438
|
const multiOpenWarnedRef = useRef(false);
|
|
3067
3439
|
if (editorTabs === "multi" && !multiOpenWarnedRef.current) {
|
|
3068
3440
|
multiOpenWarnedRef.current = true;
|
|
@@ -3080,6 +3452,25 @@ function RecordsAdminShell(props) {
|
|
|
3080
3452
|
onTelemetry?.({ type: "presentation.change", recordType, from: presentation, to: next });
|
|
3081
3453
|
setPresentation(next);
|
|
3082
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);
|
|
3083
3474
|
const ctx = useMemo(
|
|
3084
3475
|
() => ({ SL, collectionId, appId, recordType }),
|
|
3085
3476
|
[SL, collectionId, appId, recordType]
|
|
@@ -3138,6 +3529,15 @@ function RecordsAdminShell(props) {
|
|
|
3138
3529
|
}
|
|
3139
3530
|
}, [contextScope?.batchId]);
|
|
3140
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]);
|
|
3141
3541
|
const productBrowse = useProductBrowse({
|
|
3142
3542
|
SL,
|
|
3143
3543
|
collectionId,
|
|
@@ -3149,7 +3549,7 @@ function RecordsAdminShell(props) {
|
|
|
3149
3549
|
scopeKind: activeScope,
|
|
3150
3550
|
search,
|
|
3151
3551
|
filter,
|
|
3152
|
-
classify,
|
|
3552
|
+
classify: classify2,
|
|
3153
3553
|
contextScope,
|
|
3154
3554
|
enabled: activeScope === "facet" && !probe.isLoading
|
|
3155
3555
|
});
|
|
@@ -3204,19 +3604,82 @@ function RecordsAdminShell(props) {
|
|
|
3204
3604
|
}
|
|
3205
3605
|
return parseRef(buildRef({ productId: selectedProductId }));
|
|
3206
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]);
|
|
3207
3670
|
const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
|
|
3208
3671
|
const resolved = useResolvedRecord({
|
|
3209
3672
|
SL,
|
|
3210
3673
|
appId,
|
|
3211
3674
|
recordType,
|
|
3212
3675
|
collectionId,
|
|
3213
|
-
productId:
|
|
3214
|
-
variantId:
|
|
3215
|
-
batchId:
|
|
3216
|
-
facetId:
|
|
3217
|
-
facetValue:
|
|
3676
|
+
productId: editingTargetScope?.productId,
|
|
3677
|
+
variantId: editingTargetScope?.variantId,
|
|
3678
|
+
batchId: editingTargetScope?.batchId,
|
|
3679
|
+
facetId: editingTargetScope?.facetId,
|
|
3680
|
+
facetValue: editingTargetScope?.facetValue,
|
|
3218
3681
|
supportedScopes: supportedForResolution,
|
|
3219
|
-
enabled: !!
|
|
3682
|
+
enabled: !!editingTargetScope
|
|
3220
3683
|
});
|
|
3221
3684
|
const refetchAll = useCallback(() => {
|
|
3222
3685
|
productBrowse.refetch();
|
|
@@ -3224,20 +3687,23 @@ function RecordsAdminShell(props) {
|
|
|
3224
3687
|
facetBrowse.refetch();
|
|
3225
3688
|
variantChildren.refetch();
|
|
3226
3689
|
batchChildren.refetch();
|
|
3227
|
-
|
|
3690
|
+
if (isCollection) collectionItems.refetch();
|
|
3691
|
+
}, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren, isCollection, collectionItems]);
|
|
3228
3692
|
const editorCtx = useRecordEditor({
|
|
3229
3693
|
ctx,
|
|
3230
|
-
scope:
|
|
3694
|
+
scope: editingTargetScope ?? parseRef(""),
|
|
3231
3695
|
resolved: { data: resolved.data, source: resolved.source, sourceRef: resolved.sourceRef, parentValue: resolved.parentValue },
|
|
3232
3696
|
defaultData,
|
|
3233
3697
|
reseed: dirtyStrategy === "keep" ? "preserve-dirty" : "always",
|
|
3234
3698
|
onSaved: () => {
|
|
3235
|
-
onTelemetry?.({ type: "record.save", recordType, ref:
|
|
3699
|
+
onTelemetry?.({ type: "record.save", recordType, ref: editingTargetScope?.raw ?? "", isCreate: resolved.source !== "self" });
|
|
3236
3700
|
refetchAll();
|
|
3237
3701
|
},
|
|
3238
3702
|
onDeleted: () => {
|
|
3239
|
-
onTelemetry?.({ type: "record.delete", recordType, ref:
|
|
3240
|
-
if (
|
|
3703
|
+
onTelemetry?.({ type: "record.delete", recordType, ref: editingTargetScope?.raw ?? "" });
|
|
3704
|
+
if (isCollection && selectedItemId) {
|
|
3705
|
+
setSelectedItemId(null);
|
|
3706
|
+
} else if (activeScope === "facet") {
|
|
3241
3707
|
setSelectedFacetRef(void 0);
|
|
3242
3708
|
} else if (drillTab === "variant") {
|
|
3243
3709
|
setSelectedVariantId(void 0);
|
|
@@ -3494,15 +3960,104 @@ function RecordsAdminShell(props) {
|
|
|
3494
3960
|
};
|
|
3495
3961
|
} : void 0;
|
|
3496
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]);
|
|
3497
4052
|
const renderEditorWithPreview = () => {
|
|
3498
|
-
if (!
|
|
4053
|
+
if (!editingTargetScope) return null;
|
|
3499
4054
|
const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
|
|
3500
4055
|
const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
3501
4056
|
PreviewScopePicker,
|
|
3502
4057
|
{
|
|
3503
4058
|
SL,
|
|
3504
4059
|
collectionId,
|
|
3505
|
-
editingScope,
|
|
4060
|
+
editingScope: editingTargetScope,
|
|
3506
4061
|
value: effectivePreviewScope,
|
|
3507
4062
|
onChange: setPreviewScope,
|
|
3508
4063
|
showVariants: drillVariantsAllowed,
|
|
@@ -3510,6 +4065,20 @@ function RecordsAdminShell(props) {
|
|
|
3510
4065
|
i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
|
|
3511
4066
|
}
|
|
3512
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;
|
|
3513
4082
|
const baseEditor = (extraFooter, inlinePreviewBody) => /* @__PURE__ */ jsx(
|
|
3514
4083
|
RecordEditor,
|
|
3515
4084
|
{
|
|
@@ -3518,7 +4087,7 @@ function RecordsAdminShell(props) {
|
|
|
3518
4087
|
bulkActions: { ...csvBulk, i18n },
|
|
3519
4088
|
preview: inlinePreviewBody,
|
|
3520
4089
|
footerExtra: extraFooter,
|
|
3521
|
-
onBeforeDelete: onBeforeDelete &&
|
|
4090
|
+
onBeforeDelete: onBeforeDelete && editingTargetScope ? () => onBeforeDelete(editingTargetScope) : void 0,
|
|
3522
4091
|
headerLabel: editorHeaderLabel,
|
|
3523
4092
|
headerSubtitle: editorHeaderSubtitle,
|
|
3524
4093
|
headerMeta: editorHeaderMeta,
|
|
@@ -3528,64 +4097,76 @@ function RecordsAdminShell(props) {
|
|
|
3528
4097
|
children: renderEditor(editorCtx)
|
|
3529
4098
|
}
|
|
3530
4099
|
);
|
|
3531
|
-
|
|
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());
|
|
3532
4105
|
if (previewMode === "inline") {
|
|
3533
|
-
return baseEditor(
|
|
4106
|
+
return withNav(baseEditor(
|
|
3534
4107
|
void 0,
|
|
3535
4108
|
/* @__PURE__ */ jsx(InlinePreview, { label: i18n.preview, scopePicker, children: previewBody })
|
|
3536
|
-
);
|
|
4109
|
+
));
|
|
3537
4110
|
}
|
|
3538
4111
|
if (previewMode === "side") {
|
|
3539
4112
|
if (!sidePreviewOpen) {
|
|
3540
|
-
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() }),
|
|
3541
4128
|
/* @__PURE__ */ jsx(
|
|
3542
|
-
|
|
4129
|
+
SidePreview,
|
|
3543
4130
|
{
|
|
3544
|
-
|
|
3545
|
-
|
|
4131
|
+
label: i18n.preview,
|
|
4132
|
+
scopePicker,
|
|
4133
|
+
onClose: () => setSidePreviewOpen(false),
|
|
4134
|
+
children: previewBody
|
|
3546
4135
|
}
|
|
3547
4136
|
)
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
4137
|
+
] })
|
|
4138
|
+
);
|
|
4139
|
+
}
|
|
4140
|
+
if (previewMode === "tab") {
|
|
4141
|
+
return withNav(
|
|
3552
4142
|
/* @__PURE__ */ jsx(
|
|
3553
|
-
|
|
4143
|
+
TabbedPreview,
|
|
3554
4144
|
{
|
|
3555
|
-
|
|
4145
|
+
editor: baseEditor(),
|
|
4146
|
+
preview: previewBody,
|
|
3556
4147
|
scopePicker,
|
|
3557
|
-
|
|
3558
|
-
children: previewBody
|
|
4148
|
+
i18n: { editor: i18n.editor, preview: i18n.preview }
|
|
3559
4149
|
}
|
|
3560
4150
|
)
|
|
3561
|
-
] });
|
|
3562
|
-
}
|
|
3563
|
-
if (previewMode === "tab") {
|
|
3564
|
-
return /* @__PURE__ */ jsx(
|
|
3565
|
-
TabbedPreview,
|
|
3566
|
-
{
|
|
3567
|
-
editor: baseEditor(),
|
|
3568
|
-
preview: previewBody,
|
|
3569
|
-
scopePicker,
|
|
3570
|
-
i18n: { editor: i18n.editor, preview: i18n.preview }
|
|
3571
|
-
}
|
|
3572
4151
|
);
|
|
3573
4152
|
}
|
|
3574
|
-
return
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
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
|
+
);
|
|
3589
4170
|
};
|
|
3590
4171
|
const isProductTab = activeScope === "product";
|
|
3591
4172
|
const productPinned = !!contextScope?.productId;
|
|
@@ -3661,9 +4242,9 @@ function RecordsAdminShell(props) {
|
|
|
3661
4242
|
}
|
|
3662
4243
|
),
|
|
3663
4244
|
(() => {
|
|
3664
|
-
|
|
3665
|
-
const
|
|
3666
|
-
|
|
4245
|
+
if (!headerWillRender) return null;
|
|
4246
|
+
const showHeaderReopen = !!intro && dismissed && resolvedReopenAffordance === "header";
|
|
4247
|
+
const reopenLabel = intro?.reopenLabel ?? `How ${label.toLowerCase()} works`;
|
|
3667
4248
|
return /* @__PURE__ */ jsx(
|
|
3668
4249
|
ShellHeader,
|
|
3669
4250
|
{
|
|
@@ -3681,18 +4262,32 @@ function RecordsAdminShell(props) {
|
|
|
3681
4262
|
},
|
|
3682
4263
|
statsItems,
|
|
3683
4264
|
statsTitle,
|
|
3684
|
-
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
|
|
3685
4279
|
}
|
|
3686
4280
|
);
|
|
3687
4281
|
})(),
|
|
3688
|
-
/* @__PURE__ */ jsx(
|
|
4282
|
+
resolvedReopenAffordance === "inline" || resolvedReopenAffordance === "footer" ? /* @__PURE__ */ jsx(
|
|
3689
4283
|
UtilityRow,
|
|
3690
4284
|
{
|
|
3691
|
-
label,
|
|
4285
|
+
label: intro?.reopenLabel ? "" : label,
|
|
4286
|
+
customLabel: intro?.reopenLabel,
|
|
3692
4287
|
introHidden: dismissed && !!intro,
|
|
3693
4288
|
onShowIntro: undismiss
|
|
3694
4289
|
}
|
|
3695
|
-
),
|
|
4290
|
+
) : null,
|
|
3696
4291
|
editorCtx.isDirty && /* @__PURE__ */ jsx(
|
|
3697
4292
|
UnsavedBanner,
|
|
3698
4293
|
{
|
|
@@ -3721,7 +4316,18 @@ function RecordsAdminShell(props) {
|
|
|
3721
4316
|
className: "flex-1 grid border-t overflow-hidden",
|
|
3722
4317
|
style: { gridTemplateColumns: "minmax(260px, 320px) 1fr", borderColor: "hsl(var(--ra-border))", marginTop: "0.75rem" },
|
|
3723
4318
|
children: [
|
|
3724
|
-
/* @__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: [
|
|
3725
4331
|
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
|
|
3726
4332
|
ScopeTabs,
|
|
3727
4333
|
{
|
|
@@ -3776,27 +4382,6 @@ function RecordsAdminShell(props) {
|
|
|
3776
4382
|
hideZero: ["partial"],
|
|
3777
4383
|
i18n
|
|
3778
4384
|
}
|
|
3779
|
-
),
|
|
3780
|
-
cardinality === "collection" && !isProductTab && editingScope && /* @__PURE__ */ jsxs(
|
|
3781
|
-
"button",
|
|
3782
|
-
{
|
|
3783
|
-
type: "button",
|
|
3784
|
-
onClick: () => {
|
|
3785
|
-
void runWithGuard(() => {
|
|
3786
|
-
const id = generateItemId ? generateItemId() : defaultItemId();
|
|
3787
|
-
const baseRef = editingScope.raw;
|
|
3788
|
-
const itemRef = baseRef ? `${baseRef}/item:${id}` : `item:${id}`;
|
|
3789
|
-
setSelectedFacetRef(itemRef);
|
|
3790
|
-
onTelemetry?.({ type: "item.create", recordType, scopeRef: baseRef });
|
|
3791
|
-
});
|
|
3792
|
-
},
|
|
3793
|
-
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))]",
|
|
3794
|
-
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
3795
|
-
children: [
|
|
3796
|
-
/* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
|
|
3797
|
-
i18n.newItem || `New ${itemNoun}`
|
|
3798
|
-
]
|
|
3799
|
-
}
|
|
3800
4385
|
)
|
|
3801
4386
|
] }),
|
|
3802
4387
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
@@ -3820,7 +4405,6 @@ function RecordsAdminShell(props) {
|
|
|
3820
4405
|
dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
|
|
3821
4406
|
presentation: effectivePresentation,
|
|
3822
4407
|
renderListRow,
|
|
3823
|
-
renderCard,
|
|
3824
4408
|
groupBy: effectiveGroupBy,
|
|
3825
4409
|
rowClipboard
|
|
3826
4410
|
}
|
|
@@ -3840,11 +4424,29 @@ function RecordsAdminShell(props) {
|
|
|
3840
4424
|
) })
|
|
3841
4425
|
] })
|
|
3842
4426
|
] })
|
|
3843
|
-
] }),
|
|
4427
|
+
] }) }),
|
|
3844
4428
|
/* @__PURE__ */ jsxs("main", { className: "overflow-hidden", children: [
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
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(
|
|
3848
4450
|
ProductDrillDown,
|
|
3849
4451
|
{
|
|
3850
4452
|
productLabel: productBrowse.items.find((p) => p.id === selectedProductId)?.name ?? selectedProductId,
|
|
@@ -3872,7 +4474,7 @@ function RecordsAdminShell(props) {
|
|
|
3872
4474
|
batches: batchChildren.items,
|
|
3873
4475
|
variantsLoading: variantChildren.isLoading,
|
|
3874
4476
|
batchesLoading: batchChildren.isLoading,
|
|
3875
|
-
children:
|
|
4477
|
+
children: editingTargetScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
|
|
3876
4478
|
EmptyState,
|
|
3877
4479
|
{
|
|
3878
4480
|
title: drillTab === "variant" ? "Pick a variant" : "Pick a batch",
|
|
@@ -3881,7 +4483,7 @@ function RecordsAdminShell(props) {
|
|
|
3881
4483
|
)
|
|
3882
4484
|
}
|
|
3883
4485
|
),
|
|
3884
|
-
!isProductTab &&
|
|
4486
|
+
!isProductTab && editingTargetScope && (!isCollection || selectedItemId) && renderEditorWithPreview()
|
|
3885
4487
|
] })
|
|
3886
4488
|
]
|
|
3887
4489
|
}
|
|
@@ -3953,6 +4555,87 @@ var RecordBrowser = ({
|
|
|
3953
4555
|
] })
|
|
3954
4556
|
] });
|
|
3955
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
|
+
};
|
|
3956
4639
|
var Ctx = createContext({});
|
|
3957
4640
|
var InheritanceProvider = ({
|
|
3958
4641
|
parentValue,
|
|
@@ -4283,6 +4966,6 @@ function useMergedRecord(args) {
|
|
|
4283
4966
|
};
|
|
4284
4967
|
}
|
|
4285
4968
|
|
|
4286
|
-
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,
|
|
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 };
|
|
4287
4970
|
//# sourceMappingURL=index.js.map
|
|
4288
4971
|
//# sourceMappingURL=index.js.map
|