@proveanything/smartlinks-utils-ui 0.3.5 → 0.3.8
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-NIAIQRFC.js +28 -0
- package/dist/chunk-NIAIQRFC.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 +83 -15
- package/dist/components/RecordsAdmin/index.js +664 -76
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-WFNEZQCD.js +0 -28
- package/dist/chunk-WFNEZQCD.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { styleInject } from '../../chunk-
|
|
1
|
+
import { styleInject } from '../../chunk-NIAIQRFC.js';
|
|
2
2
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
3
3
|
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, Image, List, ChevronRight, Eraser, Box, AlertTriangle, Info,
|
|
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, Image, List, ChevronRight, Eraser, Box, X, AlertTriangle, Info, HelpCircle, Search, CornerDownLeft, Circle, AlertCircle, Undo2, Save } from 'lucide-react';
|
|
5
5
|
import { useQueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
|
6
|
+
import { createPortal } from 'react-dom';
|
|
6
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
|
|
8
9
|
var DEFAULT_ICONS = {
|
|
@@ -83,6 +84,7 @@ var DEFAULT_I18N = {
|
|
|
83
84
|
unsavedPromptDiscard: "Discard changes",
|
|
84
85
|
unsavedPromptCancel: "Stay here",
|
|
85
86
|
unsavedPromptSave: "Save & continue",
|
|
87
|
+
unsavedBannerBody: "Unsaved changes on {name}",
|
|
86
88
|
presentationList: "List",
|
|
87
89
|
presentationGrid: "Grid",
|
|
88
90
|
presentationGallery: "Gallery",
|
|
@@ -436,6 +438,7 @@ var useRecordList = (args) => {
|
|
|
436
438
|
}, [queryClient, ctx.collectionId, ctx.appId, ctx.recordType]);
|
|
437
439
|
const total = query.data?.pages[query.data.pages.length - 1]?.total ?? items.length;
|
|
438
440
|
return {
|
|
441
|
+
allItems: items,
|
|
439
442
|
items: filtered,
|
|
440
443
|
total,
|
|
441
444
|
counts,
|
|
@@ -454,12 +457,24 @@ var resolveRecord = async (args) => {
|
|
|
454
457
|
const editingScope = parsedRefToScope(args.target);
|
|
455
458
|
const result = await matchRecords(args.ctx, target, { strategy: "all" }).catch(() => null);
|
|
456
459
|
const records = result?.records ?? [];
|
|
460
|
+
console.info("[RecordsAdmin/resolveRecord]", {
|
|
461
|
+
editingScope,
|
|
462
|
+
target,
|
|
463
|
+
matchCount: records.length,
|
|
464
|
+
winnerScope: records[0]?.record?.scope,
|
|
465
|
+
winnerRef: records[0]?.record?.ref
|
|
466
|
+
});
|
|
457
467
|
if (records.length === 0) {
|
|
458
468
|
return { data: null, source: "empty" };
|
|
459
469
|
}
|
|
460
470
|
const winnerEntry = records[0];
|
|
461
471
|
const winner = winnerEntry.record;
|
|
462
472
|
const winnerIsSelf = scopesEqual(winner.scope, editingScope);
|
|
473
|
+
console.info("[RecordsAdmin/resolveRecord] classification", {
|
|
474
|
+
winnerIsSelf,
|
|
475
|
+
winnerScope: winner.scope,
|
|
476
|
+
editingScope
|
|
477
|
+
});
|
|
463
478
|
if (winnerIsSelf) {
|
|
464
479
|
const parent = records[1]?.record;
|
|
465
480
|
return {
|
|
@@ -750,7 +765,133 @@ var useScopeProbe = ({ SL, collectionId, admin = true, enabled = true }) => {
|
|
|
750
765
|
error: query.error ?? null
|
|
751
766
|
};
|
|
752
767
|
};
|
|
753
|
-
var
|
|
768
|
+
var LOG = "[RecordsAdmin/useFacetBrowse]";
|
|
769
|
+
var QK = ["records-admin", "facet-browse"];
|
|
770
|
+
var toScaffoldSummary = (facet, value) => {
|
|
771
|
+
const facetKey = facet.key ?? "";
|
|
772
|
+
const valueKey = value.key ?? "";
|
|
773
|
+
const ref = buildRef({ facetId: facetKey, facetValue: valueKey });
|
|
774
|
+
return {
|
|
775
|
+
id: null,
|
|
776
|
+
ref,
|
|
777
|
+
scope: parseRef(ref),
|
|
778
|
+
data: null,
|
|
779
|
+
status: "empty",
|
|
780
|
+
label: value.name ?? valueKey ?? "Untitled value",
|
|
781
|
+
subtitle: facet.name ?? facetKey ?? void 0
|
|
782
|
+
};
|
|
783
|
+
};
|
|
784
|
+
var useFacetBrowse = ({
|
|
785
|
+
SL,
|
|
786
|
+
collectionId,
|
|
787
|
+
existing,
|
|
788
|
+
search = "",
|
|
789
|
+
filter = "all",
|
|
790
|
+
enabled = true
|
|
791
|
+
}) => {
|
|
792
|
+
const queryClient = useQueryClient();
|
|
793
|
+
const hasAdminList = !!SL?.facets?.list;
|
|
794
|
+
const hasPublicList = !!SL?.facets?.publicList;
|
|
795
|
+
const hasAnyList = hasAdminList || hasPublicList;
|
|
796
|
+
const queryEnabled = enabled && !!collectionId && hasAnyList;
|
|
797
|
+
const query = useQuery({
|
|
798
|
+
queryKey: [...QK, collectionId],
|
|
799
|
+
enabled: queryEnabled,
|
|
800
|
+
staleTime: 3e4,
|
|
801
|
+
queryFn: async () => {
|
|
802
|
+
const t0 = performance.now();
|
|
803
|
+
try {
|
|
804
|
+
if (SL?.facets?.list) {
|
|
805
|
+
console.info(`${LOG} \u2192 SL.facets.list("${collectionId}", { includeValues: true })`);
|
|
806
|
+
const res = await SL.facets.list(collectionId, { includeValues: true });
|
|
807
|
+
const items = res?.items ?? [];
|
|
808
|
+
console.info(
|
|
809
|
+
`${LOG} \u2190 SL.facets.list ok in ${Math.round(performance.now() - t0)}ms \u2014 ${items.length} facet(s)`,
|
|
810
|
+
items
|
|
811
|
+
);
|
|
812
|
+
return items;
|
|
813
|
+
}
|
|
814
|
+
if (SL?.facets?.publicList) {
|
|
815
|
+
console.info(`${LOG} \u2192 SL.facets.publicList("${collectionId}", { includeValues: true })`);
|
|
816
|
+
const res = await SL.facets.publicList(collectionId, { includeValues: true });
|
|
817
|
+
const items = res?.items ?? [];
|
|
818
|
+
console.info(
|
|
819
|
+
`${LOG} \u2190 SL.facets.publicList ok in ${Math.round(performance.now() - t0)}ms \u2014 ${items.length} facet(s)`,
|
|
820
|
+
items
|
|
821
|
+
);
|
|
822
|
+
return items;
|
|
823
|
+
}
|
|
824
|
+
console.warn(`${LOG} queryFn ran but no facets API is available on SL`);
|
|
825
|
+
return [];
|
|
826
|
+
} catch (err) {
|
|
827
|
+
console.error(`${LOG} \u2716 facets fetch failed`, err);
|
|
828
|
+
throw err;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
const lastLoggedRef = useRef("");
|
|
833
|
+
useEffect(() => {
|
|
834
|
+
const signature = `${enabled}|${collectionId}|${hasAdminList}|${hasPublicList}`;
|
|
835
|
+
if (signature === lastLoggedRef.current) return;
|
|
836
|
+
lastLoggedRef.current = signature;
|
|
837
|
+
if (!enabled) {
|
|
838
|
+
console.info(`${LOG} skipped \u2014 enabled=false (shell not on facet tab yet)`);
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
if (!collectionId) {
|
|
842
|
+
console.warn(`${LOG} skipped \u2014 no collectionId provided`);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
if (!hasAnyList) {
|
|
846
|
+
console.warn(
|
|
847
|
+
`${LOG} skipped \u2014 SDK is missing both SL.facets.list and SL.facets.publicList. Update @proveanything/smartlinks (>=1.8) or check the SDK build.`,
|
|
848
|
+
{ facetsNamespace: SL?.facets ? Object.keys(SL.facets) : null }
|
|
849
|
+
);
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
console.info(
|
|
853
|
+
`${LOG} will fetch facets for collection "${collectionId}" via ${hasAdminList ? "SL.facets.list (admin)" : "SL.facets.publicList (fallback)"}`
|
|
854
|
+
);
|
|
855
|
+
}, [enabled, collectionId, hasAdminList, hasPublicList, hasAnyList, SL]);
|
|
856
|
+
const mergedItems = useMemo(() => {
|
|
857
|
+
const existingByRef = new Map(existing.map((item) => [item.ref, item]));
|
|
858
|
+
const scaffolded = (query.data ?? []).flatMap(
|
|
859
|
+
(facet) => (facet.values ?? []).filter((value) => !!facet.key && !!value.key).map((value) => {
|
|
860
|
+
const scaffold = toScaffoldSummary(facet, value);
|
|
861
|
+
return existingByRef.get(scaffold.ref) ?? scaffold;
|
|
862
|
+
})
|
|
863
|
+
);
|
|
864
|
+
const extras = existing.filter((item) => !scaffolded.some((scaffold) => scaffold.ref === item.ref));
|
|
865
|
+
return [...scaffolded, ...extras];
|
|
866
|
+
}, [existing, query.data]);
|
|
867
|
+
const filteredItems = useMemo(() => {
|
|
868
|
+
let next = mergedItems;
|
|
869
|
+
if (filter !== "all") next = next.filter((item) => item.status === filter);
|
|
870
|
+
if (search.trim()) {
|
|
871
|
+
const q = search.trim().toLowerCase();
|
|
872
|
+
next = next.filter((item) => `${item.label} ${item.subtitle ?? ""} ${item.ref}`.toLowerCase().includes(q));
|
|
873
|
+
}
|
|
874
|
+
return next;
|
|
875
|
+
}, [mergedItems, filter, search]);
|
|
876
|
+
const counts = useMemo(() => ({
|
|
877
|
+
all: mergedItems.length,
|
|
878
|
+
configured: mergedItems.filter((item) => item.status === "configured").length,
|
|
879
|
+
partial: mergedItems.filter((item) => item.status === "partial").length,
|
|
880
|
+
empty: mergedItems.filter((item) => item.status === "empty").length
|
|
881
|
+
}), [mergedItems]);
|
|
882
|
+
const refetch = () => {
|
|
883
|
+
queryClient.invalidateQueries({ queryKey: [...QK, collectionId] });
|
|
884
|
+
};
|
|
885
|
+
return {
|
|
886
|
+
items: filteredItems,
|
|
887
|
+
total: mergedItems.length,
|
|
888
|
+
counts,
|
|
889
|
+
isLoading: query.isLoading,
|
|
890
|
+
error: query.error ?? null,
|
|
891
|
+
refetch
|
|
892
|
+
};
|
|
893
|
+
};
|
|
894
|
+
var QK2 = ["records-admin", "product-browse"];
|
|
754
895
|
var toBrowseItem = (p) => ({
|
|
755
896
|
id: p.id ?? p.productId ?? "",
|
|
756
897
|
name: p.name ?? p.id ?? "Untitled",
|
|
@@ -761,12 +902,12 @@ var useProductBrowse = (args) => {
|
|
|
761
902
|
const { SL, collectionId, search = "", pageSize = 50, enabled = true, admin = true } = args;
|
|
762
903
|
const queryClient = useQueryClient();
|
|
763
904
|
const queryKey = useMemo(
|
|
764
|
-
() => [...
|
|
905
|
+
() => [...QK2, collectionId, search.trim(), pageSize, admin],
|
|
765
906
|
[collectionId, search, pageSize, admin]
|
|
766
907
|
);
|
|
767
908
|
const query = useInfiniteQuery({
|
|
768
909
|
queryKey,
|
|
769
|
-
enabled: enabled && !!collectionId && !!SL?.product?.query,
|
|
910
|
+
enabled: enabled && !!collectionId && !!(SL?.products?.query || SL?.product?.query || SL?.products?.list || SL?.product?.list),
|
|
770
911
|
initialPageParam: { offset: 0, cursor: null },
|
|
771
912
|
queryFn: async ({ pageParam }) => {
|
|
772
913
|
const body = {
|
|
@@ -774,7 +915,23 @@ var useProductBrowse = (args) => {
|
|
|
774
915
|
sort: [{ field: "sortOrder", direction: "asc" }, { field: "name", direction: "asc" }]
|
|
775
916
|
};
|
|
776
917
|
if (search.trim()) body.query = { search: search.trim() };
|
|
777
|
-
|
|
918
|
+
let res = null;
|
|
919
|
+
if (SL?.products?.query) {
|
|
920
|
+
res = await SL.products.query(collectionId, body);
|
|
921
|
+
} else if (SL?.product?.query) {
|
|
922
|
+
res = await SL.product.query(collectionId, body, admin);
|
|
923
|
+
} else {
|
|
924
|
+
const legacy = SL?.products?.list ? await SL.products.list(collectionId, admin) : SL?.product?.list ? await SL.product.list(collectionId, admin) : [];
|
|
925
|
+
const filteredLegacy = search.trim() ? legacy.filter((item) => `${item?.name ?? ""} ${item?.sku ?? ""} ${item?.id ?? ""}`.toLowerCase().includes(search.trim().toLowerCase())) : legacy;
|
|
926
|
+
const pageItems = filteredLegacy.slice(pageParam.offset, pageParam.offset + pageSize);
|
|
927
|
+
return {
|
|
928
|
+
items: pageItems.map(toBrowseItem),
|
|
929
|
+
nextOffset: pageParam.offset + pageItems.length,
|
|
930
|
+
nextCursor: null,
|
|
931
|
+
hasMore: pageParam.offset + pageItems.length < filteredLegacy.length,
|
|
932
|
+
total: filteredLegacy.length
|
|
933
|
+
};
|
|
934
|
+
}
|
|
778
935
|
const items2 = (res?.items ?? []).map(toBrowseItem);
|
|
779
936
|
const page = res?.page ?? {};
|
|
780
937
|
return {
|
|
@@ -796,7 +953,7 @@ var useProductBrowse = (args) => {
|
|
|
796
953
|
() => query.data?.pages.flatMap((p) => p.items) ?? [],
|
|
797
954
|
[query.data]
|
|
798
955
|
);
|
|
799
|
-
const refetch = () => queryClient.invalidateQueries({ queryKey: [...
|
|
956
|
+
const refetch = () => queryClient.invalidateQueries({ queryKey: [...QK2, collectionId] });
|
|
800
957
|
return {
|
|
801
958
|
items,
|
|
802
959
|
total: query.data?.pages[query.data.pages.length - 1]?.total,
|
|
@@ -808,7 +965,7 @@ var useProductBrowse = (args) => {
|
|
|
808
965
|
refetch
|
|
809
966
|
};
|
|
810
967
|
};
|
|
811
|
-
var
|
|
968
|
+
var QK3 = ["records-admin", "product-children"];
|
|
812
969
|
var variantToItem = (v) => ({
|
|
813
970
|
id: v.id ?? v.variantId ?? "",
|
|
814
971
|
name: v.name ?? v.label ?? v.id ?? "Untitled variant",
|
|
@@ -823,7 +980,7 @@ var useProductChildren = (args) => {
|
|
|
823
980
|
const { SL, collectionId, productId, kind, enabled = true } = args;
|
|
824
981
|
const queryClient = useQueryClient();
|
|
825
982
|
const queryKey = useMemo(
|
|
826
|
-
() => [...
|
|
983
|
+
() => [...QK3, collectionId, productId ?? null, kind],
|
|
827
984
|
[collectionId, productId, kind]
|
|
828
985
|
);
|
|
829
986
|
const query = useQuery({
|
|
@@ -841,7 +998,7 @@ var useProductChildren = (args) => {
|
|
|
841
998
|
}
|
|
842
999
|
});
|
|
843
1000
|
const refetch = () => queryClient.invalidateQueries({
|
|
844
|
-
queryKey: [...
|
|
1001
|
+
queryKey: [...QK3, collectionId, productId ?? null]
|
|
845
1002
|
});
|
|
846
1003
|
return {
|
|
847
1004
|
items: query.data ?? [],
|
|
@@ -958,6 +1115,144 @@ var useDirtyNavigation = ({
|
|
|
958
1115
|
);
|
|
959
1116
|
return { runWithGuard };
|
|
960
1117
|
};
|
|
1118
|
+
var ConfirmDialog = ({
|
|
1119
|
+
open,
|
|
1120
|
+
title,
|
|
1121
|
+
body,
|
|
1122
|
+
saveLabel,
|
|
1123
|
+
discardLabel,
|
|
1124
|
+
cancelLabel,
|
|
1125
|
+
onChoice
|
|
1126
|
+
}) => {
|
|
1127
|
+
const saveBtnRef = useRef(null);
|
|
1128
|
+
useEffect(() => {
|
|
1129
|
+
if (!open) return;
|
|
1130
|
+
const prev = document.body.style.overflow;
|
|
1131
|
+
document.body.style.overflow = "hidden";
|
|
1132
|
+
const t = window.setTimeout(() => saveBtnRef.current?.focus(), 0);
|
|
1133
|
+
const onKey = (e) => {
|
|
1134
|
+
if (e.key === "Escape") {
|
|
1135
|
+
e.stopPropagation();
|
|
1136
|
+
onChoice("cancel");
|
|
1137
|
+
}
|
|
1138
|
+
};
|
|
1139
|
+
window.addEventListener("keydown", onKey, true);
|
|
1140
|
+
return () => {
|
|
1141
|
+
window.clearTimeout(t);
|
|
1142
|
+
window.removeEventListener("keydown", onKey, true);
|
|
1143
|
+
document.body.style.overflow = prev;
|
|
1144
|
+
};
|
|
1145
|
+
}, [open, onChoice]);
|
|
1146
|
+
if (!open || typeof document === "undefined") return null;
|
|
1147
|
+
return createPortal(
|
|
1148
|
+
/* @__PURE__ */ jsxs(
|
|
1149
|
+
"div",
|
|
1150
|
+
{
|
|
1151
|
+
className: "ra-shell ra-confirm-root",
|
|
1152
|
+
role: "presentation",
|
|
1153
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
1154
|
+
onClick: (e) => e.stopPropagation(),
|
|
1155
|
+
children: [
|
|
1156
|
+
/* @__PURE__ */ jsx("div", { className: "ra-confirm-backdrop", onClick: () => onChoice("cancel") }),
|
|
1157
|
+
/* @__PURE__ */ jsxs(
|
|
1158
|
+
"div",
|
|
1159
|
+
{
|
|
1160
|
+
role: "alertdialog",
|
|
1161
|
+
"aria-modal": "true",
|
|
1162
|
+
"aria-labelledby": "ra-confirm-title",
|
|
1163
|
+
"aria-describedby": "ra-confirm-body",
|
|
1164
|
+
className: "ra-confirm-card",
|
|
1165
|
+
children: [
|
|
1166
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-confirm-header", children: [
|
|
1167
|
+
/* @__PURE__ */ jsx("span", { className: "ra-confirm-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AlertTriangle, { className: "w-4 h-4" }) }),
|
|
1168
|
+
/* @__PURE__ */ jsx("h2", { id: "ra-confirm-title", className: "ra-confirm-title", children: title })
|
|
1169
|
+
] }),
|
|
1170
|
+
/* @__PURE__ */ jsx("p", { id: "ra-confirm-body", className: "ra-confirm-body", children: body }),
|
|
1171
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-confirm-actions", children: [
|
|
1172
|
+
/* @__PURE__ */ jsx(
|
|
1173
|
+
"button",
|
|
1174
|
+
{
|
|
1175
|
+
type: "button",
|
|
1176
|
+
className: "ra-confirm-btn ra-confirm-btn-ghost",
|
|
1177
|
+
onClick: () => onChoice("cancel"),
|
|
1178
|
+
children: cancelLabel
|
|
1179
|
+
}
|
|
1180
|
+
),
|
|
1181
|
+
/* @__PURE__ */ jsx(
|
|
1182
|
+
"button",
|
|
1183
|
+
{
|
|
1184
|
+
type: "button",
|
|
1185
|
+
className: "ra-confirm-btn ra-confirm-btn-danger",
|
|
1186
|
+
onClick: () => onChoice("discard"),
|
|
1187
|
+
children: discardLabel
|
|
1188
|
+
}
|
|
1189
|
+
),
|
|
1190
|
+
/* @__PURE__ */ jsx(
|
|
1191
|
+
"button",
|
|
1192
|
+
{
|
|
1193
|
+
type: "button",
|
|
1194
|
+
ref: saveBtnRef,
|
|
1195
|
+
className: "ra-confirm-btn ra-confirm-btn-primary",
|
|
1196
|
+
onClick: () => onChoice("save"),
|
|
1197
|
+
children: saveLabel
|
|
1198
|
+
}
|
|
1199
|
+
)
|
|
1200
|
+
] })
|
|
1201
|
+
]
|
|
1202
|
+
}
|
|
1203
|
+
)
|
|
1204
|
+
]
|
|
1205
|
+
}
|
|
1206
|
+
),
|
|
1207
|
+
document.body
|
|
1208
|
+
);
|
|
1209
|
+
};
|
|
1210
|
+
var DEFAULTS = {
|
|
1211
|
+
title: "Unsaved changes",
|
|
1212
|
+
body: "You have unsaved changes. Save them, discard them, or stay on this record?",
|
|
1213
|
+
saveLabel: "Save & continue",
|
|
1214
|
+
discardLabel: "Discard",
|
|
1215
|
+
cancelLabel: "Stay here"
|
|
1216
|
+
};
|
|
1217
|
+
var useConfirmDialog = () => {
|
|
1218
|
+
const [open, setOpen] = useState(false);
|
|
1219
|
+
const [state, setState] = useState(DEFAULTS);
|
|
1220
|
+
const resolverRef = useRef(null);
|
|
1221
|
+
const confirm = useCallback((i18n) => {
|
|
1222
|
+
setState({
|
|
1223
|
+
title: i18n?.title ?? DEFAULTS.title,
|
|
1224
|
+
body: i18n?.body ?? DEFAULTS.body,
|
|
1225
|
+
saveLabel: i18n?.save ?? DEFAULTS.saveLabel,
|
|
1226
|
+
discardLabel: i18n?.discard ?? DEFAULTS.discardLabel,
|
|
1227
|
+
cancelLabel: i18n?.cancel ?? DEFAULTS.cancelLabel
|
|
1228
|
+
});
|
|
1229
|
+
setOpen(true);
|
|
1230
|
+
return new Promise((resolve) => {
|
|
1231
|
+
resolverRef.current = resolve;
|
|
1232
|
+
});
|
|
1233
|
+
}, []);
|
|
1234
|
+
const handleChoice = useCallback((choice) => {
|
|
1235
|
+
setOpen(false);
|
|
1236
|
+
const r = resolverRef.current;
|
|
1237
|
+
resolverRef.current = null;
|
|
1238
|
+
r?.(choice);
|
|
1239
|
+
}, []);
|
|
1240
|
+
return {
|
|
1241
|
+
confirm,
|
|
1242
|
+
dialog: /* @__PURE__ */ jsx(
|
|
1243
|
+
ConfirmDialog,
|
|
1244
|
+
{
|
|
1245
|
+
open,
|
|
1246
|
+
title: state.title,
|
|
1247
|
+
body: state.body,
|
|
1248
|
+
saveLabel: state.saveLabel,
|
|
1249
|
+
discardLabel: state.discardLabel,
|
|
1250
|
+
cancelLabel: state.cancelLabel,
|
|
1251
|
+
onChoice: handleChoice
|
|
1252
|
+
}
|
|
1253
|
+
)
|
|
1254
|
+
};
|
|
1255
|
+
};
|
|
961
1256
|
var LABELS = {
|
|
962
1257
|
product: "Products",
|
|
963
1258
|
facet: "Shared",
|
|
@@ -996,14 +1291,17 @@ var ScopeTabs = ({
|
|
|
996
1291
|
);
|
|
997
1292
|
}) });
|
|
998
1293
|
};
|
|
999
|
-
var StatusFilterPills = ({ value, onChange, counts, i18n }) => {
|
|
1294
|
+
var StatusFilterPills = ({ value, onChange, counts, i18n, hideZero }) => {
|
|
1000
1295
|
const opts = [
|
|
1001
1296
|
{ key: "all", label: i18n.filterAll, count: counts.all },
|
|
1002
1297
|
{ key: "configured", label: i18n.filterConfigured, count: counts.configured },
|
|
1003
1298
|
{ key: "partial", label: i18n.filterPartial, count: counts.partial },
|
|
1004
1299
|
{ key: "empty", label: i18n.filterEmpty, count: counts.empty }
|
|
1005
1300
|
];
|
|
1006
|
-
|
|
1301
|
+
const visible = opts.filter(
|
|
1302
|
+
(o) => o.key === value || !hideZero?.includes(o.key) || o.count > 0
|
|
1303
|
+
);
|
|
1304
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: visible.map((o) => {
|
|
1007
1305
|
const active = value === o.key;
|
|
1008
1306
|
return /* @__PURE__ */ jsxs(
|
|
1009
1307
|
"button",
|
|
@@ -1498,25 +1796,49 @@ function RecordEditor({
|
|
|
1498
1796
|
preview,
|
|
1499
1797
|
bulkActions,
|
|
1500
1798
|
footerExtra,
|
|
1501
|
-
onBeforeDelete
|
|
1799
|
+
onBeforeDelete,
|
|
1800
|
+
headerLabel,
|
|
1801
|
+
headerSubtitle,
|
|
1802
|
+
headerMeta
|
|
1502
1803
|
}) {
|
|
1503
|
-
const sourceLabel = ctx.source === "self" ? "
|
|
1804
|
+
const sourceLabel = ctx.source === "self" ? "Customised" : ctx.source === "inherited" ? "Inherited" : null;
|
|
1504
1805
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
1505
1806
|
/* @__PURE__ */ jsxs(
|
|
1506
1807
|
"header",
|
|
1507
1808
|
{
|
|
1508
|
-
className: "sticky top-0 z-
|
|
1809
|
+
className: "sticky top-0 z-40 px-5 py-3 border-b flex items-start justify-between gap-3",
|
|
1509
1810
|
style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" },
|
|
1510
1811
|
children: [
|
|
1511
1812
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1512
|
-
/* @__PURE__ */
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1813
|
+
headerLabel ? /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
1814
|
+
/* @__PURE__ */ jsx(
|
|
1815
|
+
"div",
|
|
1816
|
+
{
|
|
1817
|
+
className: "text-sm font-medium truncate",
|
|
1818
|
+
style: { color: "hsl(var(--ra-text))" },
|
|
1819
|
+
title: headerLabel,
|
|
1820
|
+
children: headerLabel
|
|
1821
|
+
}
|
|
1822
|
+
),
|
|
1823
|
+
headerSubtitle && /* @__PURE__ */ jsx(
|
|
1824
|
+
"div",
|
|
1825
|
+
{
|
|
1826
|
+
className: "text-xs truncate",
|
|
1827
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
1828
|
+
title: headerSubtitle,
|
|
1829
|
+
children: headerSubtitle
|
|
1830
|
+
}
|
|
1831
|
+
)
|
|
1832
|
+
] }) : /* @__PURE__ */ jsx(ScopeBreadcrumb, { scope: ctx.scope }),
|
|
1833
|
+
(sourceLabel || ctx.isDirty) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mt-1", children: [
|
|
1834
|
+
sourceLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1835
|
+
/* @__PURE__ */ jsx(StatusDot, { source: ctx.source }),
|
|
1836
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide", style: { color: "hsl(var(--ra-muted-text))" }, children: sourceLabel })
|
|
1837
|
+
] }),
|
|
1516
1838
|
ctx.isDirty && /* @__PURE__ */ jsxs(
|
|
1517
1839
|
"span",
|
|
1518
1840
|
{
|
|
1519
|
-
className:
|
|
1841
|
+
className: `flex items-center gap-1 text-[10px] uppercase tracking-wide ${sourceLabel ? "ml-2" : ""}`,
|
|
1520
1842
|
style: { color: "hsl(var(--ra-accent))" },
|
|
1521
1843
|
children: [
|
|
1522
1844
|
/* @__PURE__ */ jsx("span", { className: "ra-status-dot ra-status-shared", "aria-hidden": "true" }),
|
|
@@ -1526,7 +1848,22 @@ function RecordEditor({
|
|
|
1526
1848
|
)
|
|
1527
1849
|
] })
|
|
1528
1850
|
] }),
|
|
1529
|
-
|
|
1851
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 shrink-0", children: [
|
|
1852
|
+
headerMeta && /* @__PURE__ */ jsx(
|
|
1853
|
+
"code",
|
|
1854
|
+
{
|
|
1855
|
+
className: "text-[10px] font-mono px-1.5 py-0.5 rounded truncate max-w-[14rem] mt-0.5",
|
|
1856
|
+
style: {
|
|
1857
|
+
color: "hsl(var(--ra-muted-text) / 0.85)",
|
|
1858
|
+
background: "hsl(var(--ra-muted) / 0.5)",
|
|
1859
|
+
border: "1px solid hsl(var(--ra-border) / 0.6)"
|
|
1860
|
+
},
|
|
1861
|
+
title: headerMeta,
|
|
1862
|
+
children: headerMeta
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
bulkActions && /* @__PURE__ */ jsx(BulkActionsMenu, { ...bulkActions, i18n })
|
|
1866
|
+
] })
|
|
1530
1867
|
]
|
|
1531
1868
|
}
|
|
1532
1869
|
),
|
|
@@ -1741,13 +2078,29 @@ var InlinePreview = ({ children, scopePicker, label = "Preview" }) => /* @__PURE
|
|
|
1741
2078
|
] }),
|
|
1742
2079
|
children
|
|
1743
2080
|
] });
|
|
1744
|
-
var SidePreview = ({
|
|
2081
|
+
var SidePreview = ({
|
|
2082
|
+
children,
|
|
2083
|
+
scopePicker,
|
|
2084
|
+
label = "Preview",
|
|
2085
|
+
onClose
|
|
2086
|
+
}) => /* @__PURE__ */ jsxs("div", { className: "ra-preview-rail", children: [
|
|
1745
2087
|
/* @__PURE__ */ jsxs("header", { className: "ra-preview-rail-header", children: [
|
|
1746
2088
|
/* @__PURE__ */ jsxs("div", { className: "ra-preview-rail-title", children: [
|
|
1747
2089
|
/* @__PURE__ */ jsx(Eye, { className: "w-3 h-3" }),
|
|
1748
2090
|
label
|
|
1749
2091
|
] }),
|
|
1750
|
-
scopePicker && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: scopePicker })
|
|
2092
|
+
scopePicker && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: scopePicker }),
|
|
2093
|
+
onClose && /* @__PURE__ */ jsx(
|
|
2094
|
+
"button",
|
|
2095
|
+
{
|
|
2096
|
+
type: "button",
|
|
2097
|
+
onClick: onClose,
|
|
2098
|
+
"aria-label": "Close preview",
|
|
2099
|
+
className: scopePicker ? "p-1 rounded hover:bg-[hsl(var(--ra-muted))]" : "ml-auto p-1 rounded hover:bg-[hsl(var(--ra-muted))]",
|
|
2100
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
2101
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
|
|
2102
|
+
}
|
|
2103
|
+
)
|
|
1751
2104
|
] }),
|
|
1752
2105
|
/* @__PURE__ */ jsx("div", { className: "ra-preview-rail-body", children })
|
|
1753
2106
|
] });
|
|
@@ -1861,7 +2214,13 @@ var PreviewScopePicker = ({
|
|
|
1861
2214
|
showBatches,
|
|
1862
2215
|
i18n
|
|
1863
2216
|
}) => {
|
|
1864
|
-
const
|
|
2217
|
+
const productPinned = !!editingScope.productId;
|
|
2218
|
+
const products = useProductBrowse({
|
|
2219
|
+
SL,
|
|
2220
|
+
collectionId,
|
|
2221
|
+
pageSize: 100,
|
|
2222
|
+
enabled: !productPinned
|
|
2223
|
+
});
|
|
1865
2224
|
const variants = useProductChildren({
|
|
1866
2225
|
SL,
|
|
1867
2226
|
collectionId,
|
|
@@ -1878,6 +2237,27 @@ var PreviewScopePicker = ({
|
|
|
1878
2237
|
() => value.raw === editingScope.raw,
|
|
1879
2238
|
[value.raw, editingScope.raw]
|
|
1880
2239
|
);
|
|
2240
|
+
useEffect(() => {
|
|
2241
|
+
if (productPinned) return;
|
|
2242
|
+
if (value.productId) return;
|
|
2243
|
+
const first = products.items[0];
|
|
2244
|
+
if (!first) return;
|
|
2245
|
+
onChange({
|
|
2246
|
+
...value,
|
|
2247
|
+
productId: first.id,
|
|
2248
|
+
variantId: void 0,
|
|
2249
|
+
batchId: void 0,
|
|
2250
|
+
raw: `product:${first.id}`
|
|
2251
|
+
});
|
|
2252
|
+
}, [productPinned, value.productId, products.items]);
|
|
2253
|
+
const [productPickerOpen, setProductPickerOpen] = useState(false);
|
|
2254
|
+
const showProductPicker = !productPinned && products.items.length > 1;
|
|
2255
|
+
const showVariantPicker = showVariants && !!value.productId && variants.items.length > 0;
|
|
2256
|
+
const showBatchPicker = showBatches && !!value.productId && batches.items.length > 0;
|
|
2257
|
+
if (!showProductPicker && !showVariantPicker && !showBatchPicker) {
|
|
2258
|
+
return null;
|
|
2259
|
+
}
|
|
2260
|
+
const currentProductName = products.items.find((p) => p.id === value.productId)?.name ?? value.productId ?? "";
|
|
1881
2261
|
const selectStyle = {
|
|
1882
2262
|
borderColor: "hsl(var(--ra-border))",
|
|
1883
2263
|
color: "hsl(var(--ra-text))"
|
|
@@ -1907,30 +2287,44 @@ var PreviewScopePicker = ({
|
|
|
1907
2287
|
]
|
|
1908
2288
|
}
|
|
1909
2289
|
),
|
|
1910
|
-
/* @__PURE__ */ jsxs(
|
|
2290
|
+
showProductPicker && !productPickerOpen && currentProductName && /* @__PURE__ */ jsxs(
|
|
2291
|
+
"button",
|
|
2292
|
+
{
|
|
2293
|
+
type: "button",
|
|
2294
|
+
onClick: () => setProductPickerOpen(true),
|
|
2295
|
+
className: "text-[10px] px-2 py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1 max-w-[12rem] truncate",
|
|
2296
|
+
style: selectStyle,
|
|
2297
|
+
title: `Preview as ${currentProductName} \u2014 click to change`,
|
|
2298
|
+
children: [
|
|
2299
|
+
"as ",
|
|
2300
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate", children: currentProductName }),
|
|
2301
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3 opacity-60" })
|
|
2302
|
+
]
|
|
2303
|
+
}
|
|
2304
|
+
),
|
|
2305
|
+
showProductPicker && productPickerOpen && /* @__PURE__ */ jsx(
|
|
1911
2306
|
"select",
|
|
1912
2307
|
{
|
|
1913
2308
|
className: SELECT_CLS,
|
|
1914
2309
|
style: selectStyle,
|
|
2310
|
+
autoFocus: true,
|
|
2311
|
+
onBlur: () => setProductPickerOpen(false),
|
|
1915
2312
|
value: value.productId ?? "",
|
|
1916
2313
|
onChange: (e) => {
|
|
1917
2314
|
const productId = e.target.value || void 0;
|
|
1918
2315
|
onChange({
|
|
1919
2316
|
...value,
|
|
1920
2317
|
productId,
|
|
1921
|
-
// Clear variant/batch when switching products.
|
|
1922
2318
|
variantId: void 0,
|
|
1923
2319
|
batchId: void 0,
|
|
1924
2320
|
raw: productId ? `product:${productId}` : ""
|
|
1925
2321
|
});
|
|
2322
|
+
setProductPickerOpen(false);
|
|
1926
2323
|
},
|
|
1927
|
-
children:
|
|
1928
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 Any product \u2014" }),
|
|
1929
|
-
products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
|
|
1930
|
-
]
|
|
2324
|
+
children: products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
|
|
1931
2325
|
}
|
|
1932
2326
|
),
|
|
1933
|
-
|
|
2327
|
+
showVariantPicker && /* @__PURE__ */ jsxs(
|
|
1934
2328
|
"select",
|
|
1935
2329
|
{
|
|
1936
2330
|
className: SELECT_CLS,
|
|
@@ -1951,7 +2345,7 @@ var PreviewScopePicker = ({
|
|
|
1951
2345
|
]
|
|
1952
2346
|
}
|
|
1953
2347
|
),
|
|
1954
|
-
|
|
2348
|
+
showBatchPicker && /* @__PURE__ */ jsxs(
|
|
1955
2349
|
"select",
|
|
1956
2350
|
{
|
|
1957
2351
|
className: SELECT_CLS,
|
|
@@ -2037,7 +2431,9 @@ function ShellHeader({
|
|
|
2037
2431
|
recordType,
|
|
2038
2432
|
icons,
|
|
2039
2433
|
stats,
|
|
2040
|
-
statsItems
|
|
2434
|
+
statsItems,
|
|
2435
|
+
statsTitle,
|
|
2436
|
+
statsIcon
|
|
2041
2437
|
}) {
|
|
2042
2438
|
let iconNode = null;
|
|
2043
2439
|
if (showHeaderIcon) {
|
|
@@ -2061,6 +2457,7 @@ function ShellHeader({
|
|
|
2061
2457
|
return items;
|
|
2062
2458
|
})();
|
|
2063
2459
|
const hasStats = resolvedItems.length > 0;
|
|
2460
|
+
const hasStatsHeading = !!(statsTitle || statsIcon);
|
|
2064
2461
|
return /* @__PURE__ */ jsxs("header", { className: "ra-header", children: [
|
|
2065
2462
|
/* @__PURE__ */ jsxs("div", { className: "ra-header__main", children: [
|
|
2066
2463
|
iconNode ? /* @__PURE__ */ jsx("div", { className: "ra-header-icon", "aria-hidden": "true", children: iconNode }) : null,
|
|
@@ -2070,17 +2467,86 @@ function ShellHeader({
|
|
|
2070
2467
|
] })
|
|
2071
2468
|
] }),
|
|
2072
2469
|
/* @__PURE__ */ jsxs("div", { className: "ra-header-aside", children: [
|
|
2073
|
-
hasStats ? /* @__PURE__ */
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2470
|
+
hasStats ? /* @__PURE__ */ jsxs(
|
|
2471
|
+
"div",
|
|
2472
|
+
{
|
|
2473
|
+
className: `ra-header-stats${hasStatsHeading ? " ra-header-stats--titled" : ""}`,
|
|
2474
|
+
role: "group",
|
|
2475
|
+
"aria-label": statsTitle ?? "Record counts",
|
|
2476
|
+
children: [
|
|
2477
|
+
hasStatsHeading ? /* @__PURE__ */ jsxs("div", { className: "ra-stats-heading", children: [
|
|
2478
|
+
statsIcon ? /* @__PURE__ */ jsx("span", { className: "ra-stats-heading-icon", "aria-hidden": "true", children: statsIcon }) : null,
|
|
2479
|
+
statsTitle ? /* @__PURE__ */ jsx("span", { className: "ra-stats-heading-label", children: statsTitle }) : null
|
|
2480
|
+
] }) : null,
|
|
2481
|
+
/* @__PURE__ */ jsx("div", { className: "ra-stats-items", children: resolvedItems.map((item, idx) => /* @__PURE__ */ jsxs("span", { style: { display: "contents" }, children: [
|
|
2482
|
+
idx > 0 && /* @__PURE__ */ jsx("span", { className: "ra-stat-divider", "aria-hidden": "true" }),
|
|
2483
|
+
/* @__PURE__ */ jsxs("span", { className: "ra-stat", children: [
|
|
2484
|
+
/* @__PURE__ */ jsx("span", { className: "ra-stat-value", children: item.value }),
|
|
2485
|
+
/* @__PURE__ */ jsx("span", { className: "ra-stat-label", children: item.label })
|
|
2486
|
+
] })
|
|
2487
|
+
] }, `${item.label}-${idx}`)) })
|
|
2488
|
+
]
|
|
2489
|
+
}
|
|
2490
|
+
) : null,
|
|
2080
2491
|
headerActions ? /* @__PURE__ */ jsx("div", { className: "ra-header-actions", children: headerActions }) : null
|
|
2081
2492
|
] })
|
|
2082
2493
|
] });
|
|
2083
2494
|
}
|
|
2495
|
+
var UnsavedBanner = ({
|
|
2496
|
+
label,
|
|
2497
|
+
context,
|
|
2498
|
+
isSaving,
|
|
2499
|
+
saveError,
|
|
2500
|
+
onSave,
|
|
2501
|
+
onDiscard,
|
|
2502
|
+
saveLabel,
|
|
2503
|
+
discardLabel,
|
|
2504
|
+
bodyTemplate,
|
|
2505
|
+
savingLabel,
|
|
2506
|
+
errorLabel
|
|
2507
|
+
}) => {
|
|
2508
|
+
const name = label ?? context ?? "this record";
|
|
2509
|
+
const message = bodyTemplate.replace("{name}", name);
|
|
2510
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-unsaved-banner", role: "status", "aria-live": "polite", children: [
|
|
2511
|
+
/* @__PURE__ */ jsx("span", { className: "ra-unsaved-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AlertCircle, { className: "w-3.5 h-3.5" }) }),
|
|
2512
|
+
/* @__PURE__ */ jsxs("span", { className: "ra-unsaved-text", children: [
|
|
2513
|
+
message,
|
|
2514
|
+
context && label && /* @__PURE__ */ jsxs("span", { className: "ra-unsaved-context", children: [
|
|
2515
|
+
" \xB7 ",
|
|
2516
|
+
context
|
|
2517
|
+
] })
|
|
2518
|
+
] }),
|
|
2519
|
+
saveError != null && !isSaving && /* @__PURE__ */ jsx("span", { className: "ra-unsaved-error", role: "alert", children: errorLabel ?? "Save failed" }),
|
|
2520
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-unsaved-actions", children: [
|
|
2521
|
+
/* @__PURE__ */ jsxs(
|
|
2522
|
+
"button",
|
|
2523
|
+
{
|
|
2524
|
+
type: "button",
|
|
2525
|
+
className: "ra-unsaved-btn ra-unsaved-btn-ghost",
|
|
2526
|
+
onClick: onDiscard,
|
|
2527
|
+
disabled: isSaving,
|
|
2528
|
+
children: [
|
|
2529
|
+
/* @__PURE__ */ jsx(Undo2, { className: "w-3 h-3" }),
|
|
2530
|
+
discardLabel
|
|
2531
|
+
]
|
|
2532
|
+
}
|
|
2533
|
+
),
|
|
2534
|
+
/* @__PURE__ */ jsxs(
|
|
2535
|
+
"button",
|
|
2536
|
+
{
|
|
2537
|
+
type: "button",
|
|
2538
|
+
className: "ra-unsaved-btn ra-unsaved-btn-primary",
|
|
2539
|
+
onClick: onSave,
|
|
2540
|
+
disabled: isSaving,
|
|
2541
|
+
children: [
|
|
2542
|
+
/* @__PURE__ */ jsx(Save, { className: "w-3 h-3" }),
|
|
2543
|
+
isSaving ? savingLabel ?? "Saving\u2026" : saveLabel
|
|
2544
|
+
]
|
|
2545
|
+
}
|
|
2546
|
+
)
|
|
2547
|
+
] })
|
|
2548
|
+
] });
|
|
2549
|
+
};
|
|
2084
2550
|
|
|
2085
2551
|
// src/components/RecordsAdmin/data/csv.ts
|
|
2086
2552
|
var escapeCell = (s) => {
|
|
@@ -2190,8 +2656,8 @@ var downloadBlob = (blob, filename) => {
|
|
|
2190
2656
|
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');
|
|
2191
2657
|
|
|
2192
2658
|
// src/components/RecordsAdmin/shell/shell.css
|
|
2193
|
-
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-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: 30;\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");
|
|
2194
|
-
var TOP_LEVEL_SCOPES = ["
|
|
2659
|
+
styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(--ra-page-bg));\n font-family: var(--ra-font-ui);\n}\n.ra-shell *,\n.ra-shell *::before,\n.ra-shell *::after {\n box-sizing: border-box;\n}\n.ra-shell .ra-card {\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-card-hover {\n transition:\n box-shadow .18s ease,\n transform .18s ease,\n border-color .18s ease;\n}\n.ra-shell .ra-card-hover:hover {\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-display {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-title {\n font-weight: var(--ra-title-weight);\n}\n.ra-shell :where(button, [role=button], input, select, textarea, a):focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n border-radius: calc(var(--ra-radius) * 0.6);\n}\n.ra-shell .ra-header {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.65rem 0.9rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-accent) / 0.12);\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.08),\n hsl(var(--ra-accent) / 0.02) 60%,\n hsl(var(--ra-surface)) 100%);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-header__main {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n.ra-shell .ra-header-aside {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-header-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: calc(var(--ra-radius) * 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n border: 1px solid hsl(var(--ra-accent) / 0.18);\n}\n.ra-shell .ra-header-text {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-header-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n line-height: 1.2;\n color: hsl(var(--ra-text));\n letter-spacing: -0.01em;\n margin: 0;\n}\n.ra-shell .ra-header-subtitle {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-header-stats {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n padding: 0.15rem 0.4rem;\n border-radius: calc(var(--ra-radius) * 0.75);\n background: hsl(var(--ra-surface) / 0.7);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-header-stats--titled {\n flex-direction: column;\n align-items: stretch;\n padding: 0.4rem 0.55rem;\n gap: 0.3rem;\n}\n.ra-shell .ra-header-stats .ra-stats-items {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n}\n.ra-shell .ra-header-stats .ra-stats-heading {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n color: hsl(var(--ra-muted-text));\n font-size: 0.65rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon {\n display: inline-flex;\n align-items: center;\n color: hsl(var(--ra-text));\n opacity: 0.75;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon > svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0.15rem 0.45rem;\n min-width: 2.5rem;\n}\n.ra-shell .ra-stat-value {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n line-height: 1;\n}\n.ra-shell .ra-stat-label {\n font-size: 0.6rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-stat-divider {\n width: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-header-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.ra-shell .ra-tabs {\n display: flex;\n gap: 0.25rem;\n padding: 0.25rem;\n background: hsl(var(--ra-muted));\n border-radius: calc(var(--ra-radius) * 0.85);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-tab {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.7rem;\n border-radius: calc(var(--ra-radius) * 0.65);\n font-size: 0.78rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n transition:\n background .15s ease,\n color .15s ease,\n transform .15s ease;\n white-space: nowrap;\n}\n.ra-shell .ra-tab:hover {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-tab[aria-selected=true] {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n box-shadow: var(--ra-card-shadow);\n font-weight: var(--ra-title-weight);\n}\n.ra-shell .ra-tab[aria-selected=true] .ra-tab-icon {\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-tab[disabled] {\n opacity: .5;\n cursor: not-allowed;\n}\n.ra-shell .ra-tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 0.35rem;\n height: 1.1rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n font-size: 0.625rem;\n font-weight: 600;\n line-height: 1;\n}\n.ra-shell .ra-tab[aria-selected=false] .ra-tab-count {\n background: hsl(var(--ra-muted-text) / 0.15);\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.4rem;\n}\n.ra-shell[data-density=compact] .ra-header {\n padding: 0.75rem 1rem;\n}\n.ra-shell[data-density=compact] .ra-header-icon {\n width: 2.25rem;\n height: 2.25rem;\n}\n.ra-shell .ra-row {\n display: flex;\n align-items: center;\n gap: 0.65rem;\n width: 100%;\n text-align: left;\n padding: 0.65rem 0.85rem;\n border-left: 3px solid transparent;\n background: transparent;\n border-bottom: 1px solid transparent;\n transition: background .12s ease, border-color .12s ease;\n cursor: pointer;\n color: hsl(var(--ra-text));\n font-family: inherit;\n}\n.ra-shell .ra-row + .ra-row {\n border-top: 1px solid hsl(var(--ra-border) / 0.6);\n}\n.ra-shell .ra-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n border-left-color: var(--ra-row-active-bd);\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-icon {\n background: hsl(var(--ra-accent) / 0.15);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-row-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n line-height: 1.25;\n color: hsl(var(--ra-text));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-actions {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n margin-left: auto;\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-row:hover .ra-row-actions,\n.ra-shell .ra-row:focus-within .ra-row-actions {\n opacity: 1;\n}\n.ra-shell .ra-row-action {\n width: 1.6rem;\n height: 1.6rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .15s ease, color .15s ease;\n}\n.ra-shell .ra-row-action:hover {\n background: hsl(var(--ra-accent) / 0.10);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-action[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.12);\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0.15rem 0.5rem;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 500;\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n white-space: nowrap;\n max-width: 14rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-chip[data-tone=success] {\n background: hsl(var(--ra-success) / 0.12);\n color: hsl(var(--ra-success));\n border-color: hsl(var(--ra-success) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=warning] {\n background: hsl(var(--ra-warning) / 0.14);\n color: hsl(var(--ra-warning));\n border-color: hsl(var(--ra-warning) / 0.35);\n}\n.ra-shell .ra-chip[data-tone=info] {\n background: hsl(var(--ra-info) / 0.10);\n color: hsl(var(--ra-info));\n border-color: hsl(var(--ra-info) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=danger] {\n background: hsl(var(--ra-danger) / 0.10);\n color: hsl(var(--ra-danger));\n border-color: hsl(var(--ra-danger) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=muted] {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-style: dashed;\n}\n.ra-shell .ra-group {\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-group:last-child {\n border-bottom: 0;\n}\n.ra-shell .ra-group-summary {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.6);\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-group-summary:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-group-summary .ra-group-chevron {\n transition: transform .15s ease;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-chevron {\n transform: rotate(-90deg);\n}\n.ra-shell .ra-group-name {\n flex: 1;\n text-align: left;\n}\n.ra-shell .ra-group-count {\n font-size: 0.65rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.4rem;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-body {\n display: none;\n}\n.ra-shell .ra-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2.5rem 1.5rem;\n gap: 0.75rem;\n}\n.ra-shell .ra-empty-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.08);\n color: hsl(var(--ra-accent));\n margin-bottom: 0.25rem;\n}\n.ra-shell .ra-empty-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n color: hsl(var(--ra-text));\n margin: 0;\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-empty-body {\n font-size: 0.8125rem;\n color: hsl(var(--ra-muted-text));\n max-width: 22rem;\n line-height: 1.45;\n}\n.ra-shell .ra-empty-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n flex-wrap: wrap;\n justify-content: center;\n}\n.ra-shell .ra-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.45rem 0.85rem;\n border-radius: calc(var(--ra-radius) * 0.7);\n font-size: 0.8125rem;\n font-weight: 500;\n border: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n cursor: pointer;\n transition:\n background .15s ease,\n border-color .15s ease,\n box-shadow .15s ease,\n transform .1s ease;\n}\n.ra-shell .ra-btn:hover {\n background: hsl(var(--ra-muted));\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-btn:active {\n transform: translateY(1px);\n}\n.ra-shell .ra-btn[data-variant=primary] {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-surface));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-btn[data-variant=primary]:hover {\n background: hsl(var(--ra-accent) / 0.92);\n}\n.ra-shell .ra-btn[data-variant=ghost] {\n background: transparent;\n border-color: transparent;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-btn[data-variant=ghost]:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-btn[data-variant=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-btn[data-variant=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n border-color: hsl(var(--ra-danger) / 0.40);\n}\n.ra-shell .ra-intro {\n position: relative;\n display: flex;\n gap: 0.85rem;\n padding: 0.9rem 1rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-info) / 0.30);\n background: hsl(var(--ra-info) / 0.08);\n margin-bottom: 1rem;\n}\n.ra-shell .ra-intro[data-tone=success] {\n border-color: hsl(var(--ra-success) / 0.30);\n background: hsl(var(--ra-success) / 0.08);\n}\n.ra-shell .ra-intro[data-tone=warning] {\n border-color: hsl(var(--ra-warning) / 0.35);\n background: hsl(var(--ra-warning) / 0.10);\n}\n.ra-shell .ra-intro-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-info) / 0.18);\n color: hsl(var(--ra-info));\n}\n.ra-shell .ra-intro[data-tone=success] .ra-intro-icon {\n background: hsl(var(--ra-success) / 0.18);\n color: hsl(var(--ra-success));\n}\n.ra-shell .ra-intro[data-tone=warning] .ra-intro-icon {\n background: hsl(var(--ra-warning) / 0.20);\n color: hsl(var(--ra-warning));\n}\n.ra-shell .ra-intro-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-intro-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n color: hsl(var(--ra-text));\n margin: 0 0 0.2rem 0;\n}\n.ra-shell .ra-intro-text {\n font-size: 0.8125rem;\n color: hsl(var(--ra-text) / 0.85);\n line-height: 1.45;\n}\n.ra-shell .ra-intro-dismiss {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.6rem;\n height: 1.6rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 0;\n color: hsl(var(--ra-muted-text));\n cursor: pointer;\n}\n.ra-shell .ra-intro-dismiss:hover {\n background: hsl(var(--ra-text) / 0.06);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-bulk-menu {\n min-width: 12rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow-hover);\n padding: 0.3rem;\n z-index: 60;\n}\n.ra-shell .ra-bulk-item {\n display: flex;\n align-items: center;\n gap: 0.55rem;\n width: 100%;\n padding: 0.45rem 0.6rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-bulk-item:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-bulk-item[data-tone=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-bulk-item[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n}\n.ra-shell .ra-bulk-divider {\n height: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-preview-rail {\n background: hsl(var(--ra-surface));\n border-left: 1px solid hsl(var(--ra-border));\n box-shadow: -4px 0 16px hsl(var(--ra-accent) / 0.04);\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.ra-shell .ra-preview-rail-header {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background:\n linear-gradient(\n 180deg,\n hsl(var(--ra-surface)) 0%,\n hsl(var(--ra-surface) / 0.92) 100%);\n border-bottom: 1px solid hsl(var(--ra-border));\n backdrop-filter: blur(6px);\n}\n.ra-shell .ra-preview-rail-title {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-preview-rail-body {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n}\n.ra-confirm-root {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n}\n.ra-confirm-root .ra-confirm-backdrop {\n position: absolute;\n inset: 0;\n background: hsl(0 0% 0% / 0.45);\n backdrop-filter: blur(2px);\n animation: ra-confirm-fade .12s ease-out;\n}\n.ra-confirm-root .ra-confirm-card {\n position: relative;\n width: min(440px, 100%);\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08), 0 24px 48px -12px hsl(0 0% 0% / 0.32);\n padding: 1.25rem;\n animation: ra-confirm-pop .14s ease-out;\n}\n.ra-confirm-root .ra-confirm-header {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n margin-bottom: 0.5rem;\n}\n.ra-confirm-root .ra-confirm-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 999px;\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.12);\n color: hsl(var(--ra-warning, 38 92% 50%));\n}\n.ra-confirm-root .ra-confirm-title {\n font-family: var(--ra-font-display);\n font-weight: 600;\n font-size: 1rem;\n margin: 0;\n}\n.ra-confirm-root .ra-confirm-body {\n font-size: 0.875rem;\n color: hsl(var(--ra-muted-text));\n margin: 0 0 1.1rem;\n line-height: 1.45;\n}\n.ra-confirm-root .ra-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.ra-confirm-root .ra-confirm-btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.45rem 0.85rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease;\n}\n.ra-confirm-root .ra-confirm-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-confirm-root .ra-confirm-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-confirm-root .ra-confirm-btn-ghost:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-confirm-root .ra-confirm-btn-danger {\n background: transparent;\n color: hsl(var(--ra-danger, 0 72% 51%));\n border-color: hsl(var(--ra-danger, 0 72% 51%) / 0.45);\n}\n.ra-confirm-root .ra-confirm-btn-danger:hover {\n background: hsl(var(--ra-danger, 0 72% 51%) / 0.08);\n border-color: hsl(var(--ra-danger, 0 72% 51%));\n}\n.ra-confirm-root .ra-confirm-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-confirm-root .ra-confirm-btn-primary:hover {\n filter: brightness(0.95);\n}\n@keyframes ra-confirm-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes ra-confirm-pop {\n from {\n opacity: 0;\n transform: translateY(4px) scale(.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ra-shell .ra-unsaved-banner {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 0.75rem;\n border: 1px solid hsl(var(--ra-warning, 38 92% 50%) / 0.35);\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.08);\n border-radius: var(--ra-radius);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n animation: ra-unsaved-slide .14s ease-out;\n}\n.ra-shell .ra-unsaved-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-warning, 38 92% 50%));\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ra-shell .ra-unsaved-context {\n color: hsl(var(--ra-muted-text));\n font-weight: 400;\n}\n.ra-shell .ra-unsaved-error {\n color: hsl(var(--ra-danger, 0 72% 51%));\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: 500;\n}\n.ra-shell .ra-unsaved-actions {\n display: inline-flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.3rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease,\n opacity .12s ease;\n}\n.ra-shell .ra-unsaved-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ra-shell .ra-unsaved-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-shell .ra-unsaved-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-shell .ra-unsaved-btn-ghost:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-unsaved-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-unsaved-btn-primary:hover:not(:disabled) {\n filter: brightness(0.95);\n}\n@keyframes ra-unsaved-slide {\n from {\n opacity: 0;\n transform: translateY(-3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n");
|
|
2660
|
+
var TOP_LEVEL_SCOPES = ["facet", "product"];
|
|
2195
2661
|
var defaultItemId = () => {
|
|
2196
2662
|
const time = Date.now().toString(36);
|
|
2197
2663
|
const rand = Math.random().toString(36).slice(2, 8);
|
|
@@ -2230,7 +2696,11 @@ function RecordsAdminShell(props) {
|
|
|
2230
2696
|
className,
|
|
2231
2697
|
previewMode = "inline",
|
|
2232
2698
|
previewScopePicker = false,
|
|
2233
|
-
|
|
2699
|
+
// Default to `keep` — admins can tab around freely while edits are
|
|
2700
|
+
// preserved per editor mount, and the inline UnsavedBanner surfaces the
|
|
2701
|
+
// dirty state at the top of the shell with Save/Discard buttons. Hosts
|
|
2702
|
+
// that want the old blocking behaviour can opt back into `'prompt'`.
|
|
2703
|
+
dirtyStrategy = "keep",
|
|
2234
2704
|
onBeforeDelete,
|
|
2235
2705
|
disableBeforeUnload = false,
|
|
2236
2706
|
presentations = ["list"],
|
|
@@ -2248,6 +2718,9 @@ function RecordsAdminShell(props) {
|
|
|
2248
2718
|
showStats = false,
|
|
2249
2719
|
showHeaderIcon = true,
|
|
2250
2720
|
statsItems,
|
|
2721
|
+
statsTitle,
|
|
2722
|
+
statsIcon,
|
|
2723
|
+
showHeader,
|
|
2251
2724
|
icons: iconsOverride,
|
|
2252
2725
|
groupBy,
|
|
2253
2726
|
renderEmptyState,
|
|
@@ -2271,7 +2744,7 @@ function RecordsAdminShell(props) {
|
|
|
2271
2744
|
);
|
|
2272
2745
|
const probe = useScopeProbe({ SL, collectionId });
|
|
2273
2746
|
const topLevelScopes = useMemo(
|
|
2274
|
-
() =>
|
|
2747
|
+
() => TOP_LEVEL_SCOPES.filter((s) => requestedScopes.includes(s)),
|
|
2275
2748
|
[requestedScopes]
|
|
2276
2749
|
);
|
|
2277
2750
|
const drillVariantsAllowed = useMemo(
|
|
@@ -2285,6 +2758,7 @@ function RecordsAdminShell(props) {
|
|
|
2285
2758
|
const initialScope = useMemo(() => {
|
|
2286
2759
|
if (contextScope?.productId && topLevelScopes.includes("product")) return "product";
|
|
2287
2760
|
if (defaultScope && topLevelScopes.includes(defaultScope)) return defaultScope;
|
|
2761
|
+
if (topLevelScopes.includes("facet")) return "facet";
|
|
2288
2762
|
return topLevelScopes[0] ?? "product";
|
|
2289
2763
|
}, [contextScope?.productId, defaultScope, topLevelScopes]);
|
|
2290
2764
|
const [activeScope, setActiveScope] = useState(initialScope);
|
|
@@ -2337,6 +2811,14 @@ function RecordsAdminShell(props) {
|
|
|
2337
2811
|
contextScope,
|
|
2338
2812
|
enabled: activeScope === "facet" && !probe.isLoading
|
|
2339
2813
|
});
|
|
2814
|
+
const facetBrowse = useFacetBrowse({
|
|
2815
|
+
SL,
|
|
2816
|
+
collectionId,
|
|
2817
|
+
existing: recordList.allItems,
|
|
2818
|
+
search,
|
|
2819
|
+
filter,
|
|
2820
|
+
enabled: activeScope === "facet" && !probe.isLoading
|
|
2821
|
+
});
|
|
2340
2822
|
const variantChildren = useProductChildren({
|
|
2341
2823
|
SL,
|
|
2342
2824
|
collectionId,
|
|
@@ -2358,9 +2840,9 @@ function RecordsAdminShell(props) {
|
|
|
2358
2840
|
useEffect(() => {
|
|
2359
2841
|
if (activeScope !== "facet") return;
|
|
2360
2842
|
if (selectedFacetRef) return;
|
|
2361
|
-
const first =
|
|
2843
|
+
const first = facetBrowse.items[0];
|
|
2362
2844
|
if (first) setSelectedFacetRef(first.ref);
|
|
2363
|
-
}, [activeScope, selectedFacetRef,
|
|
2845
|
+
}, [activeScope, selectedFacetRef, facetBrowse.items]);
|
|
2364
2846
|
useEffect(() => {
|
|
2365
2847
|
setSearch("");
|
|
2366
2848
|
setFilter("all");
|
|
@@ -2397,9 +2879,10 @@ function RecordsAdminShell(props) {
|
|
|
2397
2879
|
const refetchAll = useCallback(() => {
|
|
2398
2880
|
productBrowse.refetch();
|
|
2399
2881
|
recordList.refetch();
|
|
2882
|
+
facetBrowse.refetch();
|
|
2400
2883
|
variantChildren.refetch();
|
|
2401
2884
|
batchChildren.refetch();
|
|
2402
|
-
}, [productBrowse, recordList, variantChildren, batchChildren]);
|
|
2885
|
+
}, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren]);
|
|
2403
2886
|
const editorCtx = useRecordEditor({
|
|
2404
2887
|
ctx,
|
|
2405
2888
|
scope: editingScope ?? parseRef(""),
|
|
@@ -2425,13 +2908,19 @@ function RecordsAdminShell(props) {
|
|
|
2425
2908
|
useUnsavedGuard({
|
|
2426
2909
|
isDirty: editorCtx.isDirty,
|
|
2427
2910
|
label: recordType,
|
|
2428
|
-
disableBeforeUnload
|
|
2911
|
+
disableBeforeUnload,
|
|
2912
|
+
// In `keep` mode we don't want the host iframe to pop its own native
|
|
2913
|
+
// confirm — the banner is the canonical surface. Hosts on `prompt` /
|
|
2914
|
+
// `autosave` opt back into platform notifications.
|
|
2915
|
+
disableParentMessage: dirtyStrategy === "keep"
|
|
2429
2916
|
});
|
|
2917
|
+
const dirtyConfirm = useConfirmDialog();
|
|
2430
2918
|
const { runWithGuard } = useDirtyNavigation({
|
|
2431
2919
|
strategy: dirtyStrategy,
|
|
2432
2920
|
isDirty: editorCtx.isDirty,
|
|
2433
2921
|
save: editorCtx.save,
|
|
2434
2922
|
reset: editorCtx.reset,
|
|
2923
|
+
confirm: dirtyConfirm.confirm,
|
|
2435
2924
|
i18n: {
|
|
2436
2925
|
title: i18n.unsavedPromptTitle,
|
|
2437
2926
|
body: i18n.unsavedPromptBody,
|
|
@@ -2468,11 +2957,40 @@ function RecordsAdminShell(props) {
|
|
|
2468
2957
|
const csvBulk = csvSchema ? { onImportCsv: handleImport, onExportCsv: handleExport } : {};
|
|
2469
2958
|
const [previewScope, setPreviewScope] = useState(null);
|
|
2470
2959
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
2960
|
+
const [sidePreviewOpen, setSidePreviewOpen] = useState(true);
|
|
2471
2961
|
useEffect(() => {
|
|
2472
2962
|
if (!editingScope) return;
|
|
2473
2963
|
setPreviewScope((cur) => cur === null ? editingScope : cur);
|
|
2474
2964
|
}, [editingScope]);
|
|
2475
2965
|
const effectivePreviewScope = previewScope ?? editingScope;
|
|
2966
|
+
const editorHeaderLabel = useMemo(() => {
|
|
2967
|
+
if (!editingScope) return void 0;
|
|
2968
|
+
if (activeScope === "facet" && selectedFacetRef) {
|
|
2969
|
+
const hit = facetBrowse.items.find((it) => it.ref === selectedFacetRef);
|
|
2970
|
+
return hit?.label;
|
|
2971
|
+
}
|
|
2972
|
+
if (activeScope === "product" && selectedProductId) {
|
|
2973
|
+
const hit = productBrowse.items.find((it) => it.id === selectedProductId);
|
|
2974
|
+
return hit?.name ?? selectedProductId;
|
|
2975
|
+
}
|
|
2976
|
+
return void 0;
|
|
2977
|
+
}, [activeScope, editingScope, selectedFacetRef, selectedProductId, facetBrowse.items, productBrowse.items]);
|
|
2978
|
+
const editorHeaderSubtitle = useMemo(() => {
|
|
2979
|
+
if (!editingScope) return void 0;
|
|
2980
|
+
if (activeScope === "facet" && selectedFacetRef) {
|
|
2981
|
+
const hit = facetBrowse.items.find((it) => it.ref === selectedFacetRef);
|
|
2982
|
+
return hit?.subtitle;
|
|
2983
|
+
}
|
|
2984
|
+
return void 0;
|
|
2985
|
+
}, [activeScope, editingScope, selectedFacetRef, selectedProductId, facetBrowse.items, productBrowse.items]);
|
|
2986
|
+
const editorHeaderMeta = useMemo(() => {
|
|
2987
|
+
if (!editingScope) return void 0;
|
|
2988
|
+
if (activeScope === "product" && selectedProductId) {
|
|
2989
|
+
const hit = productBrowse.items.find((it) => it.id === selectedProductId);
|
|
2990
|
+
return hit?.sku ?? selectedProductId;
|
|
2991
|
+
}
|
|
2992
|
+
return void 0;
|
|
2993
|
+
}, [activeScope, editingScope, selectedProductId, productBrowse.items]);
|
|
2476
2994
|
const renderEditorWithPreview = () => {
|
|
2477
2995
|
if (!editingScope) return null;
|
|
2478
2996
|
const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
|
|
@@ -2498,6 +3016,9 @@ function RecordsAdminShell(props) {
|
|
|
2498
3016
|
preview: inlinePreviewBody,
|
|
2499
3017
|
footerExtra: extraFooter,
|
|
2500
3018
|
onBeforeDelete: onBeforeDelete && editingScope ? () => onBeforeDelete(editingScope) : void 0,
|
|
3019
|
+
headerLabel: editorHeaderLabel,
|
|
3020
|
+
headerSubtitle: editorHeaderSubtitle,
|
|
3021
|
+
headerMeta: editorHeaderMeta,
|
|
2501
3022
|
children: renderEditor(editorCtx)
|
|
2502
3023
|
}
|
|
2503
3024
|
);
|
|
@@ -2509,9 +3030,28 @@ function RecordsAdminShell(props) {
|
|
|
2509
3030
|
);
|
|
2510
3031
|
}
|
|
2511
3032
|
if (previewMode === "side") {
|
|
3033
|
+
if (!sidePreviewOpen) {
|
|
3034
|
+
return /* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
|
|
3035
|
+
/* @__PURE__ */ jsx(
|
|
3036
|
+
PreviewToggleButton,
|
|
3037
|
+
{
|
|
3038
|
+
onClick: () => setSidePreviewOpen(true),
|
|
3039
|
+
label: i18n.openPreview
|
|
3040
|
+
}
|
|
3041
|
+
)
|
|
3042
|
+
) });
|
|
3043
|
+
}
|
|
2512
3044
|
return /* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
|
|
2513
3045
|
/* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
|
|
2514
|
-
/* @__PURE__ */ jsx(
|
|
3046
|
+
/* @__PURE__ */ jsx(
|
|
3047
|
+
SidePreview,
|
|
3048
|
+
{
|
|
3049
|
+
label: i18n.preview,
|
|
3050
|
+
scopePicker,
|
|
3051
|
+
onClose: () => setSidePreviewOpen(false),
|
|
3052
|
+
children: previewBody
|
|
3053
|
+
}
|
|
3054
|
+
)
|
|
2515
3055
|
] });
|
|
2516
3056
|
}
|
|
2517
3057
|
if (previewMode === "tab") {
|
|
@@ -2543,6 +3083,18 @@ function RecordsAdminShell(props) {
|
|
|
2543
3083
|
};
|
|
2544
3084
|
const isProductTab = activeScope === "product";
|
|
2545
3085
|
const productPinned = !!contextScope?.productId;
|
|
3086
|
+
const effectivePresentation = isProductTab ? presentation : "list";
|
|
3087
|
+
const showPresentationSwitcher = isProductTab && presentations.length > 1;
|
|
3088
|
+
const effectiveGroupBy = useMemo(() => {
|
|
3089
|
+
if (groupBy) return groupBy;
|
|
3090
|
+
if (isProductTab) return void 0;
|
|
3091
|
+
return (record) => {
|
|
3092
|
+
const key = record.scope.facetId;
|
|
3093
|
+
if (!key) return null;
|
|
3094
|
+
const label2 = record.subtitle ?? key;
|
|
3095
|
+
return { key, label: label2 };
|
|
3096
|
+
};
|
|
3097
|
+
}, [groupBy, isProductTab]);
|
|
2546
3098
|
const productListItems = useMemo(() => {
|
|
2547
3099
|
if (productPinned) {
|
|
2548
3100
|
return [{
|
|
@@ -2557,9 +3109,9 @@ function RecordsAdminShell(props) {
|
|
|
2557
3109
|
}
|
|
2558
3110
|
return productBrowse.items.map(productItemToSummary);
|
|
2559
3111
|
}, [productPinned, contextScope, productBrowse.items]);
|
|
2560
|
-
const leftItems = isProductTab ? productListItems :
|
|
2561
|
-
const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : recordList.isLoading || probe.isLoading;
|
|
2562
|
-
const leftError = isProductTab ? productBrowse.error : recordList.error;
|
|
3112
|
+
const leftItems = isProductTab ? productListItems : facetBrowse.items;
|
|
3113
|
+
const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : facetBrowse.isLoading || recordList.isLoading || probe.isLoading;
|
|
3114
|
+
const leftError = isProductTab ? productBrowse.error : facetBrowse.error ?? recordList.error;
|
|
2563
3115
|
const leftSelectedRef = isProductTab ? selectedProductId ? buildRef({ productId: selectedProductId }) : void 0 : selectedFacetRef;
|
|
2564
3116
|
const onLeftSelect = (item) => {
|
|
2565
3117
|
void runWithGuard(() => {
|
|
@@ -2579,6 +3131,7 @@ function RecordsAdminShell(props) {
|
|
|
2579
3131
|
className: `ra-shell flex flex-col h-full ${className ?? ""}`,
|
|
2580
3132
|
"data-density": density,
|
|
2581
3133
|
children: [
|
|
3134
|
+
dirtyConfirm.dialog,
|
|
2582
3135
|
/* @__PURE__ */ jsxs("div", { className: "px-4 pt-4 space-y-3", children: [
|
|
2583
3136
|
intro && !dismissed && /* @__PURE__ */ jsx(
|
|
2584
3137
|
IntroCard,
|
|
@@ -2591,24 +3144,31 @@ function RecordsAdminShell(props) {
|
|
|
2591
3144
|
}
|
|
2592
3145
|
}
|
|
2593
3146
|
),
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
3147
|
+
(() => {
|
|
3148
|
+
const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
|
|
3149
|
+
const renderHeader = showHeader === true || showHeader !== false && headerCustomised;
|
|
3150
|
+
if (!renderHeader) return null;
|
|
3151
|
+
return /* @__PURE__ */ jsx(
|
|
3152
|
+
ShellHeader,
|
|
3153
|
+
{
|
|
3154
|
+
title: title ?? label ?? recordType ?? "",
|
|
3155
|
+
subtitle,
|
|
3156
|
+
headerIcon,
|
|
3157
|
+
headerActions,
|
|
3158
|
+
showStats,
|
|
3159
|
+
showHeaderIcon,
|
|
3160
|
+
recordType,
|
|
3161
|
+
icons,
|
|
3162
|
+
stats: {
|
|
3163
|
+
products: productBrowse.items.length,
|
|
3164
|
+
shared: recordList.items.length
|
|
3165
|
+
},
|
|
3166
|
+
statsItems,
|
|
3167
|
+
statsTitle,
|
|
3168
|
+
statsIcon
|
|
3169
|
+
}
|
|
3170
|
+
);
|
|
3171
|
+
})(),
|
|
2612
3172
|
/* @__PURE__ */ jsx(
|
|
2613
3173
|
UtilityRow,
|
|
2614
3174
|
{
|
|
@@ -2616,6 +3176,25 @@ function RecordsAdminShell(props) {
|
|
|
2616
3176
|
introHidden: dismissed && !!intro,
|
|
2617
3177
|
onShowIntro: undismiss
|
|
2618
3178
|
}
|
|
3179
|
+
),
|
|
3180
|
+
editorCtx.isDirty && /* @__PURE__ */ jsx(
|
|
3181
|
+
UnsavedBanner,
|
|
3182
|
+
{
|
|
3183
|
+
label: editorHeaderLabel,
|
|
3184
|
+
context: editorHeaderSubtitle,
|
|
3185
|
+
isSaving: !!editorCtx.isSaving,
|
|
3186
|
+
saveError: editorCtx.saveError,
|
|
3187
|
+
onSave: () => {
|
|
3188
|
+
void editorCtx.save().catch(() => {
|
|
3189
|
+
});
|
|
3190
|
+
},
|
|
3191
|
+
onDiscard: editorCtx.reset,
|
|
3192
|
+
saveLabel: i18n.save,
|
|
3193
|
+
discardLabel: i18n.discard,
|
|
3194
|
+
savingLabel: i18n.saving,
|
|
3195
|
+
errorLabel: i18n.saveError,
|
|
3196
|
+
bodyTemplate: i18n.unsavedBannerBody
|
|
3197
|
+
}
|
|
2619
3198
|
)
|
|
2620
3199
|
] }),
|
|
2621
3200
|
/* @__PURE__ */ jsxs(
|
|
@@ -2639,7 +3218,7 @@ function RecordsAdminShell(props) {
|
|
|
2639
3218
|
loading: probe.isLoading,
|
|
2640
3219
|
counts: {
|
|
2641
3220
|
product: productBrowse.items.length,
|
|
2642
|
-
facet:
|
|
3221
|
+
facet: facetBrowse.items.length
|
|
2643
3222
|
},
|
|
2644
3223
|
icons: icons.scope
|
|
2645
3224
|
}
|
|
@@ -2663,14 +3242,23 @@ function RecordsAdminShell(props) {
|
|
|
2663
3242
|
/* @__PURE__ */ jsx(
|
|
2664
3243
|
PresentationSwitcher,
|
|
2665
3244
|
{
|
|
2666
|
-
options: presentations,
|
|
3245
|
+
options: showPresentationSwitcher ? presentations : [],
|
|
2667
3246
|
value: presentation,
|
|
2668
3247
|
onChange: onPresentationChange,
|
|
2669
3248
|
i18n
|
|
2670
3249
|
}
|
|
2671
3250
|
)
|
|
2672
3251
|
] }),
|
|
2673
|
-
!isProductTab && /* @__PURE__ */ jsx(
|
|
3252
|
+
!isProductTab && /* @__PURE__ */ jsx(
|
|
3253
|
+
StatusFilterPills,
|
|
3254
|
+
{
|
|
3255
|
+
value: filter,
|
|
3256
|
+
onChange: setFilter,
|
|
3257
|
+
counts: facetBrowse.counts,
|
|
3258
|
+
hideZero: ["partial"],
|
|
3259
|
+
i18n
|
|
3260
|
+
}
|
|
3261
|
+
),
|
|
2674
3262
|
cardinality === "collection" && !isProductTab && editingScope && /* @__PURE__ */ jsxs(
|
|
2675
3263
|
"button",
|
|
2676
3264
|
{
|
|
@@ -2712,10 +3300,10 @@ function RecordsAdminShell(props) {
|
|
|
2712
3300
|
selectedRef: leftSelectedRef,
|
|
2713
3301
|
onSelect: onLeftSelect,
|
|
2714
3302
|
dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
|
|
2715
|
-
presentation,
|
|
3303
|
+
presentation: effectivePresentation,
|
|
2716
3304
|
renderListRow,
|
|
2717
3305
|
renderCard,
|
|
2718
|
-
groupBy
|
|
3306
|
+
groupBy: effectiveGroupBy
|
|
2719
3307
|
}
|
|
2720
3308
|
),
|
|
2721
3309
|
isProductTab && !productPinned && productBrowse.hasNextPage && /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
|
|
@@ -3175,6 +3763,6 @@ function useMergedRecord(args) {
|
|
|
3175
3763
|
};
|
|
3176
3764
|
}
|
|
3177
3765
|
|
|
3178
|
-
export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_I18N, DEFAULT_ICONS, DefaultRecordCard, DefaultRecordRow, DeleteButton, DrawerPreview, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SidePreview, StatusDot, StatusFilterPills, TabbedPreview, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
|
|
3766
|
+
export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_I18N, DEFAULT_ICONS, DefaultRecordCard, DefaultRecordRow, DeleteButton, DrawerPreview, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SidePreview, StatusDot, StatusFilterPills, TabbedPreview, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
|
|
3179
3767
|
//# sourceMappingURL=index.js.map
|
|
3180
3768
|
//# sourceMappingURL=index.js.map
|