@proveanything/smartlinks-utils-ui 0.10.0 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AssetPicker/index.css +72 -7
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +72 -7
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +72 -7
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +72 -7
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +72 -7
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +27 -3
- package/dist/components/RecordsAdmin/index.js +221 -90
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +72 -7
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
|
@@ -2055,6 +2055,15 @@ declare const useProductBrowse: (args: UseProductBrowseArgs) => {
|
|
|
2055
2055
|
refetch: () => Promise<void>;
|
|
2056
2056
|
};
|
|
2057
2057
|
|
|
2058
|
+
interface FacetValueShape {
|
|
2059
|
+
key?: string;
|
|
2060
|
+
name?: string;
|
|
2061
|
+
}
|
|
2062
|
+
interface FacetShape {
|
|
2063
|
+
key?: string;
|
|
2064
|
+
name?: string;
|
|
2065
|
+
values?: FacetValueShape[];
|
|
2066
|
+
}
|
|
2058
2067
|
interface UseFacetBrowseArgs {
|
|
2059
2068
|
SL: SmartLinksSDK;
|
|
2060
2069
|
collectionId: string;
|
|
@@ -2075,6 +2084,12 @@ declare const useFacetBrowse: ({ SL, collectionId, existing, search, filter, ena
|
|
|
2075
2084
|
isLoading: boolean;
|
|
2076
2085
|
error: Error | null;
|
|
2077
2086
|
refetch: () => void;
|
|
2087
|
+
/** Raw canonical facet vocabulary as returned by the SDK. Use this
|
|
2088
|
+
* (NOT `items`) when you need the authoritative list of facets and
|
|
2089
|
+
* their values — `items` is the record-merged list and may include
|
|
2090
|
+
* rows whose scope's `facetId` doesn't match a canonical key, which
|
|
2091
|
+
* would otherwise show up as duplicate facet groups. */
|
|
2092
|
+
vocabulary: FacetShape[];
|
|
2078
2093
|
};
|
|
2079
2094
|
|
|
2080
2095
|
interface CollectedRecord<T = unknown> {
|
|
@@ -2427,8 +2442,17 @@ interface Props<T> {
|
|
|
2427
2442
|
selectedItemId?: string;
|
|
2428
2443
|
isLoading: boolean;
|
|
2429
2444
|
error: Error | null;
|
|
2430
|
-
/**
|
|
2445
|
+
/** Back to the items list (mirrors the editor-header "Back to list"). */
|
|
2431
2446
|
onBack?: () => void;
|
|
2447
|
+
/**
|
|
2448
|
+
* Optional context label rendered next to the back arrow. Two parts:
|
|
2449
|
+
* - `kind` — short noun ("Rule", "Product", "Global", "Filtered")
|
|
2450
|
+
* - `summary` — the specific value when relevant (rule summary, product
|
|
2451
|
+
* name, …); omitted for kinds that need no qualifier.
|
|
2452
|
+
* The shell composes both from the active scope + selection.
|
|
2453
|
+
*/
|
|
2454
|
+
contextKind?: string;
|
|
2455
|
+
contextSummary?: string | null;
|
|
2432
2456
|
onSelect: (itemId: string) => void;
|
|
2433
2457
|
/**
|
|
2434
2458
|
* Set of keys (recordIds + scope refs) currently dirty in the shell-level
|
|
@@ -2439,9 +2463,9 @@ interface Props<T> {
|
|
|
2439
2463
|
dirtyKeys?: ReadonlySet<string>;
|
|
2440
2464
|
/** Subset of `dirtyKeys` whose last save attempt failed. */
|
|
2441
2465
|
errorKeys?: ReadonlySet<string>;
|
|
2442
|
-
i18n: Pick<RecordsAdminI18n, 'backToScopes' | 'siblingsHeading' | 'noItemsTitle' | 'noItemsBody'>;
|
|
2466
|
+
i18n: Pick<RecordsAdminI18n, 'backToScopes' | 'siblingsHeading' | 'noItemsTitle' | 'noItemsBody' | 'backToList'>;
|
|
2443
2467
|
}
|
|
2444
|
-
declare function SiblingRail<T>({ items, selectedItemId, isLoading, error, onSelect, dirtyKeys, errorKeys, i18n, }: Props<T>): react_jsx_runtime.JSX.Element;
|
|
2468
|
+
declare function SiblingRail<T>({ items, selectedItemId, isLoading, error, onBack, onSelect, contextKind, contextSummary, dirtyKeys, errorKeys, i18n, }: Props<T>): react_jsx_runtime.JSX.Element;
|
|
2445
2469
|
|
|
2446
2470
|
interface ClipboardEntry<T = unknown> {
|
|
2447
2471
|
value: T;
|
|
@@ -817,7 +817,13 @@ var useFacetBrowse = ({
|
|
|
817
817
|
counts,
|
|
818
818
|
isLoading: query.isLoading,
|
|
819
819
|
error: query.error ?? null,
|
|
820
|
-
refetch
|
|
820
|
+
refetch,
|
|
821
|
+
/** Raw canonical facet vocabulary as returned by the SDK. Use this
|
|
822
|
+
* (NOT `items`) when you need the authoritative list of facets and
|
|
823
|
+
* their values — `items` is the record-merged list and may include
|
|
824
|
+
* rows whose scope's `facetId` doesn't match a canonical key, which
|
|
825
|
+
* would otherwise show up as duplicate facet groups. */
|
|
826
|
+
vocabulary: query.data ?? []
|
|
821
827
|
};
|
|
822
828
|
};
|
|
823
829
|
var QK2 = ["records-admin", "product-browse"];
|
|
@@ -3697,6 +3703,8 @@ var FacetList = RecordList;
|
|
|
3697
3703
|
var VariantList = RecordList;
|
|
3698
3704
|
var BatchList = RecordList;
|
|
3699
3705
|
var COLLAPSED_FACET_CAP = 6;
|
|
3706
|
+
var COLLAPSED_VALUE_CAP = 12;
|
|
3707
|
+
var VALUE_SEARCH_THRESHOLD = 12;
|
|
3700
3708
|
function FacetBrowseFilter({
|
|
3701
3709
|
facets,
|
|
3702
3710
|
value,
|
|
@@ -3710,12 +3718,33 @@ function FacetBrowseFilter({
|
|
|
3710
3718
|
);
|
|
3711
3719
|
const [openKey, setOpenKey] = useState(value?.facetKey ?? firstUsable ?? null);
|
|
3712
3720
|
const [allExpanded, setAllExpanded] = useState(false);
|
|
3721
|
+
const [valuesExpanded, setValuesExpanded] = useState({});
|
|
3722
|
+
const [valueSearch, setValueSearch] = useState({});
|
|
3713
3723
|
const effectiveOpen = value?.facetKey ?? openKey ?? firstUsable ?? null;
|
|
3714
3724
|
if (isLoading) {
|
|
3715
3725
|
return /* @__PURE__ */ jsx("div", { className: "ra-rule-filters", "aria-busy": "true", children: /* @__PURE__ */ jsx("div", { className: "ra-rule-filters-row", children: /* @__PURE__ */ jsx("span", { className: "ra-rule-filter-chip", "data-active": "false", children: "Loading facets\u2026" }) }) });
|
|
3716
3726
|
}
|
|
3717
3727
|
if (!facets.length) return null;
|
|
3718
3728
|
const openFacet = facets.find((f) => f.key === effectiveOpen) ?? null;
|
|
3729
|
+
const openValuesExpanded = openFacet ? !!valuesExpanded[openFacet.key] : false;
|
|
3730
|
+
const openValueSearch = openFacet ? valueSearch[openFacet.key] ?? "" : "";
|
|
3731
|
+
const openValuesFiltered = useMemo(() => {
|
|
3732
|
+
if (!openFacet) return [];
|
|
3733
|
+
const q = openValueSearch.trim().toLowerCase();
|
|
3734
|
+
if (!q) return openFacet.values;
|
|
3735
|
+
return openFacet.values.filter(
|
|
3736
|
+
(v) => `${v.label ?? ""} ${v.key}`.toLowerCase().includes(q)
|
|
3737
|
+
);
|
|
3738
|
+
}, [openFacet, openValueSearch]);
|
|
3739
|
+
const valueOverflow = openFacet ? openValuesFiltered.length - COLLAPSED_VALUE_CAP : 0;
|
|
3740
|
+
const visibleValues = openFacet ? openValuesExpanded || valueOverflow <= 0 ? openValuesFiltered : (() => {
|
|
3741
|
+
const head = openValuesFiltered.slice(0, COLLAPSED_VALUE_CAP);
|
|
3742
|
+
const activeVal = value && value.facetKey === openFacet.key ? openFacet.values.find((v) => v.key === value.facetValue) : null;
|
|
3743
|
+
if (activeVal && !head.includes(activeVal)) {
|
|
3744
|
+
return [...head.slice(0, COLLAPSED_VALUE_CAP - 1), activeVal];
|
|
3745
|
+
}
|
|
3746
|
+
return head;
|
|
3747
|
+
})() : [];
|
|
3719
3748
|
const overflow = facets.length - COLLAPSED_FACET_CAP;
|
|
3720
3749
|
let visibleFacets = facets;
|
|
3721
3750
|
if (!allExpanded && overflow > 0) {
|
|
@@ -3764,30 +3793,57 @@ function FacetBrowseFilter({
|
|
|
3764
3793
|
}
|
|
3765
3794
|
)
|
|
3766
3795
|
] }),
|
|
3767
|
-
openFacet && openFacet.values.length > 0 && /* @__PURE__ */
|
|
3796
|
+
openFacet && openFacet.values.length > 0 && /* @__PURE__ */ jsxs(
|
|
3768
3797
|
"div",
|
|
3769
3798
|
{
|
|
3770
3799
|
className: "ra-rule-filters-row",
|
|
3771
3800
|
role: "group",
|
|
3772
3801
|
"aria-label": `Pick a ${openFacet.label ?? openFacet.key} value`,
|
|
3773
|
-
style: { paddingLeft: "0.25rem" },
|
|
3774
|
-
children:
|
|
3775
|
-
|
|
3776
|
-
|
|
3802
|
+
style: { paddingLeft: "0.25rem", maxHeight: "8.5rem", overflowY: "auto" },
|
|
3803
|
+
children: [
|
|
3804
|
+
openFacet.values.length > VALUE_SEARCH_THRESHOLD && /* @__PURE__ */ jsx(
|
|
3805
|
+
"input",
|
|
3806
|
+
{
|
|
3807
|
+
type: "search",
|
|
3808
|
+
value: openValueSearch,
|
|
3809
|
+
onChange: (e) => setValueSearch((s) => ({ ...s, [openFacet.key]: e.target.value })),
|
|
3810
|
+
placeholder: `Search ${openFacet.label ?? openFacet.key}\u2026`,
|
|
3811
|
+
"aria-label": `Search ${openFacet.label ?? openFacet.key} values`,
|
|
3812
|
+
className: "ra-rule-filter-chip",
|
|
3813
|
+
style: { minWidth: "8rem", writingMode: "horizontal-tb" }
|
|
3814
|
+
}
|
|
3815
|
+
),
|
|
3816
|
+
visibleValues.map((v) => {
|
|
3817
|
+
const active = value?.facetKey === openFacet.key && value?.facetValue === v.key;
|
|
3818
|
+
return /* @__PURE__ */ jsx(
|
|
3819
|
+
"button",
|
|
3820
|
+
{
|
|
3821
|
+
type: "button",
|
|
3822
|
+
className: "ra-rule-filter-chip",
|
|
3823
|
+
"data-tone": "complexity",
|
|
3824
|
+
"data-active": active ? "true" : "false",
|
|
3825
|
+
"aria-pressed": active,
|
|
3826
|
+
onClick: () => onChange(active ? null : { facetKey: openFacet.key, facetValue: v.key }),
|
|
3827
|
+
title: `Filter to ${openFacet.label ?? openFacet.key} = ${v.label ?? v.key}`,
|
|
3828
|
+
children: /* @__PURE__ */ jsx("span", { className: "ra-rule-filter-chip-label", children: v.label ?? v.key })
|
|
3829
|
+
},
|
|
3830
|
+
v.key
|
|
3831
|
+
);
|
|
3832
|
+
}),
|
|
3833
|
+
valueOverflow > 0 && /* @__PURE__ */ jsx(
|
|
3777
3834
|
"button",
|
|
3778
3835
|
{
|
|
3779
3836
|
type: "button",
|
|
3837
|
+
onClick: () => setValuesExpanded((s) => ({ ...s, [openFacet.key]: !openValuesExpanded })),
|
|
3780
3838
|
className: "ra-rule-filter-chip",
|
|
3781
|
-
"data-
|
|
3782
|
-
"
|
|
3783
|
-
"
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
);
|
|
3790
|
-
})
|
|
3839
|
+
"data-active": "false",
|
|
3840
|
+
"aria-expanded": openValuesExpanded,
|
|
3841
|
+
title: openValuesExpanded ? "Show fewer values" : `Show all ${openValuesFiltered.length} values`,
|
|
3842
|
+
children: /* @__PURE__ */ jsx("span", { className: "ra-rule-filter-chip-label", children: openValuesExpanded ? "Show fewer" : `Show all (${openValuesFiltered.length})` })
|
|
3843
|
+
}
|
|
3844
|
+
),
|
|
3845
|
+
openValuesFiltered.length === 0 && /* @__PURE__ */ jsx("span", { className: "ra-rule-filter-clear", style: { cursor: "default", textDecoration: "none" }, children: "No values match." })
|
|
3846
|
+
]
|
|
3791
3847
|
}
|
|
3792
3848
|
),
|
|
3793
3849
|
value && /* @__PURE__ */ jsx(
|
|
@@ -5950,67 +6006,92 @@ function SiblingRail({
|
|
|
5950
6006
|
selectedItemId,
|
|
5951
6007
|
isLoading,
|
|
5952
6008
|
error,
|
|
6009
|
+
onBack,
|
|
5953
6010
|
onSelect,
|
|
6011
|
+
contextKind,
|
|
6012
|
+
contextSummary,
|
|
5954
6013
|
dirtyKeys,
|
|
5955
6014
|
errorKeys,
|
|
5956
6015
|
i18n
|
|
5957
6016
|
}) {
|
|
5958
6017
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
5959
|
-
return /* @__PURE__ */
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
5963
|
-
!isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item, idx) => {
|
|
5964
|
-
const id = item.itemId ?? "";
|
|
5965
|
-
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
5966
|
-
const akey = anchorKey(item.scope);
|
|
5967
|
-
const selected = selectedItemId === id;
|
|
5968
|
-
const isDirty = !!(id && dirtyKeys?.has(id) || akey && dirtyKeys?.has(akey));
|
|
5969
|
-
const hasError = !!(id && errorKeys?.has(id) || akey && errorKeys?.has(akey));
|
|
5970
|
-
const ruleClauses = item.facetRule ? summarizeFacetRule(item.facetRule, ruleLabelLookup) : [];
|
|
5971
|
-
const isTargeted = ruleClauses.length > 0;
|
|
5972
|
-
const ruleSummary = isTargeted ? ruleClauses.map((c) => c.label).join(" \xB7 ") : null;
|
|
5973
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
6018
|
+
return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
|
|
6019
|
+
(onBack || contextKind) && /* @__PURE__ */ jsxs("div", { className: "ra-sibling-context", children: [
|
|
6020
|
+
onBack && /* @__PURE__ */ jsx(
|
|
5974
6021
|
"button",
|
|
5975
6022
|
{
|
|
5976
6023
|
type: "button",
|
|
5977
|
-
onClick:
|
|
5978
|
-
className: "ra-
|
|
5979
|
-
"
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
5983
|
-
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
5984
|
-
] }),
|
|
5985
|
-
isTargeted && /* @__PURE__ */ jsx(
|
|
5986
|
-
"span",
|
|
5987
|
-
{
|
|
5988
|
-
className: "ra-row-rule-pip",
|
|
5989
|
-
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
5990
|
-
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
5991
|
-
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
5992
|
-
}
|
|
5993
|
-
),
|
|
5994
|
-
hasError ? /* @__PURE__ */ jsx(
|
|
5995
|
-
"span",
|
|
5996
|
-
{
|
|
5997
|
-
className: "ra-error-pip",
|
|
5998
|
-
title: "Save failed",
|
|
5999
|
-
"aria-label": "Save failed"
|
|
6000
|
-
}
|
|
6001
|
-
) : isDirty ? /* @__PURE__ */ jsx(
|
|
6002
|
-
"span",
|
|
6003
|
-
{
|
|
6004
|
-
className: "ra-dirty-pip",
|
|
6005
|
-
title: "Unsaved changes",
|
|
6006
|
-
"aria-label": "Unsaved changes"
|
|
6007
|
-
}
|
|
6008
|
-
) : null
|
|
6009
|
-
]
|
|
6024
|
+
onClick: onBack,
|
|
6025
|
+
className: "ra-sibling-context-back",
|
|
6026
|
+
"aria-label": i18n.backToList,
|
|
6027
|
+
title: i18n.backToList,
|
|
6028
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5", "aria-hidden": "true" })
|
|
6010
6029
|
}
|
|
6011
|
-
)
|
|
6012
|
-
|
|
6013
|
-
|
|
6030
|
+
),
|
|
6031
|
+
contextKind && /* @__PURE__ */ jsxs("div", { className: "ra-sibling-context-label", title: contextSummary ? `${contextKind} \xB7 ${contextSummary}` : contextKind, children: [
|
|
6032
|
+
/* @__PURE__ */ jsx("span", { className: "ra-sibling-context-kind", children: contextKind }),
|
|
6033
|
+
contextSummary && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6034
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ra-sibling-context-sep", children: "\xB7" }),
|
|
6035
|
+
/* @__PURE__ */ jsx("span", { className: "ra-sibling-context-summary", children: contextSummary })
|
|
6036
|
+
] })
|
|
6037
|
+
] })
|
|
6038
|
+
] }),
|
|
6039
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-sibling-body", children: [
|
|
6040
|
+
isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
6041
|
+
!isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
|
|
6042
|
+
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
6043
|
+
!isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item, idx) => {
|
|
6044
|
+
const id = item.itemId ?? "";
|
|
6045
|
+
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
6046
|
+
const akey = anchorKey(item.scope);
|
|
6047
|
+
const selected = selectedItemId === id;
|
|
6048
|
+
const isDirty = !!(id && dirtyKeys?.has(id) || akey && dirtyKeys?.has(akey));
|
|
6049
|
+
const hasError = !!(id && errorKeys?.has(id) || akey && errorKeys?.has(akey));
|
|
6050
|
+
const ruleClauses = item.facetRule ? summarizeFacetRule(item.facetRule, ruleLabelLookup) : [];
|
|
6051
|
+
const isTargeted = ruleClauses.length > 0;
|
|
6052
|
+
const ruleSummary = isTargeted ? ruleClauses.map((c) => c.label).join(" \xB7 ") : null;
|
|
6053
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
6054
|
+
"button",
|
|
6055
|
+
{
|
|
6056
|
+
type: "button",
|
|
6057
|
+
onClick: () => onSelect(id),
|
|
6058
|
+
className: "ra-row",
|
|
6059
|
+
"data-selected": selected,
|
|
6060
|
+
children: [
|
|
6061
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
6062
|
+
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
6063
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
6064
|
+
] }),
|
|
6065
|
+
isTargeted && /* @__PURE__ */ jsx(
|
|
6066
|
+
"span",
|
|
6067
|
+
{
|
|
6068
|
+
className: "ra-row-rule-pip",
|
|
6069
|
+
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
6070
|
+
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
6071
|
+
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
6072
|
+
}
|
|
6073
|
+
),
|
|
6074
|
+
hasError ? /* @__PURE__ */ jsx(
|
|
6075
|
+
"span",
|
|
6076
|
+
{
|
|
6077
|
+
className: "ra-error-pip",
|
|
6078
|
+
title: "Save failed",
|
|
6079
|
+
"aria-label": "Save failed"
|
|
6080
|
+
}
|
|
6081
|
+
) : isDirty ? /* @__PURE__ */ jsx(
|
|
6082
|
+
"span",
|
|
6083
|
+
{
|
|
6084
|
+
className: "ra-dirty-pip",
|
|
6085
|
+
title: "Unsaved changes",
|
|
6086
|
+
"aria-label": "Unsaved changes"
|
|
6087
|
+
}
|
|
6088
|
+
) : null
|
|
6089
|
+
]
|
|
6090
|
+
}
|
|
6091
|
+
) }, key);
|
|
6092
|
+
}) })
|
|
6093
|
+
] })
|
|
6094
|
+
] });
|
|
6014
6095
|
}
|
|
6015
6096
|
var TONE_ICON = {
|
|
6016
6097
|
info: Lightbulb,
|
|
@@ -6948,6 +7029,60 @@ var SaveAllProgress = ({
|
|
|
6948
7029
|
}
|
|
6949
7030
|
);
|
|
6950
7031
|
};
|
|
7032
|
+
function PreviewReopenPill({ anchorRef, onClick, ariaLabel, title, children }) {
|
|
7033
|
+
const [pos, setPos] = useState(null);
|
|
7034
|
+
const rafRef = useRef(null);
|
|
7035
|
+
useLayoutEffect(() => {
|
|
7036
|
+
const el = anchorRef.current;
|
|
7037
|
+
if (!el || typeof window === "undefined") return;
|
|
7038
|
+
const measure = () => {
|
|
7039
|
+
if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
|
|
7040
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
7041
|
+
const rect = el.getBoundingClientRect();
|
|
7042
|
+
if (rect.width === 0 && rect.height === 0) return;
|
|
7043
|
+
setPos({
|
|
7044
|
+
top: rect.top + rect.height / 2,
|
|
7045
|
+
right: Math.max(0, window.innerWidth - rect.right)
|
|
7046
|
+
});
|
|
7047
|
+
});
|
|
7048
|
+
};
|
|
7049
|
+
measure();
|
|
7050
|
+
const ro = new ResizeObserver(measure);
|
|
7051
|
+
ro.observe(el);
|
|
7052
|
+
ro.observe(document.body);
|
|
7053
|
+
window.addEventListener("resize", measure);
|
|
7054
|
+
window.addEventListener("scroll", measure, true);
|
|
7055
|
+
return () => {
|
|
7056
|
+
ro.disconnect();
|
|
7057
|
+
window.removeEventListener("resize", measure);
|
|
7058
|
+
window.removeEventListener("scroll", measure, true);
|
|
7059
|
+
if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
|
|
7060
|
+
};
|
|
7061
|
+
}, [anchorRef]);
|
|
7062
|
+
if (typeof document === "undefined" || !pos) return null;
|
|
7063
|
+
return createPortal(
|
|
7064
|
+
/* @__PURE__ */ jsx(
|
|
7065
|
+
"button",
|
|
7066
|
+
{
|
|
7067
|
+
type: "button",
|
|
7068
|
+
className: "ra-shell ra-preview-reopen ra-preview-reopen--floating",
|
|
7069
|
+
onClick,
|
|
7070
|
+
"aria-label": ariaLabel,
|
|
7071
|
+
title,
|
|
7072
|
+
style: {
|
|
7073
|
+
position: "fixed",
|
|
7074
|
+
top: pos.top,
|
|
7075
|
+
right: pos.right,
|
|
7076
|
+
// Pull half the pill width out into the gutter so it visually
|
|
7077
|
+
// anchors *to* the editor edge rather than sitting inside it.
|
|
7078
|
+
transform: "translate(50%, -50%)"
|
|
7079
|
+
},
|
|
7080
|
+
children
|
|
7081
|
+
}
|
|
7082
|
+
),
|
|
7083
|
+
document.body
|
|
7084
|
+
);
|
|
7085
|
+
}
|
|
6951
7086
|
var EditorMountPool = ({
|
|
6952
7087
|
renderSlot,
|
|
6953
7088
|
keepMountedHidden = true,
|
|
@@ -7700,6 +7835,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7700
7835
|
]);
|
|
7701
7836
|
const onLeftSelectRef = useRef(null);
|
|
7702
7837
|
const onCreateItemDraftRef = useRef(null);
|
|
7838
|
+
const previewReopenAnchorRef = useRef(null);
|
|
7703
7839
|
const { runWithGuard } = useDirtyNavigation({
|
|
7704
7840
|
strategy: dirtyStrategy,
|
|
7705
7841
|
isDirty: editorCtx.isDirty,
|
|
@@ -7807,6 +7943,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7807
7943
|
const itemViewCtx = baseItemViewCtx;
|
|
7808
7944
|
const renderEditorWithPreview = () => {
|
|
7809
7945
|
if (!editingTargetScope) return null;
|
|
7946
|
+
const previewAnchorRef = previewReopenAnchorRef;
|
|
7810
7947
|
const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
|
|
7811
7948
|
const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
7812
7949
|
PreviewScopePicker,
|
|
@@ -7908,15 +8045,14 @@ function RecordsAdminShellInner(props) {
|
|
|
7908
8045
|
if (previewMode === "side") {
|
|
7909
8046
|
if (!sidePreviewOpen) {
|
|
7910
8047
|
return withNav(
|
|
7911
|
-
/* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
|
|
8048
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-full", ref: previewAnchorRef, children: [
|
|
7912
8049
|
baseEditor(),
|
|
7913
8050
|
/* @__PURE__ */ jsxs(
|
|
7914
|
-
|
|
8051
|
+
PreviewReopenPill,
|
|
7915
8052
|
{
|
|
7916
|
-
|
|
7917
|
-
className: "ra-preview-reopen",
|
|
8053
|
+
anchorRef: previewAnchorRef,
|
|
7918
8054
|
onClick: () => setSidePreviewOpen(true),
|
|
7919
|
-
|
|
8055
|
+
ariaLabel: i18n.openPreview,
|
|
7920
8056
|
title: i18n.openPreview,
|
|
7921
8057
|
children: [
|
|
7922
8058
|
/* @__PURE__ */ jsx(Eye, { "aria-hidden": "true" }),
|
|
@@ -8212,25 +8348,18 @@ function RecordsAdminShellInner(props) {
|
|
|
8212
8348
|
[facetBrowseFilter]
|
|
8213
8349
|
);
|
|
8214
8350
|
const facetBrowseFacets = useMemo(() => {
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
const
|
|
8220
|
-
if (!key
|
|
8221
|
-
const
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
if (existing) {
|
|
8225
|
-
if (!existing.values.some((v) => v.key === value)) {
|
|
8226
|
-
existing.values.push({ key: value, label: valueLabel });
|
|
8227
|
-
}
|
|
8228
|
-
} else {
|
|
8229
|
-
byKey.set(key, { key, label: facetLabel, values: [{ key: value, label: valueLabel }] });
|
|
8230
|
-
}
|
|
8351
|
+
const vocab = facetBrowse.vocabulary ?? [];
|
|
8352
|
+
if (!vocab.length) return [];
|
|
8353
|
+
const out = [];
|
|
8354
|
+
for (const facet of vocab) {
|
|
8355
|
+
const key = facet.key;
|
|
8356
|
+
if (!key) continue;
|
|
8357
|
+
const values = (facet.values ?? []).filter((v) => !!v.key).map((v) => ({ key: v.key, label: v.name ?? v.key }));
|
|
8358
|
+
if (!values.length) continue;
|
|
8359
|
+
out.push({ key, label: facet.name ?? key, values });
|
|
8231
8360
|
}
|
|
8232
|
-
return
|
|
8233
|
-
}, [facetBrowse.
|
|
8361
|
+
return out;
|
|
8362
|
+
}, [facetBrowse.vocabulary]);
|
|
8234
8363
|
const collectionGlobalAllRow = useMemo(
|
|
8235
8364
|
() => ({
|
|
8236
8365
|
id: null,
|
|
@@ -8438,6 +8567,8 @@ function RecordsAdminShellInner(props) {
|
|
|
8438
8567
|
onSelect: onItemOpen,
|
|
8439
8568
|
dirtyKeys,
|
|
8440
8569
|
errorKeys,
|
|
8570
|
+
contextKind: activeScope === "rule" ? "Rule" : activeScope === "product" ? "Product" : activeScope === "collection" ? "Global" : activeScope === "all" ? "All records" : activeScope === "variant" ? "Variant" : activeScope === "batch" ? "Batch" : activeScope === "facet" ? "Facet" : void 0,
|
|
8571
|
+
contextSummary: activeScope === "rule" ? activeRuleSummary : activeScope === "product" ? editorHeaderLabel ?? null : null,
|
|
8441
8572
|
i18n
|
|
8442
8573
|
}
|
|
8443
8574
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|