@proveanything/smartlinks-utils-ui 0.11.5 → 0.11.7

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.
@@ -3397,7 +3397,7 @@ var RowContextMenu = ({
3397
3397
  onCopy();
3398
3398
  },
3399
3399
  children: [
3400
- /* @__PURE__ */ jsx(Copy, { className: "w-3 h-3", "aria-hidden": "true" }),
3400
+ /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5 opacity-70", "aria-hidden": "true" }),
3401
3401
  /* @__PURE__ */ jsx("span", { children: i18n.copy })
3402
3402
  ]
3403
3403
  }
@@ -3414,7 +3414,7 @@ var RowContextMenu = ({
3414
3414
  onDuplicate();
3415
3415
  },
3416
3416
  children: [
3417
- /* @__PURE__ */ jsx(CopyPlus, { className: "w-3 h-3", "aria-hidden": "true" }),
3417
+ /* @__PURE__ */ jsx(CopyPlus, { className: "w-3.5 h-3.5 opacity-70", "aria-hidden": "true" }),
3418
3418
  /* @__PURE__ */ jsx("span", { children: i18n.duplicateAction })
3419
3419
  ]
3420
3420
  }
@@ -3438,7 +3438,7 @@ var RowContextMenu = ({
3438
3438
  void action.onAction();
3439
3439
  },
3440
3440
  children: [
3441
- Icon && /* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }),
3441
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5 opacity-70" }),
3442
3442
  /* @__PURE__ */ jsx("span", { children: action.label })
3443
3443
  ]
3444
3444
  },
@@ -6594,12 +6594,15 @@ function NewRuleWizard({
6594
6594
  canChooseSeed = false,
6595
6595
  seedMode = null,
6596
6596
  onSeedModeChange,
6597
+ pasteSourceLabel,
6597
6598
  facets,
6598
6599
  children,
6599
- itemNoun = "record"
6600
+ itemNoun = "record",
6601
+ seedPromptMode = "inline"
6600
6602
  }) {
6601
6603
  const preview = useRulePreview({ SL, collectionId, appId, rule });
6602
6604
  const canProceed = isFacetRuleValid(rule);
6605
+ const showSeedPicker = (canChooseSeed || pasteSourceLabel) && seedPromptMode === "inline";
6603
6606
  if (step === 1) {
6604
6607
  return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
6605
6608
  /* @__PURE__ */ jsx(
@@ -6624,7 +6627,7 @@ function NewRuleWizard({
6624
6627
  description: "The new rule will apply to every product whose facets match every clause below."
6625
6628
  }
6626
6629
  ),
6627
- canChooseSeed && /* @__PURE__ */ jsxs(
6630
+ showSeedPicker && /* @__PURE__ */ jsxs(
6628
6631
  "div",
6629
6632
  {
6630
6633
  className: "mt-4 rounded-lg border p-3",
@@ -6635,7 +6638,7 @@ function NewRuleWizard({
6635
6638
  children: [
6636
6639
  /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
6637
6640
  /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", style: { color: "hsl(var(--ra-text))" }, children: "Start from" }),
6638
- /* @__PURE__ */ jsx("div", { className: "text-xs", style: { color: "hsl(var(--ra-muted-text))" }, children: "Choose whether the new rule starts empty or copies the current global record." })
6641
+ /* @__PURE__ */ jsx("div", { className: "text-xs", style: { color: "hsl(var(--ra-muted-text))" }, children: "Choose whether the new rule starts empty, copies the current global record, or pastes from your clipboard." })
6639
6642
  ] }),
6640
6643
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
6641
6644
  /* @__PURE__ */ jsx(
@@ -6643,12 +6646,12 @@ function NewRuleWizard({
6643
6646
  {
6644
6647
  type: "button",
6645
6648
  className: "ra-btn",
6646
- "data-variant": seedMode !== "global" ? "primary" : "ghost",
6649
+ "data-variant": seedMode === "blank" || seedMode == null ? "primary" : "ghost",
6647
6650
  onClick: () => onSeedModeChange?.("blank"),
6648
6651
  children: "Start blank"
6649
6652
  }
6650
6653
  ),
6651
- /* @__PURE__ */ jsx(
6654
+ canChooseSeed && /* @__PURE__ */ jsx(
6652
6655
  "button",
6653
6656
  {
6654
6657
  type: "button",
@@ -6657,6 +6660,17 @@ function NewRuleWizard({
6657
6660
  onClick: () => onSeedModeChange?.("global"),
6658
6661
  children: "Copy from global"
6659
6662
  }
6663
+ ),
6664
+ pasteSourceLabel && /* @__PURE__ */ jsx(
6665
+ "button",
6666
+ {
6667
+ type: "button",
6668
+ className: "ra-btn",
6669
+ "data-variant": seedMode === "paste" ? "primary" : "ghost",
6670
+ onClick: () => onSeedModeChange?.("paste"),
6671
+ title: `Paste from ${pasteSourceLabel}`,
6672
+ children: "Paste from clipboard"
6673
+ }
6660
6674
  )
6661
6675
  ] })
6662
6676
  ]
@@ -7967,6 +7981,11 @@ function RecordsAdminShellInner(props) {
7967
7981
  scopeKind: "rule",
7968
7982
  enabled: true
7969
7983
  });
7984
+ const globalScopedList = useRecordList({
7985
+ ctx,
7986
+ scopeKind: "collection",
7987
+ enabled: cardinality === "singleton"
7988
+ });
7970
7989
  const pinnedProduct = useSingleProduct({
7971
7990
  SL,
7972
7991
  collectionId,
@@ -8127,21 +8146,60 @@ function RecordsAdminShellInner(props) {
8127
8146
  enabled: !!editingTargetScope
8128
8147
  });
8129
8148
  const globalSourceRecord = useMemo(
8130
- () => recordList.items.find((it) => !it.scope.productId && !it.scope.facetId && !it.scope.variantId && !it.scope.batchId && !it.scope.proofId && !it.facetRule),
8131
- [recordList.items]
8149
+ () => {
8150
+ const pool = globalScopedList.items.length ? globalScopedList.items : recordList.items;
8151
+ return pool.find((it) => !it.scope.productId && !it.scope.facetId && !it.scope.variantId && !it.scope.batchId && !it.scope.proofId && !it.facetRule);
8152
+ },
8153
+ [globalScopedList.items, recordList.items]
8132
8154
  );
8155
+ const resolvedGlobalSeed = useResolvedRecord({
8156
+ SL,
8157
+ appId,
8158
+ recordType,
8159
+ collectionId,
8160
+ supportedScopes: ["collection"],
8161
+ enabled: cardinality === "singleton" && activeScope === "rule" && ruleWizardStep !== null
8162
+ });
8163
+ const directGlobalSeedQuery = useQuery({
8164
+ queryKey: ["records-admin", "global-seed", collectionId, appId, recordType ?? null],
8165
+ enabled: cardinality === "singleton" && activeScope === "rule" && ruleWizardStep !== null,
8166
+ staleTime: 15e3,
8167
+ queryFn: async () => {
8168
+ const res = await listRecords({ SL, collectionId, appId, recordType }, { limit: 200, offset: 0 });
8169
+ return res.data.find((rec) => !rec.productId && !rec.variantId && !rec.batchId && !rec.proofId && !rec.facetRule) ?? null;
8170
+ }
8171
+ });
8172
+ const directGlobalSeedData = directGlobalSeedQuery.data?.data;
8173
+ const singletonGlobalSeedAvailable = !!(globalSourceRecord?.data ?? directGlobalSeedData ?? ((resolvedGlobalSeed.source === "self" || resolvedGlobalSeed.source === "inherited") && resolvedGlobalSeed.data));
8174
+ const wizardClipboard = useRecordClipboard({
8175
+ appId,
8176
+ recordType: recordType ?? "__default"
8177
+ });
8133
8178
  const ruleWizardInitialData = useMemo(() => {
8134
- if (ruleWizardSeedMode !== "global") return void 0;
8135
- if (!globalSourceRecord?.data) return defaultData?.();
8136
- if (onCopyOverride) {
8137
- return onCopyOverride({ value: globalSourceRecord.data, scope: globalSourceRecord.scope });
8179
+ if (ruleWizardSeedMode === "global") {
8180
+ const globalSeedSource = globalSourceRecord?.data ?? directGlobalSeedData ?? resolvedGlobalSeed.data;
8181
+ if (!globalSeedSource) return defaultData?.();
8182
+ const globalSeedScope = globalSourceRecord?.scope ?? parseRef("");
8183
+ if (onCopyOverride) {
8184
+ return onCopyOverride({ value: globalSeedSource, scope: globalSeedScope });
8185
+ }
8186
+ try {
8187
+ return structuredClone(globalSeedSource);
8188
+ } catch {
8189
+ return JSON.parse(JSON.stringify(globalSeedSource));
8190
+ }
8138
8191
  }
8139
- try {
8140
- return structuredClone(globalSourceRecord.data);
8141
- } catch {
8142
- return JSON.parse(JSON.stringify(globalSourceRecord.data));
8192
+ if (ruleWizardSeedMode === "paste") {
8193
+ const entry = wizardClipboard.entry;
8194
+ if (!entry) return defaultData?.();
8195
+ try {
8196
+ return structuredClone(entry.value);
8197
+ } catch {
8198
+ return JSON.parse(JSON.stringify(entry.value));
8199
+ }
8143
8200
  }
8144
- }, [ruleWizardSeedMode, globalSourceRecord, onCopyOverride, defaultData]);
8201
+ return void 0;
8202
+ }, [ruleWizardSeedMode, globalSourceRecord, directGlobalSeedData, resolvedGlobalSeed.data, onCopyOverride, defaultData, wizardClipboard.entry]);
8145
8203
  const refetchAll = useCallback(async () => {
8146
8204
  await Promise.all([
8147
8205
  recordList.refetch(),
@@ -8634,9 +8692,13 @@ function RecordsAdminShellInner(props) {
8634
8692
  if (!isRuleTab) return void 0;
8635
8693
  if (isCollection) return void 0;
8636
8694
  return (record) => {
8637
- const hash = ruleHash(record.facetRule);
8638
- if (!hash) return null;
8639
- return { key: `rule:${hash}`, label: summariseRule(record.facetRule, ruleLabelLookup) };
8695
+ const rule = record.facetRule;
8696
+ if (!rule || !Array.isArray(rule.all) || rule.all.length === 0) return null;
8697
+ const keys = rule.all.map((c) => c.facetKey).filter((k) => !!k).slice().sort();
8698
+ if (keys.length === 0) return null;
8699
+ const key = `facets:${keys.join("|")}`;
8700
+ const label2 = keys.map((k) => ruleLabelLookup?.facetLabel?.(k) ?? k).join(" \xB7 ");
8701
+ return { key, label: label2 };
8640
8702
  };
8641
8703
  }, [groupBy, isRuleTab, isAllTab, isCollection, ruleLabelLookup]);
8642
8704
  const [bulkRuleEditTarget, setBulkRuleEditTarget] = useState(null);
@@ -8678,6 +8740,7 @@ function RecordsAdminShellInner(props) {
8678
8740
  const renderRuleGroupActions = useCallback(
8679
8741
  (group) => {
8680
8742
  if (!isRuleTab || groupBy) return null;
8743
+ if (!isCollection) return null;
8681
8744
  const ids = group.items.map((it) => it.id).filter((id) => !!id);
8682
8745
  if (ids.length < 2) return null;
8683
8746
  const rule = group.items.find((it) => it.facetRule)?.facetRule ?? null;
@@ -8696,15 +8759,15 @@ function RecordsAdminShellInner(props) {
8696
8759
  }
8697
8760
  );
8698
8761
  },
8699
- [isRuleTab, groupBy]
8762
+ [isRuleTab, groupBy, isCollection]
8700
8763
  );
8701
- const onCreateRule = useCallback(() => {
8764
+ const onCreateRule = useCallback((seed) => {
8702
8765
  void runWithGuard(() => {
8703
8766
  if (activeScope !== "rule") setActiveScope("rule");
8704
8767
  setSelectedRecordId(null);
8705
8768
  setSelectedItemId(null);
8706
8769
  setDraftKind("rule");
8707
- setRuleWizardSeedMode("blank");
8770
+ setRuleWizardSeedMode(seed ?? "blank");
8708
8771
  setRuleWizardDraftKey(null);
8709
8772
  setRuleWizardRule({ all: [] });
8710
8773
  setRuleWizardStep(1);
@@ -8724,10 +8787,13 @@ function RecordsAdminShellInner(props) {
8724
8787
  setRuleWizardStep(2);
8725
8788
  } else {
8726
8789
  setRuleWizardStep(2);
8790
+ if (ruleWizardSeedMode == null) {
8791
+ setRuleWizardSeedMode(singletonGlobalSeedAvailable ? "global" : "blank");
8792
+ }
8727
8793
  setRuleWizardDraftKey(mintRuleWizardDraftKey());
8728
8794
  setSelectedRecordId(DRAFT_ID3);
8729
8795
  }
8730
- }, [cardinality, mintRuleWizardDraftKey]);
8796
+ }, [cardinality, mintRuleWizardDraftKey, ruleWizardSeedMode, singletonGlobalSeedAvailable, setRuleWizardSeedMode]);
8731
8797
  const onRuleWizardBack = useCallback(() => {
8732
8798
  setRuleWizardStep(1);
8733
8799
  setRuleWizardDraftKey(null);
@@ -9173,20 +9239,37 @@ function RecordsAdminShellInner(props) {
9173
9239
  }
9174
9240
  ) }),
9175
9241
  /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-2.5 border-b", style: { borderColor: "hsl(var(--ra-border))" }, children: [
9176
- isRuleTab && /* @__PURE__ */ jsxs(
9177
- "button",
9178
- {
9179
- type: "button",
9180
- onClick: onCreateRule,
9181
- className: "ra-btn w-full",
9182
- "data-variant": "primary",
9183
- "aria-label": "New rule",
9184
- children: [
9185
- /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5", "aria-hidden": "true" }),
9186
- /* @__PURE__ */ jsx("span", { children: "New rule" })
9187
- ]
9188
- }
9189
- ),
9242
+ isRuleTab && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
9243
+ /* @__PURE__ */ jsxs(
9244
+ "button",
9245
+ {
9246
+ type: "button",
9247
+ onClick: () => onCreateRule(),
9248
+ className: "ra-btn w-full",
9249
+ "data-variant": "primary",
9250
+ "aria-label": "New rule",
9251
+ children: [
9252
+ /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5", "aria-hidden": "true" }),
9253
+ /* @__PURE__ */ jsx("span", { children: "New rule" })
9254
+ ]
9255
+ }
9256
+ ),
9257
+ wizardClipboard.entry && /* @__PURE__ */ jsxs(
9258
+ "button",
9259
+ {
9260
+ type: "button",
9261
+ onClick: () => onCreateRule("paste"),
9262
+ className: "ra-btn w-full",
9263
+ "data-variant": "ghost",
9264
+ "aria-label": "Paste as new rule",
9265
+ title: wizardClipboard.entry.sourceLabel ? `Paste from ${wizardClipboard.entry.sourceLabel}` : "Paste from clipboard",
9266
+ children: [
9267
+ /* @__PURE__ */ jsx(ClipboardPaste, { className: "w-3.5 h-3.5", "aria-hidden": "true" }),
9268
+ /* @__PURE__ */ jsx("span", { children: "Paste as new rule" })
9269
+ ]
9270
+ }
9271
+ )
9272
+ ] }),
9190
9273
  showCreateGlobal && /* @__PURE__ */ jsxs(
9191
9274
  "button",
9192
9275
  {
@@ -9336,13 +9419,72 @@ function RecordsAdminShellInner(props) {
9336
9419
  onCancel: onCancelRuleWizard,
9337
9420
  onNext: onRuleWizardNext,
9338
9421
  onBack: onRuleWizardBack,
9339
- canChooseSeed: !isCollection && !!globalSourceRecord,
9422
+ canChooseSeed: !isCollection && singletonGlobalSeedAvailable,
9340
9423
  seedMode: ruleWizardSeedMode,
9341
9424
  onSeedModeChange: setRuleWizardSeedMode,
9425
+ pasteSourceLabel: wizardClipboard.entry?.sourceLabel ?? (wizardClipboard.entry ? "clipboard" : void 0),
9342
9426
  facets: ruleWizardFacets,
9343
9427
  itemNoun,
9428
+ seedPromptMode: !isCollection ? "after-next" : "inline",
9344
9429
  children: [
9345
- ruleWizardStep === 2 && !isCollection && editingTargetScope && renderEditorWithPreview(),
9430
+ ruleWizardStep === 2 && !isCollection && /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
9431
+ /* @__PURE__ */ jsxs(
9432
+ "div",
9433
+ {
9434
+ className: "border-b px-5 py-3",
9435
+ style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" },
9436
+ children: [
9437
+ /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
9438
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", style: { color: "hsl(var(--ra-text))" }, children: "Start from" }),
9439
+ /* @__PURE__ */ jsx("div", { className: "text-xs", style: { color: "hsl(var(--ra-muted-text))" }, children: "Choose whether the new rule starts empty, copies the current global record, or pastes from your clipboard." })
9440
+ ] }),
9441
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
9442
+ /* @__PURE__ */ jsx(
9443
+ "button",
9444
+ {
9445
+ type: "button",
9446
+ className: "ra-btn",
9447
+ "data-variant": ruleWizardSeedMode === "blank" || ruleWizardSeedMode == null ? "primary" : "ghost",
9448
+ onClick: () => {
9449
+ setRuleWizardSeedMode("blank");
9450
+ setRuleWizardDraftKey(mintRuleWizardDraftKey());
9451
+ },
9452
+ children: "Start blank"
9453
+ }
9454
+ ),
9455
+ singletonGlobalSeedAvailable && /* @__PURE__ */ jsx(
9456
+ "button",
9457
+ {
9458
+ type: "button",
9459
+ className: "ra-btn",
9460
+ "data-variant": ruleWizardSeedMode === "global" ? "primary" : "ghost",
9461
+ onClick: () => {
9462
+ setRuleWizardSeedMode("global");
9463
+ setRuleWizardDraftKey(mintRuleWizardDraftKey());
9464
+ },
9465
+ children: "Copy from global"
9466
+ }
9467
+ ),
9468
+ wizardClipboard.entry && /* @__PURE__ */ jsx(
9469
+ "button",
9470
+ {
9471
+ type: "button",
9472
+ className: "ra-btn",
9473
+ "data-variant": ruleWizardSeedMode === "paste" ? "primary" : "ghost",
9474
+ onClick: () => {
9475
+ setRuleWizardSeedMode("paste");
9476
+ setRuleWizardDraftKey(mintRuleWizardDraftKey());
9477
+ },
9478
+ title: wizardClipboard.entry.sourceLabel ? `Paste from ${wizardClipboard.entry.sourceLabel}` : "Paste from clipboard",
9479
+ children: "Paste from clipboard"
9480
+ }
9481
+ )
9482
+ ] })
9483
+ ]
9484
+ }
9485
+ ),
9486
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: editingTargetScope && renderEditorWithPreview() })
9487
+ ] }),
9346
9488
  ruleWizardStep === 2 && isCollection && !selectedItemId && /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center px-6 py-10", children: /* @__PURE__ */ jsxs("div", { className: "max-w-sm text-center space-y-3", children: [
9347
9489
  /* @__PURE__ */ jsxs(
9348
9490
  "h3",