@proveanything/smartlinks-utils-ui 0.7.4 → 0.7.5
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.
|
@@ -727,6 +727,14 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
727
727
|
csvSchema?: CsvSchema<TData>;
|
|
728
728
|
classify?: (record: RecordSummary<TData>) => RecordStatus;
|
|
729
729
|
defaultData?: () => TData;
|
|
730
|
+
/**
|
|
731
|
+
* Optional derivation for the label that represents an in-flight draft
|
|
732
|
+
* in the unsaved-changes tray. Receives the editor's current value and
|
|
733
|
+
* its scope; return a short, human-readable title (or `undefined` to
|
|
734
|
+
* defer to the built-in heuristic). Useful when your record shape nests
|
|
735
|
+
* the title under a custom key the heuristic doesn't know about.
|
|
736
|
+
*/
|
|
737
|
+
deriveDraftLabel?: (value: TData, scope: ParsedRef) => string | undefined;
|
|
730
738
|
/**
|
|
731
739
|
* Which layouts the rail offers. Default `['list']`. When more than one is
|
|
732
740
|
* supplied, a switcher appears above the list and the choice persists
|
|
@@ -1566,6 +1574,15 @@ interface UseRecordEditorArgs<T> {
|
|
|
1566
1574
|
* back a concrete `recordId`.
|
|
1567
1575
|
*/
|
|
1568
1576
|
createMode?: boolean;
|
|
1577
|
+
/**
|
|
1578
|
+
* Optional host-supplied derivation for the label this editor registers
|
|
1579
|
+
* with the unsaved-changes tray. Receives the in-flight value and the
|
|
1580
|
+
* scope; should return a short, human-readable title. When omitted (or
|
|
1581
|
+
* when it returns `undefined`), the hook falls back to a built-in heuristic
|
|
1582
|
+
* that scans common title-shaped fields (`title`, `display.title`,
|
|
1583
|
+
* `name`, `label`, `heading`, `question`, `slug`).
|
|
1584
|
+
*/
|
|
1585
|
+
deriveDraftLabel?: (value: T, scope: ParsedRef) => string | undefined;
|
|
1569
1586
|
}
|
|
1570
1587
|
declare function useRecordEditor<T>(args: UseRecordEditorArgs<T>): EditorContext<T>;
|
|
1571
1588
|
|
|
@@ -692,7 +692,8 @@ function useRecordEditor(args) {
|
|
|
692
692
|
onSaveError,
|
|
693
693
|
reseed = "always",
|
|
694
694
|
initialFacetRule = null,
|
|
695
|
-
createMode = false
|
|
695
|
+
createMode = false,
|
|
696
|
+
deriveDraftLabel
|
|
696
697
|
} = args;
|
|
697
698
|
const queryClient = useQueryClient();
|
|
698
699
|
const draftStore = useDirtyDraftStore();
|
|
@@ -857,11 +858,29 @@ function useRecordEditor(args) {
|
|
|
857
858
|
const anchors = parsedRefToScope(scope);
|
|
858
859
|
const saveKind = resolved.recordId && resolved.source === "self" ? "update" : createMode ? "create" : "upsert";
|
|
859
860
|
const deriveLabel = () => {
|
|
861
|
+
if (deriveDraftLabel) {
|
|
862
|
+
try {
|
|
863
|
+
const custom = deriveDraftLabel(value, scope);
|
|
864
|
+
if (typeof custom === "string" && custom.trim()) return custom.trim();
|
|
865
|
+
} catch {
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
const KEYS = ["title", "name", "label", "heading", "question", "slug"];
|
|
869
|
+
const pickString = (obj) => {
|
|
870
|
+
if (!obj || typeof obj !== "object") return void 0;
|
|
871
|
+
for (const key of KEYS) {
|
|
872
|
+
const raw = obj[key];
|
|
873
|
+
if (typeof raw === "string" && raw.trim()) return raw.trim();
|
|
874
|
+
}
|
|
875
|
+
return void 0;
|
|
876
|
+
};
|
|
860
877
|
const v = value;
|
|
878
|
+
const top = pickString(v);
|
|
879
|
+
if (top) return top;
|
|
861
880
|
if (v && typeof v === "object") {
|
|
862
|
-
for (const
|
|
863
|
-
const
|
|
864
|
-
if (
|
|
881
|
+
for (const wrapper of ["display", "content", "meta", "data"]) {
|
|
882
|
+
const nested = pickString(v[wrapper]);
|
|
883
|
+
if (nested) return nested;
|
|
865
884
|
}
|
|
866
885
|
}
|
|
867
886
|
if (scope.raw?.startsWith("item:")) return "Untitled item";
|
|
@@ -4668,6 +4687,11 @@ styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(-
|
|
|
4668
4687
|
var TOP_LEVEL_SCOPES = ["collection", "rule", "product"];
|
|
4669
4688
|
var WARNED_FACET_DEPRECATED = false;
|
|
4670
4689
|
var DRAFT_ID = "__draft__";
|
|
4690
|
+
var isDraftId = (id) => !!id && (id === DRAFT_ID || id.startsWith("draft:"));
|
|
4691
|
+
var mintDraftItemId = () => {
|
|
4692
|
+
const rand = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
4693
|
+
return `draft:${rand}`;
|
|
4694
|
+
};
|
|
4671
4695
|
var productItemToSummary = (p) => {
|
|
4672
4696
|
const ref = buildRef({ productId: p.id });
|
|
4673
4697
|
return {
|
|
@@ -4749,7 +4773,8 @@ function RecordsAdminShellInner(props) {
|
|
|
4749
4773
|
renderItemEmpty,
|
|
4750
4774
|
collectionRailMode = "siblings",
|
|
4751
4775
|
// Deep linking
|
|
4752
|
-
deepLink
|
|
4776
|
+
deepLink,
|
|
4777
|
+
deriveDraftLabel
|
|
4753
4778
|
} = props;
|
|
4754
4779
|
const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
|
|
4755
4780
|
const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
|
|
@@ -5060,7 +5085,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5060
5085
|
// fall back to anchor-based `match()` at the collection root and the
|
|
5061
5086
|
// editor would mount against `null` data — surfacing as the host's
|
|
5062
5087
|
// "Select a {noun} from the list to edit" placeholder.
|
|
5063
|
-
recordId: isCollection && selectedItemId && selectedItemId
|
|
5088
|
+
recordId: isCollection && selectedItemId && !isDraftId(selectedItemId) ? selectedItemId : selectedRecordId && !isDraftId(selectedRecordId) ? selectedRecordId : void 0,
|
|
5064
5089
|
supportedScopes: supportedForResolution,
|
|
5065
5090
|
enabled: !!editingTargetScope
|
|
5066
5091
|
});
|
|
@@ -5115,7 +5140,8 @@ function RecordsAdminShellInner(props) {
|
|
|
5115
5140
|
setSelectedBatchId(void 0);
|
|
5116
5141
|
}
|
|
5117
5142
|
refetchAll();
|
|
5118
|
-
}
|
|
5143
|
+
},
|
|
5144
|
+
deriveDraftLabel
|
|
5119
5145
|
});
|
|
5120
5146
|
useUnsavedGuard({
|
|
5121
5147
|
isDirty: editorCtx.isDirty,
|
|
@@ -5386,7 +5412,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5386
5412
|
const onItemCreate = useCallback(() => {
|
|
5387
5413
|
if (!isCollection) return;
|
|
5388
5414
|
void runWithGuard(() => {
|
|
5389
|
-
const id = generateItemId ? generateItemId() :
|
|
5415
|
+
const id = generateItemId ? generateItemId() : mintDraftItemId();
|
|
5390
5416
|
setSelectedItemId(id);
|
|
5391
5417
|
onTelemetry?.({ type: "item.create", recordType, scopeRef: baseScopeRef });
|
|
5392
5418
|
deepLinkState.emit({ recordId: null, scope: baseScopeRef || null }, "record.open");
|
|
@@ -5394,7 +5420,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5394
5420
|
}, [isCollection, runWithGuard, generateItemId, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
|
|
5395
5421
|
const onItemDelete = useCallback(async (itemId) => {
|
|
5396
5422
|
if (!isCollection) return;
|
|
5397
|
-
if (itemId
|
|
5423
|
+
if (isDraftId(itemId)) return;
|
|
5398
5424
|
if (onBeforeDelete) {
|
|
5399
5425
|
const ok = await onBeforeDelete(editingScope ?? parseRef(""));
|
|
5400
5426
|
if (!ok) return;
|
|
@@ -5475,7 +5501,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5475
5501
|
i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
|
|
5476
5502
|
}
|
|
5477
5503
|
) : null;
|
|
5478
|
-
const itemNav = isCollection && selectedItemId && itemPosition ? /* @__PURE__ */ jsx(
|
|
5504
|
+
const itemNav = isCollection && selectedItemId && itemPosition && ruleWizardStep === null ? /* @__PURE__ */ jsx(
|
|
5479
5505
|
EditorItemNav,
|
|
5480
5506
|
{
|
|
5481
5507
|
label: editorHeaderLabel,
|
|
@@ -5649,7 +5675,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5649
5675
|
}, []);
|
|
5650
5676
|
const onRuleWizardCreateItem = useCallback(() => {
|
|
5651
5677
|
if (!isCollection) return;
|
|
5652
|
-
const id = generateItemId ? generateItemId() :
|
|
5678
|
+
const id = generateItemId ? generateItemId() : mintDraftItemId();
|
|
5653
5679
|
setSelectedItemId(id);
|
|
5654
5680
|
}, [isCollection, generateItemId]);
|
|
5655
5681
|
const hasGlobalRecord = useMemo(
|
|
@@ -5899,7 +5925,7 @@ function RecordsAdminShellInner(props) {
|
|
|
5899
5925
|
className: "flex-1 grid border-t overflow-hidden",
|
|
5900
5926
|
style: { gridTemplateColumns: "minmax(260px, 320px) 1fr", borderColor: "hsl(var(--ra-border))", marginTop: "0.75rem" },
|
|
5901
5927
|
children: [
|
|
5902
|
-
/* @__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" ? /* @__PURE__ */ jsx(
|
|
5928
|
+
/* @__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(
|
|
5903
5929
|
SiblingRail,
|
|
5904
5930
|
{
|
|
5905
5931
|
items: collectionItems.items,
|