@proveanything/smartlinks-utils-ui 0.3.9 → 0.3.11

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.
@@ -1,12 +1,23 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ComponentType, ReactNode } from 'react';
2
+ import { ReactNode, ComponentType } from 'react';
3
3
  import * as _proveanything_smartlinks_dist_types_appObjects from '@proveanything/smartlinks/dist/types/appObjects';
4
4
  import { MatchedAt, FacetRule, RecordScope, AppRecord, RecordTarget, MatchResult, MatchEntry } from '@proveanything/smartlinks/dist/types/appObjects';
5
5
  import { LucideIcon } from 'lucide-react';
6
6
  import * as _tanstack_query_core from '@tanstack/query-core';
7
7
  import { InfiniteData } from '@tanstack/react-query';
8
8
 
9
- type ScopeKind = 'product' | 'facet' | 'variant' | 'batch';
9
+ /**
10
+ * Where a record is anchored in the inheritance chain.
11
+ *
12
+ * - `collection` — terminal rung (collection-wide default). Inherited by every
13
+ * product/facet/variant/batch when nothing more specific exists. Most useful
14
+ * for collection-cardinality records (a global pool of FAQs / recipes / SOPs).
15
+ * - `facet` — anchored to a facet value (e.g. `bagel-type=white`).
16
+ * - `product` — anchored to a product.
17
+ * - `variant` — anchored to a product variant.
18
+ * - `batch` — anchored to a product batch.
19
+ */
20
+ type ScopeKind = 'collection' | 'product' | 'facet' | 'variant' | 'batch';
10
21
  /** Parsed `ref` string — see `data/refs.ts`. Format: `kind:id` or chain. */
11
22
  interface ParsedRef {
12
23
  /** Most-specific scope this ref points at. */
@@ -20,6 +31,13 @@ interface ParsedRef {
20
31
  variantId?: string;
21
32
  batchId?: string;
22
33
  proofId?: string;
34
+ /**
35
+ * For `collection` cardinality records: the per-item identifier within the
36
+ * scope. Singleton records leave this undefined. The full ref is
37
+ * `{scopeRef}/item:{itemId}`, or just `item:{itemId}` for collection-rooted
38
+ * items.
39
+ */
40
+ itemId?: string;
23
41
  }
24
42
 
25
43
  type RecordSource = 'self' | 'inherited' | 'empty';
@@ -104,14 +122,27 @@ interface CsvSchema<TData> {
104
122
  }
105
123
 
106
124
  /**
107
- * How records are laid out in the browse rail / panel.
108
- * - `list` → dense rows with status dot + label + subtitle (default).
109
- * - `grid` → square cards with thumbnail + label.
110
- * - `gallery` → larger 16:9 cards with thumbnail + label + subtitle.
111
- * - `compact` → minimal one-line rows (no subtitle, no status dot).
125
+ * How records are laid out in the **left rail** (the navigator).
126
+ *
127
+ * The rail is intentionally a dense tree/list — cards or galleries belong on
128
+ * the right pane, not in a 260px column. Only the row densities are offered:
129
+ *
130
+ * - `list` → dense rows with status dot + label + subtitle (default).
131
+ * - `compact` → minimal one-line rows (no subtitle, no status dot).
112
132
  */
113
- type RecordPresentation = 'list' | 'grid' | 'gallery' | 'compact';
133
+ type RecordPresentation = 'list' | 'compact';
114
134
  declare const ALL_PRESENTATIONS: RecordPresentation[];
135
+ /**
136
+ * How a multi-item collection is rendered in the **right pane** when a scope
137
+ * is selected and no item is open. Right-pane only — cards and galleries
138
+ * have the room to breathe here.
139
+ *
140
+ * - `table` → declarative columns (built-in default with `itemColumns`).
141
+ * - `cards` → square cards with thumbnail + label.
142
+ * - `gallery` → larger 16:9 cards with thumbnail + label + subtitle.
143
+ */
144
+ type ItemView = 'table' | 'cards' | 'gallery';
145
+ declare const ALL_ITEM_VIEWS: ItemView[];
115
146
  /**
116
147
  * Whether each scope holds at most one record of this type, or many.
117
148
  * - `singleton` → one record per scope (e.g. washing instructions). Default.
@@ -131,6 +162,17 @@ type CollectedSort = {
131
162
  field: string;
132
163
  direction?: 'asc' | 'desc';
133
164
  };
165
+ /**
166
+ * What the left rail shows once an item is open in the editor (collection
167
+ * cardinality only):
168
+ *
169
+ * - `siblings` *(default)* — rail flips to the list of items in the current
170
+ * scope. Click any sibling to switch instantly. A pinned `← All scopes`
171
+ * link returns to scope navigation.
172
+ * - `scopes` — rail keeps showing scopes. Switching items requires going
173
+ * back to the right-pane list first.
174
+ */
175
+ type CollectionRailMode = 'siblings' | 'scopes';
134
176
 
135
177
  type TelemetryEvent = {
136
178
  type: 'record.save';
@@ -171,6 +213,22 @@ type TelemetryEvent = {
171
213
  type: 'item.create';
172
214
  recordType?: string;
173
215
  scopeRef: string;
216
+ } | {
217
+ type: 'item.open';
218
+ recordType?: string;
219
+ scopeRef: string;
220
+ itemId: string;
221
+ } | {
222
+ type: 'item.delete';
223
+ recordType?: string;
224
+ scopeRef: string;
225
+ itemId: string;
226
+ } | {
227
+ type: 'item.view.change';
228
+ recordType?: string;
229
+ scopeRef: string;
230
+ from: string;
231
+ to: string;
174
232
  } | {
175
233
  type: 'clipboard.copy';
176
234
  recordType?: string;
@@ -228,13 +286,30 @@ interface RecordsAdminI18n {
228
286
  unsavedBannerBody: string;
229
287
  /** Presentation mode switcher labels. */
230
288
  presentationList: string;
231
- presentationGrid: string;
232
- presentationGallery: string;
233
289
  presentationCompact: string;
290
+ /** Right-pane item view (collection cardinality) switcher labels. */
291
+ itemViewTable: string;
292
+ itemViewCards: string;
293
+ itemViewGallery: string;
234
294
  /** Collection cardinality affordances. */
235
295
  newItem: string;
236
296
  noItemsTitle: string;
237
297
  noItemsBody: string;
298
+ /**
299
+ * Right-pane multi-item flow strings (collection cardinality).
300
+ * `{noun}` is replaced with `itemNoun` (e.g. "recipe", "FAQ").
301
+ */
302
+ backToList: string;
303
+ prevItem: string;
304
+ nextItem: string;
305
+ itemListTitle: string;
306
+ /** Friendly singular for table column header in built-in default. */
307
+ itemColumnLabel: string;
308
+ itemColumnUpdated: string;
309
+ itemActions: string;
310
+ /** Sibling rail (rail flips to items when one is open). */
311
+ backToScopes: string;
312
+ siblingsHeading: string;
238
313
  /**
239
314
  * Empty-state copy for the LEFT browse rail (the list itself is empty).
240
315
  * Defaults to a friendly "no records exist yet" message — distinct from
@@ -261,6 +336,88 @@ interface RecordsAdminI18n {
261
336
  }
262
337
  declare const DEFAULT_I18N: RecordsAdminI18n;
263
338
 
339
+ /**
340
+ * How URL changes are pushed onto the browser history.
341
+ *
342
+ * - `push` — every change adds a history entry (rich back stack).
343
+ * - `replace` — every change replaces the current entry (no history bloat).
344
+ * - `smart` — meaningful navigation (open item, change scope) pushes;
345
+ * cosmetic changes (toggle view, prev/next sibling) replace.
346
+ * Default.
347
+ */
348
+ type DeepLinkHistoryMode = 'push' | 'replace' | 'smart';
349
+ /**
350
+ * Customise the URL parameter names the shell reads / writes. Useful when
351
+ * a host already uses one of these keys for something else.
352
+ */
353
+ interface DeepLinkParamNames {
354
+ /** Default `'item'`. */
355
+ item?: string;
356
+ /** Default `'scope'`. */
357
+ scope?: string;
358
+ /** Default `'view'`. */
359
+ view?: string;
360
+ }
361
+ /**
362
+ * The shell-owned deep-link state. All fields are optional — `null` /
363
+ * `undefined` means "absent from the URL".
364
+ */
365
+ interface DeepLinkState {
366
+ /** Item id when an item is open in the editor. */
367
+ item?: string | null;
368
+ /** Scope ref when no item is open and the user is browsing a list. */
369
+ scope?: string | null;
370
+ /** Right-pane view choice (`table` / `cards` / `gallery`). */
371
+ view?: string | null;
372
+ }
373
+ /**
374
+ * Pluggable bridge between the shell and the host's URL. Hosts can supply
375
+ * their own adapter to integrate with React Router, hash routing, the
376
+ * SmartLinks `persistentQueryParams` helper, etc. When omitted the shell
377
+ * falls back to a plain `window.location` + `window.history` adapter.
378
+ */
379
+ interface DeepLinkAdapter {
380
+ /** Read the current values for the shell-owned params. */
381
+ read(): DeepLinkState;
382
+ /**
383
+ * Write a partial state update. `mode` is the resolved push/replace hint
384
+ * (the shell already mapped `'smart'` to one of the two before calling).
385
+ * Hosts should preserve every other URL parameter — only the keys
386
+ * supplied here may be touched.
387
+ */
388
+ write(partial: DeepLinkState, mode: 'push' | 'replace'): void;
389
+ /**
390
+ * Subscribe to external URL changes (back/forward, host-driven nav).
391
+ * Should fire whenever the params the shell cares about may have
392
+ * changed. Returns an unsubscribe function.
393
+ */
394
+ subscribe(listener: () => void): () => void;
395
+ }
396
+ interface DeepLinkOptions {
397
+ /** Master switch — default `false` (opt in per app). */
398
+ enabled?: boolean;
399
+ /** Push/replace strategy. Default `'smart'`. */
400
+ history?: DeepLinkHistoryMode;
401
+ /** Override the default param key names. */
402
+ paramNames?: DeepLinkParamNames;
403
+ /**
404
+ * Pluggable URL bridge. Defaults to `window.location` + `window.history`
405
+ * with a `popstate` subscription. Provide one when the host owns routing
406
+ * (React Router, hash router, iframe postMessage relay, etc.).
407
+ */
408
+ adapter?: DeepLinkAdapter;
409
+ }
410
+ /**
411
+ * Resolved param names — everywhere outside the public surface uses these
412
+ * to avoid the optional-key ceremony.
413
+ */
414
+ interface ResolvedDeepLinkParamNames {
415
+ item: string;
416
+ scope: string;
417
+ view: string;
418
+ }
419
+ declare const DEFAULT_DEEP_LINK_PARAM_NAMES: ResolvedDeepLinkParamNames;
420
+
264
421
  interface RecordsAdminIcons {
265
422
  scope: Record<ScopeKind | 'universal', LucideIcon>;
266
423
  status: {
@@ -348,6 +505,46 @@ interface RecordSlotContext {
348
505
  /** Friendly label for "Paste from {sourceLabel}" in row menus. */
349
506
  clipboardSourceLabel?: string;
350
507
  }
508
+ /**
509
+ * Declarative column definition for the built-in default item table.
510
+ * Supply `itemColumns` for the lazy path; supply `renderItemList` /
511
+ * `renderItemCard` for full control.
512
+ */
513
+ interface ItemColumn<TData = unknown> {
514
+ /** Stable key — used for React keys and per-column persistence. */
515
+ key: string;
516
+ /** Column header label. */
517
+ header: string;
518
+ /**
519
+ * Render the cell content. Receives the record summary plus the typed
520
+ * `data` for convenience.
521
+ */
522
+ render: (record: RecordSummary<TData>) => ReactNode;
523
+ /** CSS width hint applied to the `<th>` (and matching `<td>`). */
524
+ width?: string;
525
+ /** Right-align the cell (numeric columns). */
526
+ align?: 'left' | 'right' | 'center';
527
+ }
528
+ /**
529
+ * Context passed to right-pane item-view slot renderers.
530
+ */
531
+ interface ItemViewContext {
532
+ /** Open the item in the editor. */
533
+ onOpen: (itemId: string) => void;
534
+ /** Create a new item in the current scope. */
535
+ onCreate: () => void;
536
+ /** Delete an item by id. */
537
+ onDelete: (itemId: string) => void;
538
+ /** The scope the items belong to. */
539
+ scope: ParsedRef;
540
+ /** Item id currently open in the editor (when applicable). */
541
+ selectedId?: string;
542
+ /** True while the items are loading. */
543
+ isLoading: boolean;
544
+ }
545
+ interface ItemSlotContext extends ItemViewContext {
546
+ selected: boolean;
547
+ }
351
548
  interface RecordsAdminShellProps<TData = unknown> {
352
549
  SL: SmartLinksSDK;
353
550
  appId: string;
@@ -426,6 +623,24 @@ interface RecordsAdminShellProps<TData = unknown> {
426
623
  intro?: {
427
624
  title: string;
428
625
  body: ReactNode;
626
+ /**
627
+ * Where to surface the "show again" affordance after the user dismisses
628
+ * the intro banner.
629
+ *
630
+ * - `'header'` *(default)* — small ghost icon-button (`?`) inline inside
631
+ * the `ShellHeader`, right-aligned next to `headerActions`. Zero
632
+ * vertical footprint. Auto-falls back to `'footer'` when no header
633
+ * card is rendered (host hasn't enabled it).
634
+ * - `'footer'` — render the `?` button in the quiet utility row that
635
+ * sits above the rail/editor split.
636
+ * - `'inline'` — legacy behaviour: full-width strip with a "How it
637
+ * works" pill on the right.
638
+ * - `'hidden'` — once dismissed, do not offer a way to bring it back
639
+ * from this surface. The host can still re-enable via state reset.
640
+ */
641
+ reopenAffordance?: 'header' | 'footer' | 'inline' | 'hidden';
642
+ /** Override the default "How it works" label / tooltip. */
643
+ reopenLabel?: string;
429
644
  };
430
645
  csvSchema?: CsvSchema<TData>;
431
646
  classify?: (record: RecordSummary<TData>) => RecordStatus;
@@ -439,13 +654,9 @@ interface RecordsAdminShellProps<TData = unknown> {
439
654
  /** Initial presentation when nothing is persisted. Default first of `presentations`. */
440
655
  defaultPresentation?: RecordPresentation;
441
656
  /**
442
- * Optional custom card renderer used by `grid` / `gallery` presentations.
443
- * If omitted the shell uses `<DefaultRecordCard>`.
444
- */
445
- renderCard?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
446
- /**
447
- * Optional custom list-row renderer used by `list` / `compact` presentations.
448
- * If omitted the shell uses `<DefaultRecordRow>`.
657
+ * Optional custom row renderer for the rail. Applied to both `list` and
658
+ * `compact` densities. Cards/galleries are not supported in the rail
659
+ * they belong on the right pane (see `renderItemList` / `itemView`).
449
660
  */
450
661
  renderListRow?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
451
662
  /**
@@ -458,8 +669,11 @@ interface RecordsAdminShellProps<TData = unknown> {
458
669
  /**
459
670
  * Whether each scope holds at most one record (`singleton`, default) or
460
671
  * many (`collection`, e.g. FAQs / recipes / SOPs). In collection mode the
461
- * shell treats scopes as folders containing items, exposes a "+ New" action,
462
- * and the `RecordEditor` works on individual items via `itemId`-suffixed refs.
672
+ * shell treats scopes as folders containing items: when a scope is selected
673
+ * with no item open, the right pane shows the multi-item view (default
674
+ * table, or `renderItemList` / `itemView` overrides). Clicking an item
675
+ * opens it in the editor with Back / prev / next nav, and the rail flips
676
+ * to siblings (see `collectionRailMode`).
463
677
  */
464
678
  cardinality?: RecordCardinality;
465
679
  /** Display name for an item in collection mode (defaults to `'item'`). */
@@ -469,6 +683,47 @@ interface RecordsAdminShellProps<TData = unknown> {
469
683
  * timestamp+random string.
470
684
  */
471
685
  generateItemId?: () => string;
686
+ /**
687
+ * Which built-in item views the right pane offers when a scope is selected
688
+ * and no item is open. Default `['table']`. When more than one is supplied,
689
+ * a switcher appears above the item view and the choice persists per
690
+ * `appId` + `recordType`.
691
+ *
692
+ * Ignored when `renderItemList` is supplied (the host owns the entire view).
693
+ */
694
+ itemViews?: ItemView[];
695
+ /** Initial item view when nothing is persisted. Default first of `itemViews`. */
696
+ defaultItemView?: ItemView;
697
+ /**
698
+ * Declarative columns for the built-in default `table` view. The shell
699
+ * renders a styled table — most apps with a few well-defined fields
700
+ * (FAQ question + last-updated, recipe name + cuisine + servings) want
701
+ * this rather than a custom renderer.
702
+ */
703
+ itemColumns?: ItemColumn<TData>[];
704
+ /**
705
+ * Full custom item-view renderer. When supplied, replaces the built-in
706
+ * table / cards / gallery entirely — `itemViews`, `itemColumns`, and
707
+ * `renderItemCard` are ignored.
708
+ */
709
+ renderItemList?: (items: RecordSummary<TData>[], ctx: ItemViewContext) => ReactNode;
710
+ /**
711
+ * Custom card renderer for the `cards` and `gallery` item views. Falls
712
+ * back to a styled built-in card when omitted.
713
+ */
714
+ renderItemCard?: (record: RecordSummary<TData>, ctx: ItemSlotContext) => ReactNode;
715
+ /**
716
+ * Custom empty state when a scope has no items yet. Falls back to a
717
+ * styled built-in empty state with a "+ New {noun}" CTA.
718
+ */
719
+ renderItemEmpty?: (ctx: ItemViewContext) => ReactNode;
720
+ /**
721
+ * What the rail shows once an item is open (collection cardinality only).
722
+ * Default `'siblings'` — the rail flips to the items in the current scope
723
+ * with a pinned `← All scopes` link. Set to `'scopes'` to keep the rail
724
+ * on scope navigation (admin must use Back / prev / next instead).
725
+ */
726
+ collectionRailMode?: CollectionRailMode;
472
727
  /** Display title shown in the header card. Falls back to `label`, then `recordType`. */
473
728
  title?: string;
474
729
  /** Single-line muted subtitle under the header title. */
@@ -570,6 +825,21 @@ interface RecordsAdminShellProps<TData = unknown> {
570
825
  scope: ParsedRef;
571
826
  currentValue: TData | null;
572
827
  }) => TData | null;
828
+ /**
829
+ * Mirror the shell's runtime state (current scope, open item, right-pane
830
+ * view) into URL parameters so links open to the right place and the
831
+ * browser back/forward buttons feel native.
832
+ *
833
+ * Off by default. The shell only owns the params it knows about
834
+ * (`item`, `scope`, `view`); platform context like `appId` /
835
+ * `collectionId` lives in the host's URL and stays untouched.
836
+ *
837
+ * Pass an `adapter` to integrate with a host router (React Router,
838
+ * SmartLinks `persistentQueryParams`, etc.) — without one the shell
839
+ * uses a default `window.location` + `window.history` adapter that
840
+ * also handles hash routing.
841
+ */
842
+ deepLink?: DeepLinkOptions;
573
843
  }
574
844
  /**
575
845
  * Controls the small tab strip that appears above the editor body inside the
@@ -616,7 +886,7 @@ interface RecordBrowserProps {
616
886
  }
617
887
  declare const RecordBrowser: ({ scopes, activeScope, onActiveScopeChange, selectedRef, onSelectRef, items, counts, isLoading, error, filter, onFilterChange, search, onSearchChange, hasNextPage, isFetchingNextPage, onLoadMore, scopesLoading, i18n, }: RecordBrowserProps) => react_jsx_runtime.JSX.Element;
618
888
 
619
- interface Props$9 {
889
+ interface Props$f {
620
890
  scopes: ScopeKind[];
621
891
  active: ScopeKind;
622
892
  onChange: (s: ScopeKind) => void;
@@ -627,17 +897,17 @@ interface Props$9 {
627
897
  /** Override icons used per scope. Falls back to DEFAULT_ICONS.scope. */
628
898
  icons?: RecordsAdminIcons['scope'];
629
899
  }
630
- declare const ScopeTabs: ({ scopes, active, onChange, loading, counts, icons, }: Props$9) => react_jsx_runtime.JSX.Element;
900
+ declare const ScopeTabs: ({ scopes, active, onChange, loading, counts, icons, }: Props$f) => react_jsx_runtime.JSX.Element;
631
901
 
632
- interface Props$8 {
902
+ interface Props$e {
633
903
  source?: RecordSource;
634
904
  status?: RecordStatus;
635
905
  className?: string;
636
906
  }
637
907
  /** Emerald = own data, amber = inherited, muted = empty */
638
- declare const StatusDot: ({ source, status, className }: Props$8) => react_jsx_runtime.JSX.Element;
908
+ declare const StatusDot: ({ source, status, className }: Props$e) => react_jsx_runtime.JSX.Element;
639
909
 
640
- interface Props$7 {
910
+ interface Props$d {
641
911
  value: 'all' | RecordStatus;
642
912
  onChange: (v: 'all' | RecordStatus) => void;
643
913
  counts: {
@@ -652,20 +922,18 @@ interface Props$7 {
652
922
  * active filter is always rendered so users never lose context. */
653
923
  hideZero?: Array<'all' | RecordStatus>;
654
924
  }
655
- declare const StatusFilterPills: ({ value, onChange, counts, i18n, hideZero }: Props$7) => react_jsx_runtime.JSX.Element;
925
+ declare const StatusFilterPills: ({ value, onChange, counts, i18n, hideZero }: Props$d) => react_jsx_runtime.JSX.Element;
656
926
 
657
- interface Props$6 {
927
+ interface Props$c {
658
928
  items: RecordSummary[];
659
929
  selectedRef?: string;
660
930
  onSelect: (item: RecordSummary) => void;
661
931
  /** When set, the matching row gets a small "unsaved" indicator. */
662
932
  dirtyRef?: string;
663
- /** Layout. Defaults to `list` for full back-compat. */
933
+ /** Rail row density. Defaults to `list`. */
664
934
  presentation?: RecordPresentation;
665
- /** Optional override for `list` / `compact` rows. */
935
+ /** Optional custom row renderer (still dense — applied to both densities). */
666
936
  renderListRow?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
667
- /** Optional override for `grid` / `gallery` cards. */
668
- renderCard?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
669
937
  /** Optional grouping function. Returning null buckets the row under "Other". */
670
938
  groupBy?: (record: RecordSummary) => {
671
939
  key: string;
@@ -685,11 +953,11 @@ interface Props$6 {
685
953
  clipboardSourceLabel?: string;
686
954
  } | null;
687
955
  }
688
- declare const RecordList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, rowClipboard, }: Props$6) => react_jsx_runtime.JSX.Element;
689
- declare const ProductList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, rowClipboard, }: Props$6) => react_jsx_runtime.JSX.Element;
690
- declare const FacetList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, rowClipboard, }: Props$6) => react_jsx_runtime.JSX.Element;
691
- declare const VariantList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, rowClipboard, }: Props$6) => react_jsx_runtime.JSX.Element;
692
- declare const BatchList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, rowClipboard, }: Props$6) => react_jsx_runtime.JSX.Element;
956
+ declare const RecordList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, groupBy, rowClipboard, }: Props$c) => react_jsx_runtime.JSX.Element;
957
+ declare const ProductList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, groupBy, rowClipboard, }: Props$c) => react_jsx_runtime.JSX.Element;
958
+ declare const FacetList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, groupBy, rowClipboard, }: Props$c) => react_jsx_runtime.JSX.Element;
959
+ declare const VariantList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, groupBy, rowClipboard, }: Props$c) => react_jsx_runtime.JSX.Element;
960
+ declare const BatchList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, groupBy, rowClipboard, }: Props$c) => react_jsx_runtime.JSX.Element;
693
961
 
694
962
  interface DefaultRecordRowProps {
695
963
  record: RecordSummary;
@@ -731,7 +999,7 @@ declare const ErrorState: ({ error }: {
731
999
  error: Error;
732
1000
  }) => react_jsx_runtime.JSX.Element;
733
1001
 
734
- interface Props$5 {
1002
+ interface Props$b {
735
1003
  i18n: RecordsAdminI18n;
736
1004
  onApplyToMany?: () => void;
737
1005
  onCopyFrom?: () => void;
@@ -739,9 +1007,9 @@ interface Props$5 {
739
1007
  onImportCsv?: () => void;
740
1008
  onExportCsv?: () => void;
741
1009
  }
742
- declare const BulkActionsMenu: ({ i18n, onApplyToMany, onCopyFrom, onClearMany, onImportCsv, onExportCsv, }: Props$5) => react_jsx_runtime.JSX.Element | null;
1010
+ declare const BulkActionsMenu: ({ i18n, onApplyToMany, onCopyFrom, onClearMany, onImportCsv, onExportCsv, }: Props$b) => react_jsx_runtime.JSX.Element | null;
743
1011
 
744
- interface Props$4<T> {
1012
+ interface Props$a<T> {
745
1013
  ctx: EditorContext<T>;
746
1014
  i18n: RecordsAdminI18n;
747
1015
  children: ReactNode;
@@ -784,7 +1052,7 @@ interface Props$4<T> {
784
1052
  /** Host-provided icons rendered before save / discard / delete labels. */
785
1053
  actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
786
1054
  }
787
- declare function RecordEditor<T>({ ctx, i18n, children, preview, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$4<T>): react_jsx_runtime.JSX.Element;
1055
+ declare function RecordEditor<T>({ ctx, i18n, children, preview, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
788
1056
 
789
1057
  interface InheritanceCtx {
790
1058
  parentValue?: Record<string, unknown> | null;
@@ -802,10 +1070,10 @@ interface MarkerProps {
802
1070
  }
803
1071
  declare const InheritanceMarker: ({ field, inheritedValue, value, children }: MarkerProps) => react_jsx_runtime.JSX.Element;
804
1072
 
805
- interface Props$3 {
1073
+ interface Props$9 {
806
1074
  children: ReactNode;
807
1075
  }
808
- declare const ResolvedPreview: ({ children }: Props$3) => react_jsx_runtime.JSX.Element;
1076
+ declare const ResolvedPreview: ({ children }: Props$9) => react_jsx_runtime.JSX.Element;
809
1077
 
810
1078
  interface ProductChildItem {
811
1079
  /** Variant or batch id (the `<id>` part of `variant:<id>` / `batch:<id>`). */
@@ -836,7 +1104,7 @@ declare const useProductChildren: (args: UseProductChildrenArgs) => {
836
1104
  };
837
1105
 
838
1106
  type DrillTab = 'product' | 'variant' | 'batch';
839
- interface Props$2 {
1107
+ interface Props$8 {
840
1108
  productLabel: string;
841
1109
  /** Which child types are available on the collection. */
842
1110
  showVariants: boolean;
@@ -861,7 +1129,7 @@ interface Props$2 {
861
1129
  */
862
1130
  hideSingleTab?: boolean;
863
1131
  }
864
- declare const ProductDrillDown: ({ productLabel, showVariants, showBatches, active, onChange, selectedChildId, onSelectChild, variants, batches, variantsLoading, batchesLoading, children, hideSingleTab, }: Props$2) => react_jsx_runtime.JSX.Element;
1132
+ declare const ProductDrillDown: ({ productLabel, showVariants, showBatches, active, onChange, selectedChildId, onSelectChild, variants, batches, variantsLoading, batchesLoading, children, hideSingleTab, }: Props$8) => react_jsx_runtime.JSX.Element;
865
1133
 
866
1134
  type PreviewMode = 'inline' | 'side' | 'tab' | 'drawer';
867
1135
  interface CommonProps {
@@ -928,7 +1196,7 @@ declare const ScopeBreadcrumb: ({ scope }: {
928
1196
  }) => react_jsx_runtime.JSX.Element | null;
929
1197
 
930
1198
  type IntroTone = 'info' | 'success' | 'warning';
931
- interface Props$1 {
1199
+ interface Props$7 {
932
1200
  title: string;
933
1201
  body: ReactNode;
934
1202
  onDismiss: () => void;
@@ -937,14 +1205,16 @@ interface Props$1 {
937
1205
  /** Optional "Learn more" link or button rendered inline after the body. */
938
1206
  action?: ReactNode;
939
1207
  }
940
- declare const IntroCard: ({ title, body, onDismiss, tone, action }: Props$1) => react_jsx_runtime.JSX.Element;
1208
+ declare const IntroCard: ({ title, body, onDismiss, tone, action }: Props$7) => react_jsx_runtime.JSX.Element;
941
1209
 
942
- interface Props {
1210
+ interface Props$6 {
943
1211
  label: string;
1212
+ /** Optional override for the button label. When set, takes precedence over `label`. */
1213
+ customLabel?: string;
944
1214
  introHidden: boolean;
945
1215
  onShowIntro?: () => void;
946
1216
  }
947
- declare const UtilityRow: ({ label, introHidden, onShowIntro }: Props) => react_jsx_runtime.JSX.Element | null;
1217
+ declare const UtilityRow: ({ label, customLabel, introHidden, onShowIntro }: Props$6) => react_jsx_runtime.JSX.Element | null;
948
1218
 
949
1219
  interface RecordsCtx {
950
1220
  SL: SmartLinksSDK;
@@ -1121,6 +1391,68 @@ declare function useResolvedRecord<T = unknown>(args: UseResolvedRecordArgs): {
1121
1391
  matchedRule?: _proveanything_smartlinks_dist_types_appObjects.FacetRule;
1122
1392
  };
1123
1393
 
1394
+ interface UseCollectionItemsArgs {
1395
+ ctx: RecordsCtx;
1396
+ /**
1397
+ * Scope the items live under. Items at the collection root pass an empty
1398
+ * `scope.raw` (the hook then uses `refPrefix: 'item:'`). Pass `null` to
1399
+ * keep the query disabled.
1400
+ */
1401
+ scope: ParsedRef | null;
1402
+ /** Per-page size requested from the SDK (default 100). */
1403
+ pageSize?: number;
1404
+ /**
1405
+ * Optional projector that derives the row label / subtitle / thumbnail
1406
+ * from a record's `data`. Falls back to the itemId.
1407
+ */
1408
+ toSummary?: (rec: AppRecord, base: RecordSummary) => RecordSummary;
1409
+ /** When false, the query is paused (used while the host is still booting). */
1410
+ enabled?: boolean;
1411
+ }
1412
+ /**
1413
+ * The shell's `useRecordList` filters by *scope kind*, which doesn't
1414
+ * differentiate items from singletons. This hook intentionally bypasses
1415
+ * that filter and asks for refs under a precise prefix.
1416
+ */
1417
+ declare function useCollectionItems<T = unknown>(args: UseCollectionItemsArgs): {
1418
+ items: RecordSummary<T>[];
1419
+ total: number;
1420
+ isLoading: boolean;
1421
+ error: Error | null;
1422
+ hasNextPage: boolean;
1423
+ isFetchingNextPage: boolean;
1424
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<{
1425
+ data: AppRecord[];
1426
+ total: number;
1427
+ hasMore: boolean;
1428
+ nextOffset: number;
1429
+ }, unknown>, Error>>;
1430
+ refetch: () => void;
1431
+ };
1432
+
1433
+ /**
1434
+ * Which logical changes are "meaningful navigation" (push) vs "cosmetic /
1435
+ * incremental" (replace) under `'smart'` history mode. The shell tags each
1436
+ * emit with one of these.
1437
+ */
1438
+ type DeepLinkChangeKind = 'item.open' | 'item.close' | 'item.step' | 'scope' | 'view';
1439
+ interface UseDeepLinkStateResult {
1440
+ /** Latest snapshot read from the adapter. */
1441
+ urlState: DeepLinkState;
1442
+ /**
1443
+ * Push a partial update through the adapter. `kind` informs the
1444
+ * push-vs-replace decision under `'smart'` mode.
1445
+ */
1446
+ emit: (partial: DeepLinkState, kind: DeepLinkChangeKind) => void;
1447
+ /** Resolved param names for callers that need them. */
1448
+ paramNames: ResolvedDeepLinkParamNames;
1449
+ /** True when deep linking is active (host opted in + we have an adapter). */
1450
+ enabled: boolean;
1451
+ }
1452
+ declare function useDeepLinkState(options: DeepLinkOptions | undefined): UseDeepLinkStateResult;
1453
+
1454
+ declare const createDefaultDeepLinkAdapter: (paramNames: ResolvedDeepLinkParamNames) => DeepLinkAdapter;
1455
+
1124
1456
  interface UseResolveAllRecordsArgs {
1125
1457
  SL: SmartLinksSDK;
1126
1458
  collectionId: string;
@@ -1434,6 +1766,88 @@ declare function usePresentationPref(args: {
1434
1766
  options: RecordPresentation[];
1435
1767
  defaultValue: RecordPresentation;
1436
1768
  }): [RecordPresentation, (next: RecordPresentation) => void];
1769
+ /**
1770
+ * Twin of `usePresentationPref` for the right-pane item view (collection
1771
+ * cardinality only). Stored under a distinct key so toggling the rail
1772
+ * presentation never clobbers the table/cards/gallery preference.
1773
+ */
1774
+ declare function useItemViewPref(args: {
1775
+ appId: string;
1776
+ recordType?: string;
1777
+ options: ItemView[];
1778
+ defaultValue: ItemView;
1779
+ }): [ItemView, (next: ItemView) => void];
1780
+
1781
+ interface Props$5<T> {
1782
+ items: RecordSummary<T>[];
1783
+ isLoading: boolean;
1784
+ error: Error | null;
1785
+ ctx: ItemViewContext;
1786
+ itemNoun: string;
1787
+ view: ItemView;
1788
+ views: ItemView[];
1789
+ onViewChange: (view: ItemView) => void;
1790
+ renderItemList?: (items: RecordSummary<T>[], ctx: ItemViewContext) => ReactNode;
1791
+ renderItemCard?: (record: RecordSummary<T>, ctx: ItemSlotContext) => ReactNode;
1792
+ renderItemEmpty?: (ctx: ItemViewContext) => ReactNode;
1793
+ itemColumns?: ItemColumn<T>[];
1794
+ i18n: RecordsAdminI18n;
1795
+ }
1796
+ declare function ItemListView<T>({ items, isLoading, error, ctx, itemNoun, view, views, onViewChange, renderItemList, renderItemCard, renderItemEmpty, itemColumns, i18n, }: Props$5<T>): react_jsx_runtime.JSX.Element;
1797
+
1798
+ interface Props$4 {
1799
+ options: ItemView[];
1800
+ value: ItemView;
1801
+ onChange: (next: ItemView) => void;
1802
+ i18n: Pick<RecordsAdminI18n, 'itemViewTable' | 'itemViewCards' | 'itemViewGallery'>;
1803
+ }
1804
+ declare const ItemViewSwitcher: ({ options, value, onChange, i18n }: Props$4) => react_jsx_runtime.JSX.Element | null;
1805
+
1806
+ interface Props$3<T> {
1807
+ items: RecordSummary<T>[];
1808
+ columns?: ItemColumn<T>[];
1809
+ selectedId?: string;
1810
+ onOpen: (itemId: string) => void;
1811
+ onDelete: (itemId: string) => void;
1812
+ i18n: Pick<RecordsAdminI18n, 'itemColumnLabel' | 'itemColumnUpdated' | 'itemActions' | 'delete'>;
1813
+ }
1814
+ declare function DefaultItemTable<T>({ items, columns, selectedId, onOpen, onDelete, i18n, }: Props$3<T>): react_jsx_runtime.JSX.Element;
1815
+
1816
+ interface Props$2<T> {
1817
+ items: RecordSummary<T>[];
1818
+ variant: 'cards' | 'gallery';
1819
+ selectedId?: string;
1820
+ ctx: ItemViewContext;
1821
+ renderCard?: (record: RecordSummary<T>, slotCtx: ItemSlotContext) => ReactNode;
1822
+ i18n: Pick<RecordsAdminI18n, 'delete'>;
1823
+ }
1824
+ declare function DefaultItemCards<T>({ items, variant, selectedId, ctx, renderCard, i18n, }: Props$2<T>): react_jsx_runtime.JSX.Element;
1825
+
1826
+ interface Props$1 {
1827
+ /** Friendly name of the item being edited (mostly for screen readers). */
1828
+ label?: string;
1829
+ /** 1-based position within the current sibling list. */
1830
+ position?: number;
1831
+ total?: number;
1832
+ onBack: () => void;
1833
+ onPrev?: () => void;
1834
+ onNext?: () => void;
1835
+ canPrev: boolean;
1836
+ canNext: boolean;
1837
+ i18n: Pick<RecordsAdminI18n, 'backToList' | 'prevItem' | 'nextItem'>;
1838
+ }
1839
+ declare const EditorItemNav: ({ label, position, total, onBack, onPrev, onNext, canPrev, canNext, i18n, }: Props$1) => react_jsx_runtime.JSX.Element;
1840
+
1841
+ interface Props<T> {
1842
+ items: RecordSummary<T>[];
1843
+ selectedItemId?: string;
1844
+ isLoading: boolean;
1845
+ error: Error | null;
1846
+ onBack: () => void;
1847
+ onSelect: (itemId: string) => void;
1848
+ i18n: Pick<RecordsAdminI18n, 'backToScopes' | 'siblingsHeading' | 'noItemsTitle' | 'noItemsBody'>;
1849
+ }
1850
+ declare function SiblingRail<T>({ items, selectedItemId, isLoading, error, onBack, onSelect, i18n, }: Props<T>): react_jsx_runtime.JSX.Element;
1437
1851
 
1438
1852
  interface ClipboardEntry<T = unknown> {
1439
1853
  value: T;
@@ -1504,6 +1918,7 @@ interface BuildRefArgs {
1504
1918
  variantId?: string;
1505
1919
  batchId?: string;
1506
1920
  proofId?: string;
1921
+ itemId?: string;
1507
1922
  }
1508
1923
  declare const buildRef: (a: BuildRefArgs) => string;
1509
1924
  /**
@@ -1511,6 +1926,17 @@ declare const buildRef: (a: BuildRefArgs) => string;
1511
1926
  * `supportedScopes` prunes scopes the app doesn't care about.
1512
1927
  */
1513
1928
  declare const resolutionChain: (target: ParsedRef, supportedScopes: ScopeKind[]) => string[];
1929
+ /**
1930
+ * Strip the trailing `/item:{id}` (or leading `item:{id}`) from a ref and
1931
+ * return both halves. For singleton refs `itemId` is `undefined` and
1932
+ * `scopeRef` equals the input.
1933
+ */
1934
+ declare const splitItemRef: (raw: string) => {
1935
+ scopeRef: string;
1936
+ itemId?: string;
1937
+ };
1938
+ /** Concatenate a scope ref (possibly empty for collection) and an itemId. */
1939
+ declare const buildItemRef: (scopeRef: string, itemId: string) => string;
1514
1940
 
1515
1941
  interface ResolveArgs {
1516
1942
  ctx: RecordsCtx;
@@ -1550,4 +1976,4 @@ declare const exportCsv: <T>(records: RecordSummary<T>[], schema: CsvSchema<T>)
1550
1976
  declare const importCsv: <T>(file: File, schema: CsvSchema<T>, ctx: RecordsCtx) => Promise<ImportReport>;
1551
1977
  declare const downloadBlob: (blob: Blob, filename: string) => void;
1552
1978
 
1553
- export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, type ClipboardEntry, type CollectedRecord, type CollectedSort, type CsvSchema, type CsvSchemaColumn, DEFAULT_I18N, DEFAULT_ICONS, DefaultRecordCard, DefaultRecordRow, DeleteButton, type DirtyStrategy, DrawerPreview, type EditorContext, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, type MergeStrategy, type MergedRecord, type NavConfirmI18n, type ParsedRef, type PasteCompatibility, type PasteCompatibilityResult, PresentationSwitcher, type PreviewMode, PreviewScopePicker, PreviewToggleButton, type ProductBrowseItem, type ProductChildItem, ProductDrillDown, ProductList, type RecordBadge, RecordBrowser, type RecordCardinality, RecordEditor, RecordList, type RecordPresentation, type RecordSlotContext, type RecordSource, type RecordStatus, type RecordSummary, type RecordsAdminI18n, type RecordsAdminIcons, RecordsAdminShell, type RecordsAdminShellProps, ResolvedPreview, type ResolvedRecord, ScopeBreadcrumb, type ScopeKind, ScopeTabs, SidePreview, type SmartLinksSDK, StatusDot, StatusFilterPills, TabbedPreview, type TelemetryEvent, type UseRecordClipboardArgs, type UseRecordClipboardReturn, type UseResolveAllRecordsArgs, type UseResolveAllResult, type UseRulePreviewArgs, type UseRulePreviewResult, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, checkPasteCompatibility, cloneValue, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
1979
+ export { ALL_ITEM_VIEWS, ALL_PRESENTATIONS, BatchList, BulkActionsMenu, type ClipboardEntry, type CollectedRecord, type CollectedSort, type CollectionRailMode, type CsvSchema, type CsvSchemaColumn, DEFAULT_DEEP_LINK_PARAM_NAMES, DEFAULT_I18N, DEFAULT_ICONS, type DeepLinkAdapter, type DeepLinkChangeKind, type DeepLinkHistoryMode, type DeepLinkOptions, type DeepLinkParamNames, type DeepLinkState, DefaultItemCards, DefaultItemTable, DefaultRecordCard, DefaultRecordRow, DeleteButton, type DirtyStrategy, DrawerPreview, type EditorContext, EditorItemNav, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, type ItemColumn, ItemListView, type ItemSlotContext, type ItemView, type ItemViewContext, ItemViewSwitcher, LoadingState, type MergeStrategy, type MergedRecord, type NavConfirmI18n, type ParsedRef, type PasteCompatibility, type PasteCompatibilityResult, PresentationSwitcher, type PreviewMode, PreviewScopePicker, PreviewToggleButton, type ProductBrowseItem, type ProductChildItem, ProductDrillDown, ProductList, type RecordBadge, RecordBrowser, type RecordCardinality, RecordEditor, RecordList, type RecordPresentation, type RecordSlotContext, type RecordSource, type RecordStatus, type RecordSummary, type RecordsAdminI18n, type RecordsAdminIcons, RecordsAdminShell, type RecordsAdminShellProps, type ResolvedDeepLinkParamNames, ResolvedPreview, type ResolvedRecord, ScopeBreadcrumb, type ScopeKind, ScopeTabs, SiblingRail, SidePreview, type SmartLinksSDK, StatusDot, StatusFilterPills, TabbedPreview, type TelemetryEvent, type UseCollectionItemsArgs, type UseRecordClipboardArgs, type UseRecordClipboardReturn, type UseResolveAllRecordsArgs, type UseResolveAllResult, type UseRulePreviewArgs, type UseRulePreviewResult, UtilityRow, VariantList, buildItemRef, buildRef, bulkDelete, bulkUpsert, checkPasteCompatibility, cloneValue, createDefaultDeepLinkAdapter, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, splitItemRef, upsertRecord, useCollectedRecords, useCollectionItems, useDeepLinkState, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useItemViewPref, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };