@proveanything/smartlinks-utils-ui 0.9.1 → 0.9.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.
@@ -424,6 +424,14 @@ interface RecordsAdminI18n {
424
424
  rulesTabTooltip: string;
425
425
  /** Empty-state body shown inside the Rules tab when no rules exist yet. */
426
426
  rulesEmptyBody: string;
427
+ /**
428
+ * Lifecycle-hook failure toasts. `{message}` is replaced with the
429
+ * thrown error's message (or a generic fallback when none is provided).
430
+ */
431
+ hookBeforeSaveFailed: string;
432
+ hookAfterSaveFailed: string;
433
+ hookBeforeDeleteFailed: string;
434
+ hookAfterDeleteFailed: string;
427
435
  }
428
436
  declare const DEFAULT_I18N: RecordsAdminI18n;
429
437
 
@@ -485,7 +493,17 @@ interface DeepLinkAdapter {
485
493
  subscribe(listener: () => void): () => void;
486
494
  }
487
495
  interface DeepLinkOptions {
488
- /** Master switch — default `false` (opt in per app). */
496
+ /**
497
+ * Master switch. **Default `true` as of v0.10.** Most hosts want URL
498
+ * round-tripping (refresh / share-link restores the open record), so the
499
+ * shell installs a default adapter automatically — `window.location` +
500
+ * `window.history` for standalone hosts, or a postMessage relay when
501
+ * mounted inside a SmartLinks iframe.
502
+ *
503
+ * Set to `false` to run an isolated shell whose state never touches the
504
+ * URL. Useful for embedded previews, modal pickers, or hosts that own
505
+ * a more opinionated URL scheme they don't want the shell to touch.
506
+ */
489
507
  enabled?: boolean;
490
508
  /** Push/replace strategy. Default `'smart'`. */
491
509
  history?: DeepLinkHistoryMode;
@@ -555,6 +573,54 @@ declare function mergeIcons(override?: Partial<RecordsAdminIcons>): RecordsAdmin
555
573
  * explicit `headerIcon` > `icons.header.byRecordType[type]` > `icons.header.default`. */
556
574
  declare function pickHeaderIcon(icons: RecordsAdminIcons, recordType?: string): LucideIcon;
557
575
 
576
+ /** Common context fields passed to every lifecycle hook. */
577
+ interface RecordHookCtx {
578
+ collectionId: string;
579
+ appId: string;
580
+ recordType?: string;
581
+ /** Editing scope kind (`'global' | 'rule' | 'product' | …`). */
582
+ scope: ScopeKind;
583
+ /** Resolved scope ref string when available (e.g. `product:abc`). Most
584
+ * hosts ignore this; provided for parity with non-shell callers. */
585
+ targetRef?: string;
586
+ /** Always `true` from inside the shell; included for symmetry with
587
+ * future non-shell callers. */
588
+ admin: true;
589
+ }
590
+ interface SaveHookCtx<T = unknown> extends RecordHookCtx {
591
+ isCreate: boolean;
592
+ /** Record as it WILL be (in `beforeSave`) or HAS been (in `afterSave`)
593
+ * written. `id` is the resolved UUID when known, otherwise undefined. */
594
+ record: RecordSummary<T>;
595
+ /** Snapshot of the record's previous server state. Undefined on create. */
596
+ before?: RecordSummary<T>;
597
+ }
598
+ interface DeleteHookCtx<T = unknown> extends RecordHookCtx {
599
+ /** Snapshot of the record taken immediately before deletion. */
600
+ record: RecordSummary<T>;
601
+ }
602
+ /**
603
+ * Opt-in lifecycle hooks for `RecordsAdminShell`. All four are awaited.
604
+ *
605
+ * - `beforeSave` — return `false` (or throw) to cancel the write. Return
606
+ * a `Partial<T>` to merge into the record's `data` payload before it
607
+ * hits the server (e.g. inject computed `status`, normalised dates).
608
+ * - `afterSave` — runs after a successful write. Throwing surfaces a
609
+ * toast but does NOT roll back the server state.
610
+ * - `beforeDelete` — return `false` (or throw) to cancel the delete.
611
+ * - `afterDelete` — runs after a successful delete. Throwing surfaces a
612
+ * toast; the record is already gone.
613
+ *
614
+ * `data` is the only host-shaped portion of the payload — anchors and
615
+ * `facetRule` are owned by the shell, so `beforeSave` returns a partial
616
+ * of the typed `data` shape, not of the full SDK record input.
617
+ */
618
+ interface RecordsAdminShellHooks<T = unknown> {
619
+ beforeSave?: (ctx: SaveHookCtx<T>) => Promise<Partial<T> | false | void> | Partial<T> | false | void;
620
+ afterSave?: (ctx: SaveHookCtx<T>) => Promise<void> | void;
621
+ beforeDelete?: (ctx: DeleteHookCtx<T>) => Promise<false | void> | false | void;
622
+ afterDelete?: (ctx: DeleteHookCtx<T>) => Promise<void> | void;
623
+ }
558
624
  /**
559
625
  * Footer / banner action keys whose label and icon can be customised by
560
626
  * the host. `save`, `discard`, `delete` are wired today. `saveAll` /
@@ -714,6 +780,15 @@ interface RecordsAdminShellProps<TData = unknown> {
714
780
  unsaved?: UnsavedConfig<TData>;
715
781
  clipboard?: ClipboardConfig<TData>;
716
782
  actions?: ActionsConfig;
783
+ /**
784
+ * Opt-in awaited callbacks fired around record save/delete. See
785
+ * {@link RecordsAdminShellHooks} for the contract.
786
+ *
787
+ * Today these fire on the single-record paths (editor footer Save/Delete
788
+ * and the right-pane item-list trash). Bulk paths (CSV import, paste,
789
+ * Save-all) do NOT fire hooks yet — tracked as a follow-up.
790
+ */
791
+ hooks?: RecordsAdminShellHooks<TData>;
717
792
  /**
718
793
  * Mirror the shell's runtime state into URL params. Off by default. The
719
794
  * shell only owns `item`, `scope`, `view` — host platform params are
@@ -1311,13 +1386,19 @@ interface PreviewScopePickerProps {
1311
1386
  /** Are variants/batches available for drill-down. */
1312
1387
  showVariants: boolean;
1313
1388
  showBatches: boolean;
1389
+ /** Active rail tab. The picker hides itself on product/variant/batch
1390
+ * tabs because the editing scope already pins a product there. */
1391
+ activeScope?: ScopeKind;
1314
1392
  /** i18n strings (uses defaults if omitted). */
1315
1393
  i18n?: {
1316
1394
  previewAs?: string;
1317
1395
  previewAsDefault?: string;
1396
+ change?: string;
1397
+ searchProducts?: string;
1398
+ close?: string;
1318
1399
  };
1319
1400
  }
1320
- declare const PreviewScopePicker: ({ SL, collectionId, editingScope, value, onChange, showVariants, showBatches, i18n, }: PreviewScopePickerProps) => react_jsx_runtime.JSX.Element | null;
1401
+ declare const PreviewScopePicker: ({ SL, collectionId, editingScope, value, onChange, showVariants, showBatches, activeScope, i18n, }: PreviewScopePickerProps) => react_jsx_runtime.JSX.Element | null;
1321
1402
 
1322
1403
  declare const ScopeBreadcrumb: ({ scope }: {
1323
1404
  scope: ParsedRef;
@@ -2134,6 +2215,12 @@ interface Props$5<T> {
2134
2215
  error: Error | null;
2135
2216
  ctx: ItemViewContext;
2136
2217
  itemNoun: string;
2218
+ /**
2219
+ * Optional one-line rule summary shown beneath the toolbar — used in
2220
+ * collection-mode when an item list is scoped to a specific rule, so the
2221
+ * admin sees which rule's items they're viewing without leaving the pane.
2222
+ */
2223
+ ruleSummary?: string | null;
2137
2224
  view: ItemView;
2138
2225
  views: ItemView[];
2139
2226
  onViewChange: (view: ItemView) => void;
@@ -2145,7 +2232,7 @@ interface Props$5<T> {
2145
2232
  cardSize?: 'sm' | 'md' | 'lg';
2146
2233
  i18n: RecordsAdminI18n;
2147
2234
  }
2148
- declare function ItemListView<T>({ items, isLoading, error, ctx, itemNoun, view, views, onViewChange, renderItemList, renderItemCard, renderItemEmpty, itemColumns, cardSize, i18n, }: Props$5<T>): react_jsx_runtime.JSX.Element;
2235
+ declare function ItemListView<T>({ items, isLoading, error, ctx, itemNoun, ruleSummary, view, views, onViewChange, renderItemList, renderItemCard, renderItemEmpty, itemColumns, cardSize, i18n, }: Props$5<T>): react_jsx_runtime.JSX.Element;
2149
2236
 
2150
2237
  interface Props$4 {
2151
2238
  options: ItemView[];