@proveanything/smartlinks-utils-ui 0.8.2 → 0.8.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.
|
@@ -658,6 +658,22 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
658
658
|
variantId?: string;
|
|
659
659
|
batchId?: string;
|
|
660
660
|
};
|
|
661
|
+
/**
|
|
662
|
+
* How the rail should react when `contextScope.productId` is pinned.
|
|
663
|
+
*
|
|
664
|
+
* - `'strict'` (default) — the host has scoped this mount to one product.
|
|
665
|
+
* The rail hides `'collection'` (Global) and `'rule'` tabs entirely
|
|
666
|
+
* (they're collection-wide concerns the product inherits) and the
|
|
667
|
+
* product list collapses to that single product. When the product has
|
|
668
|
+
* no variants and no batches available for drill-down AND no other
|
|
669
|
+
* top-level scopes survive, the rail itself is hidden and the editor
|
|
670
|
+
* takes the whole pane.
|
|
671
|
+
* - `'expand'` — legacy behaviour. The full rail renders; pinning only
|
|
672
|
+
* biases the default tab + selected product.
|
|
673
|
+
*
|
|
674
|
+
* Has no effect when `contextScope.productId` is not set.
|
|
675
|
+
*/
|
|
676
|
+
contextScopeMode?: 'strict' | 'expand';
|
|
661
677
|
renderEditor: (ctx: EditorContext<TData>) => ReactNode;
|
|
662
678
|
/**
|
|
663
679
|
* Render the preview surface. Receives the editor's current value so the
|
|
@@ -1651,6 +1667,16 @@ interface UseCollectionItemsArgs {
|
|
|
1651
1667
|
* the query disabled.
|
|
1652
1668
|
*/
|
|
1653
1669
|
scope: ParsedRef | null;
|
|
1670
|
+
/**
|
|
1671
|
+
* When the scope is a rule (kind === 'rule'), pass the rule's `facetRule`
|
|
1672
|
+
* here. Items belonging to a rule are records that carry the *same*
|
|
1673
|
+
* facetRule — they share anchors only by coincidence (typically empty),
|
|
1674
|
+
* so anchor equality alone isn't enough to identify them. When this is
|
|
1675
|
+
* provided we match rule records by facetRule equality and ignore
|
|
1676
|
+
* anchors. When absent, anchor-based matching applies (and rule records
|
|
1677
|
+
* are skipped, since they belong on the Rules tab).
|
|
1678
|
+
*/
|
|
1679
|
+
facetRule?: FacetRule | null;
|
|
1654
1680
|
/** Per-page size requested from the SDK (default 100). */
|
|
1655
1681
|
pageSize?: number;
|
|
1656
1682
|
/**
|
|
@@ -2229,6 +2229,14 @@ function useItemViewPref(args) {
|
|
|
2229
2229
|
return [value, set];
|
|
2230
2230
|
}
|
|
2231
2231
|
var QK_BASE2 = ["records-admin", "collection-items"];
|
|
2232
|
+
var canonicalFacetRule = (rule) => {
|
|
2233
|
+
if (!rule || !Array.isArray(rule.all)) return "";
|
|
2234
|
+
const clauses = rule.all.map((c) => ({
|
|
2235
|
+
facetKey: c.facetKey,
|
|
2236
|
+
anyOf: [...c.anyOf ?? []].sort()
|
|
2237
|
+
})).sort((a, b) => a.facetKey.localeCompare(b.facetKey));
|
|
2238
|
+
return JSON.stringify(clauses);
|
|
2239
|
+
};
|
|
2232
2240
|
var defaultToSummary = (rec, base) => {
|
|
2233
2241
|
const data = rec.data;
|
|
2234
2242
|
const display = data?.display ?? void 0;
|
|
@@ -2238,8 +2246,13 @@ var defaultToSummary = (rec, base) => {
|
|
|
2238
2246
|
const thumbnail = data.thumbnail ?? data.image ?? data.cover ?? data.home_image_url ?? base.thumbnail;
|
|
2239
2247
|
return { ...base, label, subtitle, thumbnail };
|
|
2240
2248
|
};
|
|
2241
|
-
var recordMatchesScope = (rec, scope) => {
|
|
2249
|
+
var recordMatchesScope = (rec, scope, ruleSignature) => {
|
|
2242
2250
|
const facetRule = rec.facetRule ?? null;
|
|
2251
|
+
if (scope.kind === "rule") {
|
|
2252
|
+
if (!facetRule) return false;
|
|
2253
|
+
if (!ruleSignature) return false;
|
|
2254
|
+
return canonicalFacetRule(facetRule) === ruleSignature;
|
|
2255
|
+
}
|
|
2243
2256
|
if (facetRule) return false;
|
|
2244
2257
|
return (rec.productId ?? void 0) === scope.productId && (rec.variantId ?? void 0) === scope.variantId && (rec.batchId ?? void 0) === scope.batchId && (rec.proofId ?? void 0) === scope.proofId;
|
|
2245
2258
|
};
|
|
@@ -2247,15 +2260,20 @@ function useCollectionItems(args) {
|
|
|
2247
2260
|
const {
|
|
2248
2261
|
ctx,
|
|
2249
2262
|
scope,
|
|
2263
|
+
facetRule,
|
|
2250
2264
|
pageSize = 100,
|
|
2251
2265
|
toSummary: toSummary2 = defaultToSummary,
|
|
2252
2266
|
enabled = true
|
|
2253
2267
|
} = args;
|
|
2254
2268
|
const queryClient = useQueryClient();
|
|
2255
2269
|
const scopeRef = scope?.raw ?? "";
|
|
2270
|
+
const ruleSignature = useMemo(
|
|
2271
|
+
() => scope?.kind === "rule" ? canonicalFacetRule(facetRule) : "",
|
|
2272
|
+
[scope?.kind, facetRule]
|
|
2273
|
+
);
|
|
2256
2274
|
const queryKey = useMemo(
|
|
2257
|
-
() => [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType, scopeRef],
|
|
2258
|
-
[ctx.collectionId, ctx.appId, ctx.recordType, scopeRef]
|
|
2275
|
+
() => [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType, scopeRef, ruleSignature],
|
|
2276
|
+
[ctx.collectionId, ctx.appId, ctx.recordType, scopeRef, ruleSignature]
|
|
2259
2277
|
);
|
|
2260
2278
|
const query = useInfiniteQuery({
|
|
2261
2279
|
queryKey,
|
|
@@ -2275,7 +2293,7 @@ function useCollectionItems(args) {
|
|
|
2275
2293
|
const items = useMemo(() => {
|
|
2276
2294
|
if (!scope) return [];
|
|
2277
2295
|
const all = query.data?.pages.flatMap((p) => p.data) ?? [];
|
|
2278
|
-
const relevant = all.filter((rec) => recordMatchesScope(rec, scope));
|
|
2296
|
+
const relevant = all.filter((rec) => recordMatchesScope(rec, scope, ruleSignature));
|
|
2279
2297
|
return relevant.map((rec) => {
|
|
2280
2298
|
const ref = rec.ref ?? "";
|
|
2281
2299
|
const parsed = parseRef(ref);
|
|
@@ -2292,7 +2310,7 @@ function useCollectionItems(args) {
|
|
|
2292
2310
|
};
|
|
2293
2311
|
return toSummary2(rec, base);
|
|
2294
2312
|
}).filter((x) => x !== null);
|
|
2295
|
-
}, [query.data, toSummary2, scope]);
|
|
2313
|
+
}, [query.data, toSummary2, scope, ruleSignature]);
|
|
2296
2314
|
const refetch = useCallback(() => {
|
|
2297
2315
|
queryClient.invalidateQueries({ queryKey });
|
|
2298
2316
|
}, [queryClient, queryKey]);
|
|
@@ -5535,6 +5553,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5535
5553
|
scopes: requestedScopes,
|
|
5536
5554
|
defaultScope,
|
|
5537
5555
|
contextScope,
|
|
5556
|
+
contextScopeMode = "strict",
|
|
5538
5557
|
renderEditor,
|
|
5539
5558
|
renderPreview,
|
|
5540
5559
|
intro,
|
|
@@ -5657,6 +5676,11 @@ function RecordsAdminShellInner(props) {
|
|
|
5657
5676
|
}
|
|
5658
5677
|
return [...TOP_LEVEL_SCOPES];
|
|
5659
5678
|
}, [requestedScopes]);
|
|
5679
|
+
const productPinnedFromContext = !!contextScope?.productId;
|
|
5680
|
+
const effectiveTopLevelScopes = useMemo(() => {
|
|
5681
|
+
if (!productPinnedFromContext || contextScopeMode !== "strict") return topLevelScopes;
|
|
5682
|
+
return topLevelScopes.filter((s) => s !== "collection" && s !== "rule");
|
|
5683
|
+
}, [productPinnedFromContext, contextScopeMode, topLevelScopes]);
|
|
5660
5684
|
useEffect(() => {
|
|
5661
5685
|
if (requestedScopes.includes("facet") && !WARNED_FACET_DEPRECATED) {
|
|
5662
5686
|
WARNED_FACET_DEPRECATED = true;
|
|
@@ -5674,10 +5698,10 @@ function RecordsAdminShellInner(props) {
|
|
|
5674
5698
|
[requestedScopes, probe.isLoading, probe.hasBatches]
|
|
5675
5699
|
);
|
|
5676
5700
|
const initialScope = useMemo(() => {
|
|
5677
|
-
if (contextScope?.productId &&
|
|
5678
|
-
if (defaultScope &&
|
|
5679
|
-
return
|
|
5680
|
-
}, [contextScope?.productId, defaultScope,
|
|
5701
|
+
if (contextScope?.productId && effectiveTopLevelScopes.includes("product")) return "product";
|
|
5702
|
+
if (defaultScope && effectiveTopLevelScopes.includes(defaultScope)) return defaultScope;
|
|
5703
|
+
return effectiveTopLevelScopes[0] ?? "product";
|
|
5704
|
+
}, [contextScope?.productId, defaultScope, effectiveTopLevelScopes]);
|
|
5681
5705
|
const [activeScope, setActiveScope] = useState(initialScope);
|
|
5682
5706
|
useEffect(() => {
|
|
5683
5707
|
setActiveScope(initialScope);
|
|
@@ -5805,6 +5829,12 @@ function RecordsAdminShellInner(props) {
|
|
|
5805
5829
|
const collectionItems = useCollectionItems({
|
|
5806
5830
|
ctx,
|
|
5807
5831
|
scope: isCollection ? editingScope : null,
|
|
5832
|
+
// When the editing scope is a rule, items belonging to that rule are
|
|
5833
|
+
// records carrying the *same* facetRule (anchors are typically empty
|
|
5834
|
+
// and would otherwise collide with global records). Look up the rule's
|
|
5835
|
+
// facetRule from the selected record's summary so `useCollectionItems`
|
|
5836
|
+
// can match by rule equality instead of by anchors.
|
|
5837
|
+
facetRule: editingScope?.kind === "rule" ? recordList.items.find((it) => it.id === selectedRecordId)?.facetRule ?? null : null,
|
|
5808
5838
|
enabled: isCollection
|
|
5809
5839
|
});
|
|
5810
5840
|
const editingTargetScope = useMemo(() => {
|
|
@@ -6385,6 +6415,21 @@ function RecordsAdminShellInner(props) {
|
|
|
6385
6415
|
};
|
|
6386
6416
|
const isProductTab = activeScope === "product";
|
|
6387
6417
|
const productPinned = !!contextScope?.productId;
|
|
6418
|
+
const railHidden = useMemo(() => {
|
|
6419
|
+
if (!productPinned) return false;
|
|
6420
|
+
if (contextScopeMode !== "strict") return false;
|
|
6421
|
+
if (cardinality === "collection") return false;
|
|
6422
|
+
if (effectiveTopLevelScopes.length > 1) return false;
|
|
6423
|
+
if (drillVariantsAllowed || drillBatchesAllowed) return false;
|
|
6424
|
+
return true;
|
|
6425
|
+
}, [
|
|
6426
|
+
productPinned,
|
|
6427
|
+
contextScopeMode,
|
|
6428
|
+
cardinality,
|
|
6429
|
+
effectiveTopLevelScopes.length,
|
|
6430
|
+
drillVariantsAllowed,
|
|
6431
|
+
drillBatchesAllowed
|
|
6432
|
+
]);
|
|
6388
6433
|
const effectivePresentation = isProductTab ? presentation : "list";
|
|
6389
6434
|
const showPresentationSwitcher = isProductTab && presentations.length > 1;
|
|
6390
6435
|
const effectiveGroupBy = groupBy;
|
|
@@ -6679,9 +6724,12 @@ function RecordsAdminShellInner(props) {
|
|
|
6679
6724
|
"div",
|
|
6680
6725
|
{
|
|
6681
6726
|
className: "flex-1 grid border-t overflow-hidden",
|
|
6682
|
-
style: {
|
|
6727
|
+
style: {
|
|
6728
|
+
gridTemplateColumns: railHidden ? "1fr" : "minmax(260px, 320px) 1fr",
|
|
6729
|
+
borderColor: "hsl(var(--ra-border))"
|
|
6730
|
+
},
|
|
6683
6731
|
children: [
|
|
6684
|
-
/* @__PURE__ */ jsx("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: isCollection && selectedItemId && collectionRailMode === "siblings" && ruleWizardStep === null ? /* @__PURE__ */ jsx(
|
|
6732
|
+
!railHidden && /* @__PURE__ */ jsx("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: isCollection && selectedItemId && collectionRailMode === "siblings" && ruleWizardStep === null ? /* @__PURE__ */ jsx(
|
|
6685
6733
|
SiblingRail,
|
|
6686
6734
|
{
|
|
6687
6735
|
items: collectionItems.items,
|
|
@@ -6698,7 +6746,7 @@ function RecordsAdminShellInner(props) {
|
|
|
6698
6746
|
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
|
|
6699
6747
|
ScopeTabs,
|
|
6700
6748
|
{
|
|
6701
|
-
scopes:
|
|
6749
|
+
scopes: effectiveTopLevelScopes,
|
|
6702
6750
|
active: activeScope,
|
|
6703
6751
|
onChange: (s) => {
|
|
6704
6752
|
void runWithGuard(() => {
|
|
@@ -6747,60 +6795,62 @@ function RecordsAdminShellInner(props) {
|
|
|
6747
6795
|
]
|
|
6748
6796
|
}
|
|
6749
6797
|
),
|
|
6750
|
-
/* @__PURE__ */ jsxs(
|
|
6751
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
6752
|
-
/* @__PURE__ */
|
|
6798
|
+
!(isGlobalTab && !isCollection) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6799
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6800
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0", children: [
|
|
6801
|
+
/* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 opacity-50" }),
|
|
6802
|
+
/* @__PURE__ */ jsx(
|
|
6803
|
+
"input",
|
|
6804
|
+
{
|
|
6805
|
+
type: "text",
|
|
6806
|
+
value: search,
|
|
6807
|
+
onChange: (e) => setSearch(e.target.value),
|
|
6808
|
+
placeholder: i18n.searchPlaceholder,
|
|
6809
|
+
className: "w-full pl-8 pr-3 py-1.5 text-xs rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
6810
|
+
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" }
|
|
6811
|
+
}
|
|
6812
|
+
)
|
|
6813
|
+
] }),
|
|
6753
6814
|
/* @__PURE__ */ jsx(
|
|
6754
|
-
|
|
6815
|
+
PresentationSwitcher,
|
|
6755
6816
|
{
|
|
6756
|
-
|
|
6757
|
-
value:
|
|
6758
|
-
onChange:
|
|
6759
|
-
|
|
6760
|
-
className: "w-full pl-8 pr-3 py-1.5 text-xs rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
6761
|
-
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" }
|
|
6817
|
+
options: showPresentationSwitcher ? presentations : [],
|
|
6818
|
+
value: presentation,
|
|
6819
|
+
onChange: onPresentationChange,
|
|
6820
|
+
i18n
|
|
6762
6821
|
}
|
|
6763
6822
|
)
|
|
6764
6823
|
] }),
|
|
6765
|
-
/* @__PURE__ */ jsx(
|
|
6766
|
-
|
|
6824
|
+
!isProductTab && !isRuleTab && !isGlobalTab && /* @__PURE__ */ jsx(
|
|
6825
|
+
StatusFilterPills,
|
|
6767
6826
|
{
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6827
|
+
value: filter,
|
|
6828
|
+
onChange: setFilter,
|
|
6829
|
+
counts: facetBrowse.counts,
|
|
6830
|
+
hideZero: ["partial"],
|
|
6771
6831
|
i18n
|
|
6772
6832
|
}
|
|
6833
|
+
),
|
|
6834
|
+
isRuleTab && /* @__PURE__ */ jsx(
|
|
6835
|
+
RuleFilterChips,
|
|
6836
|
+
{
|
|
6837
|
+
source: recordList.items,
|
|
6838
|
+
value: ruleFilters,
|
|
6839
|
+
onChange: setRuleFilters
|
|
6840
|
+
}
|
|
6841
|
+
),
|
|
6842
|
+
isRuleTab && /* @__PURE__ */ jsx(
|
|
6843
|
+
FacetBrowseFilter,
|
|
6844
|
+
{
|
|
6845
|
+
facets: facetBrowseFacets,
|
|
6846
|
+
value: facetBrowseFilter,
|
|
6847
|
+
onChange: setFacetBrowseFilter,
|
|
6848
|
+
isLoading: facetBrowse.isLoading
|
|
6849
|
+
}
|
|
6773
6850
|
)
|
|
6774
|
-
] })
|
|
6775
|
-
!isProductTab && !isRuleTab && !isGlobalTab && /* @__PURE__ */ jsx(
|
|
6776
|
-
StatusFilterPills,
|
|
6777
|
-
{
|
|
6778
|
-
value: filter,
|
|
6779
|
-
onChange: setFilter,
|
|
6780
|
-
counts: facetBrowse.counts,
|
|
6781
|
-
hideZero: ["partial"],
|
|
6782
|
-
i18n
|
|
6783
|
-
}
|
|
6784
|
-
),
|
|
6785
|
-
isRuleTab && /* @__PURE__ */ jsx(
|
|
6786
|
-
RuleFilterChips,
|
|
6787
|
-
{
|
|
6788
|
-
source: recordList.items,
|
|
6789
|
-
value: ruleFilters,
|
|
6790
|
-
onChange: setRuleFilters
|
|
6791
|
-
}
|
|
6792
|
-
),
|
|
6793
|
-
(isRuleTab || isGlobalTab && !isCollection) && /* @__PURE__ */ jsx(
|
|
6794
|
-
FacetBrowseFilter,
|
|
6795
|
-
{
|
|
6796
|
-
facets: facetBrowseFacets,
|
|
6797
|
-
value: facetBrowseFilter,
|
|
6798
|
-
onChange: setFacetBrowseFilter,
|
|
6799
|
-
isLoading: facetBrowse.isLoading
|
|
6800
|
-
}
|
|
6801
|
-
)
|
|
6851
|
+
] })
|
|
6802
6852
|
] }),
|
|
6803
|
-
/* @__PURE__ */
|
|
6853
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isGlobalTab && !isCollection ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6804
6854
|
leftLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
6805
6855
|
!leftLoading && leftError && /* @__PURE__ */ jsx(ErrorState, { error: leftError }),
|
|
6806
6856
|
!leftLoading && !leftError && leftItems.length === 0 && (renderEmpty ? renderEmpty({ scope: editingScope }) : renderEmptyState ? renderEmptyState({ scope: activeScope }) : /* @__PURE__ */ jsx(
|
|
@@ -6844,7 +6894,7 @@ function RecordsAdminShellInner(props) {
|
|
|
6844
6894
|
}
|
|
6845
6895
|
) })
|
|
6846
6896
|
] })
|
|
6847
|
-
] })
|
|
6897
|
+
] }) })
|
|
6848
6898
|
] }) }),
|
|
6849
6899
|
/* @__PURE__ */ jsxs("main", { className: "overflow-hidden", children: [
|
|
6850
6900
|
ruleWizardStep !== null && /* @__PURE__ */ jsxs(
|