@proveanything/smartlinks-utils-ui 0.9.7 → 0.9.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/components/AssetPicker/index.css +18 -0
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +18 -0
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +18 -0
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +18 -0
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +18 -0
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +27 -2
- package/dist/components/RecordsAdmin/index.js +94 -41
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +18 -0
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
|
@@ -1235,6 +1235,14 @@ interface Props$a<T> {
|
|
|
1235
1235
|
headerLabel?: string;
|
|
1236
1236
|
/** Optional subtitle shown beneath `headerLabel` (e.g. facet name). */
|
|
1237
1237
|
headerSubtitle?: string;
|
|
1238
|
+
/**
|
|
1239
|
+
* Optional content rendered at the very start of the header's left
|
|
1240
|
+
* cluster, before the title/breadcrumb. Used by the shell to embed the
|
|
1241
|
+
* collection-mode `EditorItemNav` (Back / position / arrows) inline so
|
|
1242
|
+
* it shares the row with the Global / scope chip instead of consuming
|
|
1243
|
+
* its own strip above the editor.
|
|
1244
|
+
*/
|
|
1245
|
+
headerLeading?: ReactNode;
|
|
1238
1246
|
/**
|
|
1239
1247
|
* Optional technical reference (e.g. productId / SKU) shown as a tiny muted
|
|
1240
1248
|
* caption pinned to the top-right of the header. Power users can scan it
|
|
@@ -1259,7 +1267,7 @@ interface Props$a<T> {
|
|
|
1259
1267
|
/** Host-provided icons rendered before save / discard / delete labels. */
|
|
1260
1268
|
actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
|
|
1261
1269
|
}
|
|
1262
|
-
declare function RecordEditor<T>({ ctx, i18n, children, preview, targeting, targetingControl, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
|
|
1270
|
+
declare function RecordEditor<T>({ ctx, i18n, children, preview, targeting, targetingControl, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, headerLeading, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
|
|
1263
1271
|
|
|
1264
1272
|
interface InheritanceCtx {
|
|
1265
1273
|
parentValue?: Record<string, unknown> | null;
|
|
@@ -1897,6 +1905,16 @@ interface UseScopeCountsResult {
|
|
|
1897
1905
|
error: Error | null;
|
|
1898
1906
|
/** True when we hit `maxRecords` and stopped paginating. */
|
|
1899
1907
|
truncated: boolean;
|
|
1908
|
+
/**
|
|
1909
|
+
* Set of distinct `productId`s observed across the scanned records.
|
|
1910
|
+
* Used by the rail to:
|
|
1911
|
+
* • surface "X products configured" as the Products tab badge
|
|
1912
|
+
* (consistent with Global/Rules counts — never catalogue size);
|
|
1913
|
+
* • sort configured products to the top of the browse rail;
|
|
1914
|
+
* • back the Configured/Not-configured filter pills.
|
|
1915
|
+
* Lower bound when `truncated` is true.
|
|
1916
|
+
*/
|
|
1917
|
+
productIds: ReadonlySet<string>;
|
|
1900
1918
|
}
|
|
1901
1919
|
declare const useScopeCounts: (args: UseScopeCountsArgs) => UseScopeCountsResult;
|
|
1902
1920
|
/** React Query key factory for cache invalidation from save/delete sites. */
|
|
@@ -2283,8 +2301,15 @@ interface Props$1 {
|
|
|
2283
2301
|
canPrev: boolean;
|
|
2284
2302
|
canNext: boolean;
|
|
2285
2303
|
i18n: Pick<RecordsAdminI18n, 'backToList' | 'prevItem' | 'nextItem'>;
|
|
2304
|
+
/**
|
|
2305
|
+
* When true, render without the row-level border/background/padding so
|
|
2306
|
+
* the nav can sit inline inside another header strip (the shell embeds
|
|
2307
|
+
* it in `RecordEditor`'s header to avoid a dedicated row of whitespace
|
|
2308
|
+
* above the editor).
|
|
2309
|
+
*/
|
|
2310
|
+
embedded?: boolean;
|
|
2286
2311
|
}
|
|
2287
|
-
declare const EditorItemNav: ({ label, position, total, onBack, onPrev, onNext, canPrev, canNext, i18n, }: Props$1) => react_jsx_runtime.JSX.Element;
|
|
2312
|
+
declare const EditorItemNav: ({ label, position, total, onBack, onPrev, onNext, canPrev, canNext, i18n, embedded, }: Props$1) => react_jsx_runtime.JSX.Element;
|
|
2288
2313
|
|
|
2289
2314
|
interface Props<T> {
|
|
2290
2315
|
items: RecordSummary<T>[];
|
|
@@ -531,14 +531,20 @@ var useScopeCounts = (args) => {
|
|
|
531
531
|
rule: 0,
|
|
532
532
|
all: 0
|
|
533
533
|
};
|
|
534
|
-
|
|
534
|
+
const productIds = /* @__PURE__ */ new Set();
|
|
535
|
+
for (const rec of records) {
|
|
536
|
+
counts[classify(rec)] += 1;
|
|
537
|
+
const pid = rec.productId ?? void 0;
|
|
538
|
+
if (pid) productIds.add(pid);
|
|
539
|
+
}
|
|
535
540
|
counts.all = records.length;
|
|
536
541
|
return {
|
|
537
542
|
counts,
|
|
538
543
|
total: records.length,
|
|
539
544
|
isLoading: query.isLoading,
|
|
540
545
|
error: query.error ?? null,
|
|
541
|
-
truncated
|
|
546
|
+
truncated,
|
|
547
|
+
productIds
|
|
542
548
|
};
|
|
543
549
|
}, [query.data, query.isLoading, query.error]);
|
|
544
550
|
return result;
|
|
@@ -4245,6 +4251,7 @@ function RecordEditor({
|
|
|
4245
4251
|
headerLabel,
|
|
4246
4252
|
headerSubtitle,
|
|
4247
4253
|
headerMeta,
|
|
4254
|
+
headerLeading,
|
|
4248
4255
|
clipboard,
|
|
4249
4256
|
actionLabels,
|
|
4250
4257
|
actionIcons
|
|
@@ -4261,7 +4268,7 @@ function RecordEditor({
|
|
|
4261
4268
|
const s = ctx.scope;
|
|
4262
4269
|
return Boolean(s?.facetId || s?.productId || s?.variantId || s?.batchId);
|
|
4263
4270
|
})();
|
|
4264
|
-
const hasLeftContent = Boolean(headerLabel) || hasBreadcrumb;
|
|
4271
|
+
const hasLeftContent = Boolean(headerLabel) || hasBreadcrumb || Boolean(headerLeading);
|
|
4265
4272
|
const hasRightContent = showInherited || showEmpty || Boolean(headerMeta) || Boolean(bulkActions) || Boolean(targetingControl);
|
|
4266
4273
|
const showHeader = hasLeftContent || hasRightContent;
|
|
4267
4274
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
@@ -4271,26 +4278,29 @@ function RecordEditor({
|
|
|
4271
4278
|
className: "sticky top-0 z-40 px-5 py-3 border-b flex items-start justify-between gap-3",
|
|
4272
4279
|
style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" },
|
|
4273
4280
|
children: [
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */ jsx(
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4281
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 flex items-center gap-3", children: [
|
|
4282
|
+
headerLeading && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: headerLeading }),
|
|
4283
|
+
headerLabel ? /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
4284
|
+
/* @__PURE__ */ jsx(
|
|
4285
|
+
"div",
|
|
4286
|
+
{
|
|
4287
|
+
className: "text-sm font-medium truncate",
|
|
4288
|
+
style: { color: "hsl(var(--ra-text))" },
|
|
4289
|
+
title: headerLabel,
|
|
4290
|
+
children: headerLabel
|
|
4291
|
+
}
|
|
4292
|
+
),
|
|
4293
|
+
headerSubtitle && /* @__PURE__ */ jsx(
|
|
4294
|
+
"div",
|
|
4295
|
+
{
|
|
4296
|
+
className: "text-xs truncate",
|
|
4297
|
+
style: { color: "hsl(var(--ra-muted-text))" },
|
|
4298
|
+
title: headerSubtitle,
|
|
4299
|
+
children: headerSubtitle
|
|
4300
|
+
}
|
|
4301
|
+
)
|
|
4302
|
+
] }) : /* @__PURE__ */ jsx(ScopeBreadcrumb, { scope: ctx.scope })
|
|
4303
|
+
] }),
|
|
4294
4304
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 shrink-0", children: [
|
|
4295
4305
|
showInherited && /* @__PURE__ */ jsxs(
|
|
4296
4306
|
"span",
|
|
@@ -5759,8 +5769,9 @@ var EditorItemNav = ({
|
|
|
5759
5769
|
onNext,
|
|
5760
5770
|
canPrev,
|
|
5761
5771
|
canNext,
|
|
5762
|
-
i18n
|
|
5763
|
-
|
|
5772
|
+
i18n,
|
|
5773
|
+
embedded
|
|
5774
|
+
}) => /* @__PURE__ */ jsxs("div", { className: "ra-item-nav", "data-embedded": embedded ? "true" : void 0, children: [
|
|
5764
5775
|
/* @__PURE__ */ jsxs(
|
|
5765
5776
|
"button",
|
|
5766
5777
|
{
|
|
@@ -5774,12 +5785,7 @@ var EditorItemNav = ({
|
|
|
5774
5785
|
]
|
|
5775
5786
|
}
|
|
5776
5787
|
),
|
|
5777
|
-
|
|
5778
|
-
position,
|
|
5779
|
-
" / ",
|
|
5780
|
-
total
|
|
5781
|
-
] }),
|
|
5782
|
-
/* @__PURE__ */ jsxs("div", { className: "ra-item-nav-arrows", children: [
|
|
5788
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-item-nav-cluster", children: [
|
|
5783
5789
|
/* @__PURE__ */ jsx(
|
|
5784
5790
|
"button",
|
|
5785
5791
|
{
|
|
@@ -5792,6 +5798,11 @@ var EditorItemNav = ({
|
|
|
5792
5798
|
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
|
|
5793
5799
|
}
|
|
5794
5800
|
),
|
|
5801
|
+
typeof position === "number" && typeof total === "number" && total > 0 && /* @__PURE__ */ jsxs("span", { className: "ra-item-nav-position", "aria-label": label, children: [
|
|
5802
|
+
position,
|
|
5803
|
+
" / ",
|
|
5804
|
+
total
|
|
5805
|
+
] }),
|
|
5795
5806
|
/* @__PURE__ */ jsx(
|
|
5796
5807
|
"button",
|
|
5797
5808
|
{
|
|
@@ -7665,6 +7676,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7665
7676
|
const itemNav = isCollection && selectedItemId && itemPosition && ruleWizardStep === null ? /* @__PURE__ */ jsx(
|
|
7666
7677
|
EditorItemNav,
|
|
7667
7678
|
{
|
|
7679
|
+
embedded: true,
|
|
7668
7680
|
label: editorHeaderLabel,
|
|
7669
7681
|
position: itemPosition.index + 1,
|
|
7670
7682
|
total: itemPosition.total,
|
|
@@ -7717,6 +7729,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7717
7729
|
headerLabel: editorHeaderLabel,
|
|
7718
7730
|
headerSubtitle: editorHeaderSubtitle,
|
|
7719
7731
|
headerMeta: editorHeaderMeta,
|
|
7732
|
+
headerLeading: itemNav,
|
|
7720
7733
|
clipboard: editorClipboard,
|
|
7721
7734
|
actionLabels,
|
|
7722
7735
|
actionIcons,
|
|
@@ -7735,10 +7748,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7735
7748
|
)
|
|
7736
7749
|
}
|
|
7737
7750
|
);
|
|
7738
|
-
const withNav = (node) =>
|
|
7739
|
-
itemNav,
|
|
7740
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: node })
|
|
7741
|
-
] }) : node;
|
|
7751
|
+
const withNav = (node) => node;
|
|
7742
7752
|
if (!previewBody) return withNav(baseEditor());
|
|
7743
7753
|
if (previewMode === "inline") {
|
|
7744
7754
|
return withNav(baseEditor(
|
|
@@ -7841,8 +7851,26 @@ function RecordsAdminShellInner(props) {
|
|
|
7841
7851
|
subtitle: pinnedProduct.item?.sku ?? void 0
|
|
7842
7852
|
}];
|
|
7843
7853
|
}
|
|
7844
|
-
|
|
7845
|
-
|
|
7854
|
+
const configured = scopeCounts.productIds;
|
|
7855
|
+
const all = productBrowse.items.map(productItemToSummary);
|
|
7856
|
+
const isConfigured = (s) => {
|
|
7857
|
+
const pid = s.scope.productId;
|
|
7858
|
+
return !!pid && configured.has(pid);
|
|
7859
|
+
};
|
|
7860
|
+
if (filter === "configured") return all.filter(isConfigured);
|
|
7861
|
+
if (filter === "empty") return all.filter((s) => !isConfigured(s));
|
|
7862
|
+
const yes = [];
|
|
7863
|
+
const no = [];
|
|
7864
|
+
for (const s of all) (isConfigured(s) ? yes : no).push(s);
|
|
7865
|
+
return [...yes, ...no];
|
|
7866
|
+
}, [
|
|
7867
|
+
productPinned,
|
|
7868
|
+
contextScope,
|
|
7869
|
+
productBrowse.items,
|
|
7870
|
+
pinnedProduct.item,
|
|
7871
|
+
scopeCounts.productIds,
|
|
7872
|
+
filter
|
|
7873
|
+
]);
|
|
7846
7874
|
const isRuleTab = activeScope === "rule";
|
|
7847
7875
|
const isGlobalTab = activeScope === "collection";
|
|
7848
7876
|
const isAllTab = activeScope === "all";
|
|
@@ -8281,10 +8309,14 @@ function RecordsAdminShellInner(props) {
|
|
|
8281
8309
|
},
|
|
8282
8310
|
loading: probe.isLoading,
|
|
8283
8311
|
counts: {
|
|
8284
|
-
//
|
|
8285
|
-
//
|
|
8286
|
-
//
|
|
8287
|
-
|
|
8312
|
+
// Products badge counts DISTINCT products that have at
|
|
8313
|
+
// least one custom record — same semantics as Global /
|
|
8314
|
+
// Rules. Catalogue size (which can be 1k–10k+) was
|
|
8315
|
+
// misleading: "Products: 247" implied 247 customised
|
|
8316
|
+
// products when in fact zero might be configured. Falls
|
|
8317
|
+
// back to a lower bound when scope-counts truncated at
|
|
8318
|
+
// the hard cap.
|
|
8319
|
+
product: scopeCounts.productIds.size,
|
|
8288
8320
|
// The remaining tabs show actual record counts so hidden
|
|
8289
8321
|
// state (e.g. a rule-scoped competition) is visible from
|
|
8290
8322
|
// any tab. `useScopeCounts` returns 0 while loading, which
|
|
@@ -8365,6 +8397,27 @@ function RecordsAdminShellInner(props) {
|
|
|
8365
8397
|
i18n
|
|
8366
8398
|
}
|
|
8367
8399
|
),
|
|
8400
|
+
isProductTab && !productPinned && (() => {
|
|
8401
|
+
const cfg = scopeCounts.productIds;
|
|
8402
|
+
let configured = 0;
|
|
8403
|
+
for (const p of productBrowse.items) if (cfg.has(p.id)) configured += 1;
|
|
8404
|
+
const total = productBrowse.items.length;
|
|
8405
|
+
return /* @__PURE__ */ jsx(
|
|
8406
|
+
StatusFilterPills,
|
|
8407
|
+
{
|
|
8408
|
+
value: filter,
|
|
8409
|
+
onChange: setFilter,
|
|
8410
|
+
counts: {
|
|
8411
|
+
all: total,
|
|
8412
|
+
configured,
|
|
8413
|
+
partial: 0,
|
|
8414
|
+
empty: total - configured
|
|
8415
|
+
},
|
|
8416
|
+
hideZero: ["partial"],
|
|
8417
|
+
i18n
|
|
8418
|
+
}
|
|
8419
|
+
);
|
|
8420
|
+
})(),
|
|
8368
8421
|
isRuleTab && /* @__PURE__ */ jsx(
|
|
8369
8422
|
RuleFilterChips,
|
|
8370
8423
|
{
|