@proveanything/smartlinks-utils-ui 0.8.2 → 0.9.0
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/chunk-NSQRNFT2.js +28 -0
- package/dist/chunk-NSQRNFT2.js.map +1 -0
- package/dist/components/AssetPicker/index.js +1 -1
- package/dist/components/ConditionsEditor/index.js +1 -1
- package/dist/components/FontPicker/index.js +1 -1
- package/dist/components/IconPicker/index.js +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +185 -259
- package/dist/components/RecordsAdmin/index.js +4324 -3878
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-F2YH3NVP.js +0 -28
- package/dist/chunk-F2YH3NVP.js.map +0 -1
|
@@ -658,286 +658,211 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
658
658
|
variantId?: string;
|
|
659
659
|
batchId?: string;
|
|
660
660
|
};
|
|
661
|
-
renderEditor: (ctx: EditorContext<TData>) => ReactNode;
|
|
662
|
-
/**
|
|
663
|
-
* Render the preview surface. Receives the editor's current value so the
|
|
664
|
-
* preview tracks unsaved edits. When `previewScope` differs from the
|
|
665
|
-
* editing scope (because the user picked something in `<PreviewScopePicker>`),
|
|
666
|
-
* `previewScope` reflects the chosen target — apps can use it to load
|
|
667
|
-
* resolved/collected/merged data for that scope instead of `resolved`.
|
|
668
|
-
*/
|
|
669
|
-
renderPreview?: (ctx: {
|
|
670
|
-
resolved: TData | null;
|
|
671
|
-
previewScope: ParsedRef;
|
|
672
|
-
}) => ReactNode;
|
|
673
|
-
/**
|
|
674
|
-
* How the preview surface attaches to the editor pane.
|
|
675
|
-
* - `inline` (default): rendered below the form (current behaviour).
|
|
676
|
-
* - `side`: resizable right pane next to the editor.
|
|
677
|
-
* - `tab`: Editor / Preview siblings inside the right pane.
|
|
678
|
-
* - `drawer`: slide-out from the right, toggled by a button.
|
|
679
|
-
*/
|
|
680
|
-
previewMode?: 'inline' | 'side' | 'tab' | 'drawer';
|
|
681
|
-
/**
|
|
682
|
-
* When true, render a `<PreviewScopePicker>` in the preview chrome so admins
|
|
683
|
-
* can preview as a different product/variant/batch than they're editing.
|
|
684
|
-
* Default false.
|
|
685
|
-
*/
|
|
686
|
-
previewScopePicker?: boolean;
|
|
687
|
-
/**
|
|
688
|
-
* Editor tab strip behaviour. See {@link RecordsAdminEditorTabsMode}.
|
|
689
|
-
* Default `'off'` — the redundant single-tab strip is hidden when the
|
|
690
|
-
* product has no variants/batches.
|
|
691
|
-
*/
|
|
692
|
-
editorTabs?: RecordsAdminEditorTabsMode;
|
|
693
|
-
/**
|
|
694
|
-
* How to handle unsaved edits when the user navigates to a different
|
|
695
|
-
* record/scope/tab.
|
|
696
|
-
* - `prompt` (default): show a confirm dialog (Discard / Cancel / Save).
|
|
697
|
-
* - `autosave`: silently save before navigating away.
|
|
698
|
-
* - `keep`: hold edits in memory keyed by ref; coming back restores them.
|
|
699
|
-
*/
|
|
700
|
-
dirtyStrategy?: 'prompt' | 'autosave' | 'keep';
|
|
701
|
-
/**
|
|
702
|
-
* Pre-delete hook. Return `false` to abort. Lets apps run app-specific
|
|
703
|
-
* confirms (e.g. "this batch has 12k linked proofs"). When omitted the
|
|
704
|
-
* inline two-step confirm is the only safeguard.
|
|
705
|
-
*/
|
|
706
|
-
onBeforeDelete?: (scope: ParsedRef) => boolean | Promise<boolean>;
|
|
707
661
|
/**
|
|
708
|
-
*
|
|
709
|
-
*
|
|
662
|
+
* How the rail should react when `contextScope.productId` is pinned.
|
|
663
|
+
*
|
|
664
|
+
* - `'strict'` (default) — the host has scoped this mount to one product.
|
|
665
|
+
* The rail hides `'collection'` (Global) and `'rule'` tabs entirely
|
|
666
|
+
* (they're collection-wide concerns the product inherits) and the
|
|
667
|
+
* product list collapses to that single product. When the product has
|
|
668
|
+
* no variants and no batches available for drill-down AND no other
|
|
669
|
+
* top-level scopes survive, the rail itself is hidden and the editor
|
|
670
|
+
* takes the whole pane.
|
|
671
|
+
* - `'expand'` — legacy behaviour. The full rail renders; pinning only
|
|
672
|
+
* biases the default tab + selected product.
|
|
673
|
+
*
|
|
674
|
+
* Has no effect when `contextScope.productId` is not set.
|
|
710
675
|
*/
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
title: string;
|
|
714
|
-
body: ReactNode;
|
|
715
|
-
/**
|
|
716
|
-
* Where to surface the "show again" affordance after the user dismisses
|
|
717
|
-
* the intro banner.
|
|
718
|
-
*
|
|
719
|
-
* - `'header'` *(default)* — small ghost icon-button (`?`) inline inside
|
|
720
|
-
* the `ShellHeader`, right-aligned next to `headerActions`. Zero
|
|
721
|
-
* vertical footprint. Auto-falls back to `'footer'` when no header
|
|
722
|
-
* card is rendered (host hasn't enabled it).
|
|
723
|
-
* - `'footer'` — render the `?` button in the quiet utility row that
|
|
724
|
-
* sits above the rail/editor split.
|
|
725
|
-
* - `'inline'` — legacy behaviour: full-width strip with a "How it
|
|
726
|
-
* works" pill on the right.
|
|
727
|
-
* - `'hidden'` — once dismissed, do not offer a way to bring it back
|
|
728
|
-
* from this surface. The host can still re-enable via state reset.
|
|
729
|
-
*/
|
|
730
|
-
reopenAffordance?: 'header' | 'footer' | 'inline' | 'hidden';
|
|
731
|
-
/** Override the default "How it works" label / tooltip. */
|
|
732
|
-
reopenLabel?: string;
|
|
733
|
-
};
|
|
676
|
+
contextScopeMode?: 'strict' | 'expand';
|
|
677
|
+
renderEditor: (ctx: EditorContext<TData>) => ReactNode;
|
|
734
678
|
csvSchema?: CsvSchema<TData>;
|
|
735
679
|
classify?: (record: RecordSummary<TData>) => RecordStatus;
|
|
736
680
|
defaultData?: () => TData;
|
|
737
681
|
/**
|
|
738
|
-
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
* defer to the built-in heuristic). Useful when your record shape nests
|
|
742
|
-
* the title under a custom key the heuristic doesn't know about.
|
|
743
|
-
*/
|
|
744
|
-
deriveDraftLabel?: (value: TData, scope: ParsedRef) => string | undefined;
|
|
745
|
-
/**
|
|
746
|
-
* Which layouts the rail offers. Default `['list']`. When more than one is
|
|
747
|
-
* supplied, a switcher appears above the list and the choice persists
|
|
748
|
-
* per-app/recordType.
|
|
682
|
+
* Header card configuration. The card is off by default; set `show: true`
|
|
683
|
+
* (or pass any of `title` / `subtitle` / `icon` / `actions` / `stats`) to
|
|
684
|
+
* opt in.
|
|
749
685
|
*/
|
|
750
|
-
|
|
751
|
-
/** Initial presentation when nothing is persisted. Default first of `presentations`. */
|
|
752
|
-
defaultPresentation?: RecordPresentation;
|
|
753
|
-
/**
|
|
754
|
-
* Optional custom row renderer for the rail. Applied to both `list` and
|
|
755
|
-
* `compact` densities. Cards/galleries are not supported in the rail —
|
|
756
|
-
* they belong on the right pane (see `renderItemList` / `itemView`).
|
|
757
|
-
*/
|
|
758
|
-
renderListRow?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
|
|
759
|
-
/**
|
|
760
|
-
* Optional custom empty-state renderer for the rail. If omitted the shell
|
|
761
|
-
* uses the default `<EmptyState>` with `i18n.emptyTitle` / `i18n.emptyBody`.
|
|
762
|
-
*/
|
|
763
|
-
renderEmpty?: (ctx: {
|
|
764
|
-
scope: ParsedRef | null;
|
|
765
|
-
}) => ReactNode;
|
|
766
|
-
/**
|
|
767
|
-
* Whether each scope holds at most one record (`singleton`, default) or
|
|
768
|
-
* many (`collection`, e.g. FAQs / recipes / SOPs). In collection mode the
|
|
769
|
-
* shell treats scopes as folders containing items: when a scope is selected
|
|
770
|
-
* with no item open, the right pane shows the multi-item view (default
|
|
771
|
-
* table, or `renderItemList` / `itemView` overrides). Clicking an item
|
|
772
|
-
* opens it in the editor with Back / prev / next nav, and the rail flips
|
|
773
|
-
* to siblings (see `collectionRailMode`).
|
|
774
|
-
*/
|
|
775
|
-
cardinality?: RecordCardinality;
|
|
776
|
-
/** Display name for an item in collection mode (defaults to `'item'`). */
|
|
777
|
-
itemNoun?: string;
|
|
778
|
-
/**
|
|
779
|
-
* Generate a host-local handle for a brand-new collection item draft when
|
|
780
|
-
* "+ New" is clicked. The shell prefixes non-draft values so they remain
|
|
781
|
-
* recognisably unsaved (`draft:…`) until the first save returns a real
|
|
782
|
-
* record UUID. Use this when the host wants stable local draft identities
|
|
783
|
-
* for analytics/UI bookkeeping — not to predeclare the eventual server id.
|
|
784
|
-
*/
|
|
785
|
-
generateItemId?: () => string;
|
|
786
|
-
/**
|
|
787
|
-
* Which built-in item views the right pane offers when a scope is selected
|
|
788
|
-
* and no item is open. Default `['table']`. When more than one is supplied,
|
|
789
|
-
* a switcher appears above the item view and the choice persists per
|
|
790
|
-
* `appId` + `recordType`.
|
|
791
|
-
*
|
|
792
|
-
* Ignored when `renderItemList` is supplied (the host owns the entire view).
|
|
793
|
-
*/
|
|
794
|
-
itemViews?: ItemView[];
|
|
795
|
-
/** Initial item view when nothing is persisted. Default first of `itemViews`. */
|
|
796
|
-
defaultItemView?: ItemView;
|
|
797
|
-
/**
|
|
798
|
-
* Declarative columns for the built-in default `table` view. The shell
|
|
799
|
-
* renders a styled table — most apps with a few well-defined fields
|
|
800
|
-
* (FAQ question + last-updated, recipe name + cuisine + servings) want
|
|
801
|
-
* this rather than a custom renderer.
|
|
802
|
-
*/
|
|
803
|
-
itemColumns?: ItemColumn<TData>[];
|
|
804
|
-
/**
|
|
805
|
-
* Full custom item-view renderer. When supplied, replaces the built-in
|
|
806
|
-
* table / cards / gallery entirely — `itemViews`, `itemColumns`, and
|
|
807
|
-
* `renderItemCard` are ignored.
|
|
808
|
-
*/
|
|
809
|
-
renderItemList?: (items: RecordSummary<TData>[], ctx: ItemViewContext) => ReactNode;
|
|
810
|
-
/**
|
|
811
|
-
* Custom card renderer for the `cards` and `gallery` item views. Falls
|
|
812
|
-
* back to a styled built-in card when omitted.
|
|
813
|
-
*/
|
|
814
|
-
renderItemCard?: (record: RecordSummary<TData>, ctx: ItemSlotContext) => ReactNode;
|
|
686
|
+
header?: HeaderConfig;
|
|
815
687
|
/**
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
* -
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
* Hosts that need exact pixel control can override the underlying
|
|
822
|
-
* `--ra-item-card-min` / `--ra-item-gallery-min` CSS custom properties
|
|
823
|
-
* on `.ra-shell` instead.
|
|
824
|
-
*/
|
|
825
|
-
itemCardSize?: 'sm' | 'md' | 'lg';
|
|
826
|
-
/**
|
|
827
|
-
* Custom empty state when a scope has no items yet. Falls back to a
|
|
828
|
-
* styled built-in empty state with a "+ New {noun}" CTA.
|
|
688
|
+
* Dismissable intro / "How it works" card shown above the rail+editor split.
|
|
689
|
+
* Only renders when supplied. The reopen affordance defaults to a small
|
|
690
|
+
* icon-button inside the header (auto-falls back to the utility row when
|
|
691
|
+
* no header is rendered).
|
|
829
692
|
*/
|
|
830
|
-
|
|
693
|
+
intro?: IntroConfig;
|
|
694
|
+
rail?: RailConfig<TData>;
|
|
695
|
+
editor?: EditorConfig<TData>;
|
|
696
|
+
items?: ItemsConfig<TData>;
|
|
697
|
+
unsaved?: UnsavedConfig<TData>;
|
|
698
|
+
clipboard?: ClipboardConfig<TData>;
|
|
699
|
+
actions?: ActionsConfig;
|
|
831
700
|
/**
|
|
832
|
-
*
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
* on scope navigation (admin must use Back / prev / next instead).
|
|
701
|
+
* Mirror the shell's runtime state into URL params. Off by default. The
|
|
702
|
+
* shell only owns `item`, `scope`, `view` — host platform params are
|
|
703
|
+
* untouched.
|
|
836
704
|
*/
|
|
837
|
-
|
|
838
|
-
/**
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
/** Icon shown in the header card. Falls back to `icons.header.byRecordType[recordType]`
|
|
851
|
-
* or `icons.header.default`. Pass a Lucide icon component or any ReactNode. */
|
|
852
|
-
headerIcon?: ReactNode;
|
|
853
|
-
/** Right-aligned header content — typically a primary "+ New" button + secondary controls. */
|
|
854
|
-
headerActions?: ReactNode;
|
|
855
|
-
/** Show a counts strip in the header (e.g. Shared · Products). Off by default —
|
|
856
|
-
* most apps don't need it. When `true`, the shell renders built-in counts unless
|
|
857
|
-
* `statsItems` is also provided. */
|
|
858
|
-
showStats?: boolean;
|
|
859
|
-
/** Show the contextual icon to the left of the header title. Default true.
|
|
860
|
-
* Set to `false` if the recordType icon (database, etc.) feels off-brand. */
|
|
861
|
-
showHeaderIcon?: boolean;
|
|
862
|
-
/** Fully custom stats strip content. When provided, replaces the built-in
|
|
863
|
-
* Shared/Products counts. Each item renders as a value + uppercase label. */
|
|
864
|
-
statsItems?: Array<{
|
|
705
|
+
deepLink?: DeepLinkOptions;
|
|
706
|
+
/** Override the default Lucide icons used by the shell. Deep-merged onto
|
|
707
|
+
* `DEFAULT_ICONS`. */
|
|
708
|
+
icons?: Partial<RecordsAdminIcons>;
|
|
709
|
+
i18n?: Partial<RecordsAdminI18n>;
|
|
710
|
+
onTelemetry?: (event: TelemetryEvent) => void;
|
|
711
|
+
className?: string;
|
|
712
|
+
}
|
|
713
|
+
interface HeaderStatsConfig {
|
|
714
|
+
/** Show a counts strip in the header. */
|
|
715
|
+
show?: boolean;
|
|
716
|
+
/** Fully custom stats items. When provided, replaces built-in counts. */
|
|
717
|
+
items?: Array<{
|
|
865
718
|
label: string;
|
|
866
719
|
value: string | number;
|
|
867
720
|
}>;
|
|
868
721
|
/** Optional title rendered above the stats strip (e.g. "At a glance"). */
|
|
869
|
-
|
|
870
|
-
/** Optional icon rendered next to
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
*
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
*/
|
|
722
|
+
title?: string;
|
|
723
|
+
/** Optional icon rendered next to the stats title. */
|
|
724
|
+
icon?: ReactNode;
|
|
725
|
+
}
|
|
726
|
+
interface HeaderConfig {
|
|
727
|
+
/** Render the branded header card above the rail. Auto-true when any other
|
|
728
|
+
* header field is set. */
|
|
729
|
+
show?: boolean;
|
|
730
|
+
/** Display title shown in the header card. Falls back to `label`, then
|
|
731
|
+
* `recordType`. */
|
|
732
|
+
title?: string;
|
|
733
|
+
/** Single-line muted subtitle under the title. */
|
|
734
|
+
subtitle?: string;
|
|
735
|
+
/** Icon shown to the left of the header title. Falls back to
|
|
736
|
+
* `icons.header.byRecordType[recordType]` or `icons.header.default`. */
|
|
737
|
+
icon?: ReactNode;
|
|
738
|
+
/** Show the contextual icon. Default true. */
|
|
739
|
+
showIcon?: boolean;
|
|
740
|
+
/** Right-aligned header content — typically a primary "+ New" button. */
|
|
741
|
+
actions?: ReactNode;
|
|
742
|
+
/** External help / documentation link rendered as a small icon-button. */
|
|
879
743
|
helpUrl?: string;
|
|
880
|
-
/** Tooltip / aria-label for the help link. Defaults to
|
|
744
|
+
/** Tooltip / aria-label for the help link. Defaults to
|
|
745
|
+
* "Help & documentation". */
|
|
881
746
|
helpLabel?: string;
|
|
882
|
-
/**
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
747
|
+
/** Counts strip configuration. */
|
|
748
|
+
stats?: HeaderStatsConfig;
|
|
749
|
+
}
|
|
750
|
+
interface IntroConfig {
|
|
751
|
+
title: string;
|
|
752
|
+
body: ReactNode;
|
|
753
|
+
/**
|
|
754
|
+
* Where to surface the "show again" affordance after dismissal.
|
|
755
|
+
* Defaults to `'header'` (auto-falls back to `'footer'` when no header
|
|
756
|
+
* card is rendered).
|
|
757
|
+
*/
|
|
758
|
+
reopenAffordance?: 'header' | 'footer' | 'inline' | 'hidden';
|
|
759
|
+
/** Override the default "How it works" label / tooltip. */
|
|
760
|
+
reopenLabel?: string;
|
|
761
|
+
}
|
|
762
|
+
interface RailConfig<TData = unknown> {
|
|
763
|
+
/** Which layouts the rail offers. Default `['list']`. */
|
|
764
|
+
presentations?: RecordPresentation[];
|
|
765
|
+
/** Initial presentation when nothing is persisted. */
|
|
766
|
+
defaultPresentation?: RecordPresentation;
|
|
767
|
+
/** Custom row renderer for `list` / `compact` densities. */
|
|
768
|
+
renderListRow?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
|
|
769
|
+
/**
|
|
770
|
+
* Custom empty-state renderer for the records rail. Receives the active
|
|
771
|
+
* scope (kind only). Falls back to the styled built-in empty state.
|
|
772
|
+
*/
|
|
773
|
+
renderEmpty?: (ctx: {
|
|
774
|
+
scope: ScopeKind;
|
|
775
|
+
}) => ReactNode;
|
|
776
|
+
/** Group rail records into accordion-style buckets. Return `null` to put
|
|
777
|
+
* a record in the default "Other" bucket. */
|
|
887
778
|
groupBy?: (record: RecordSummary) => {
|
|
888
779
|
key: string;
|
|
889
780
|
label: string;
|
|
890
781
|
icon?: ReactNode;
|
|
891
782
|
} | null;
|
|
892
|
-
/** Custom empty-state renderer for the records rail. Falls back to the styled
|
|
893
|
-
* built-in empty state (icon + title + body + optional CTAs). */
|
|
894
|
-
renderEmptyState?: (ctx: {
|
|
895
|
-
scope: ScopeKind;
|
|
896
|
-
}) => ReactNode;
|
|
897
783
|
/** Visual density. Default `comfortable`. */
|
|
898
784
|
density?: 'comfortable' | 'compact';
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
className?: string;
|
|
785
|
+
}
|
|
786
|
+
interface EditorPreviewConfig<TData = unknown> {
|
|
902
787
|
/**
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
* the shell — only the resting label is customisable here.
|
|
907
|
-
*
|
|
908
|
-
* Hosts that need translated labels should pass already-translated
|
|
909
|
-
* strings; the shell stays locale-agnostic.
|
|
788
|
+
* Render the preview surface. Receives the editor's current value so the
|
|
789
|
+
* preview tracks unsaved edits, plus the chosen `previewScope` (which can
|
|
790
|
+
* differ from the editing scope when `<PreviewScopePicker>` is used).
|
|
910
791
|
*/
|
|
911
|
-
|
|
792
|
+
render?: (ctx: {
|
|
793
|
+
resolved: TData | null;
|
|
794
|
+
previewScope: ParsedRef;
|
|
795
|
+
}) => ReactNode;
|
|
912
796
|
/**
|
|
913
|
-
*
|
|
914
|
-
*
|
|
915
|
-
*
|
|
916
|
-
*
|
|
797
|
+
* How the preview surface attaches to the editor pane.
|
|
798
|
+
* - `inline` (default): rendered below the form.
|
|
799
|
+
* - `side`: resizable right pane next to the editor.
|
|
800
|
+
* - `tab`: Editor / Preview siblings inside the right pane.
|
|
801
|
+
* - `drawer`: slide-out from the right, toggled by a button.
|
|
917
802
|
*/
|
|
918
|
-
|
|
803
|
+
mode?: 'inline' | 'side' | 'tab' | 'drawer';
|
|
804
|
+
/** Render a `<PreviewScopePicker>` so admins can preview as a different
|
|
805
|
+
* product/variant/batch than they're editing. Default false. */
|
|
806
|
+
scopePicker?: boolean;
|
|
807
|
+
}
|
|
808
|
+
interface EditorConfig<TData = unknown> {
|
|
809
|
+
/** Editor tab strip behaviour. See {@link RecordsAdminEditorTabsMode}. */
|
|
810
|
+
tabs?: RecordsAdminEditorTabsMode;
|
|
811
|
+
/** Preview pane configuration. */
|
|
812
|
+
preview?: EditorPreviewConfig<TData>;
|
|
813
|
+
}
|
|
814
|
+
interface ItemsConfig<TData = unknown> {
|
|
919
815
|
/**
|
|
920
|
-
*
|
|
921
|
-
*
|
|
922
|
-
* persists in `sessionStorage` so it survives host route changes.
|
|
816
|
+
* Whether each scope holds at most one record (`singleton`, default) or
|
|
817
|
+
* many (`collection`).
|
|
923
818
|
*/
|
|
924
|
-
|
|
819
|
+
cardinality?: RecordCardinality;
|
|
820
|
+
/** Display name for an item in collection mode. Default `'item'`. */
|
|
821
|
+
noun?: string;
|
|
822
|
+
/** Generate a host-local handle for a brand-new draft. */
|
|
823
|
+
generateId?: () => string;
|
|
824
|
+
/** Which built-in item views the right pane offers. Default `['table']`. */
|
|
825
|
+
views?: ItemView[];
|
|
826
|
+
/** Initial item view when nothing is persisted. */
|
|
827
|
+
defaultView?: ItemView;
|
|
828
|
+
/** Declarative columns for the built-in `table` view. */
|
|
829
|
+
columns?: ItemColumn<TData>[];
|
|
830
|
+
/** Card renderer for `cards` / `gallery` views. */
|
|
831
|
+
renderCard?: (record: RecordSummary<TData>, ctx: ItemSlotContext) => ReactNode;
|
|
832
|
+
/** Full custom item-view renderer. Replaces built-in views entirely. */
|
|
833
|
+
renderList?: (items: RecordSummary<TData>[], ctx: ItemViewContext) => ReactNode;
|
|
834
|
+
/** Custom empty-state when a scope has no items yet. */
|
|
835
|
+
renderEmpty?: (ctx: ItemViewContext) => ReactNode;
|
|
836
|
+
/** Visual density of `cards` / `gallery` views. Default `'md'`. */
|
|
837
|
+
cardSize?: 'sm' | 'md' | 'lg';
|
|
838
|
+
/** What the rail shows once an item is open. Default `'siblings'`. */
|
|
839
|
+
railMode?: CollectionRailMode;
|
|
840
|
+
}
|
|
841
|
+
interface UnsavedConfig<TData = unknown> {
|
|
925
842
|
/**
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
843
|
+
* How to handle unsaved edits when navigating away.
|
|
844
|
+
* - `keep` (default): hold edits per editor mount; surface via the
|
|
845
|
+
* inline UnsavedBanner.
|
|
846
|
+
* - `prompt`: show a confirm dialog on navigation.
|
|
847
|
+
* - `autosave`: silently save before navigating.
|
|
930
848
|
*/
|
|
849
|
+
strategy?: 'prompt' | 'autosave' | 'keep';
|
|
850
|
+
/** Disable the browser-level `beforeunload` prompt. Default false. */
|
|
851
|
+
disableBeforeUnload?: boolean;
|
|
852
|
+
/** Pre-delete hook. Return `false` to abort. */
|
|
853
|
+
onBeforeDelete?: (scope: ParsedRef) => boolean | Promise<boolean>;
|
|
854
|
+
/** Derive a label for an in-flight draft in the unsaved-changes tray. */
|
|
855
|
+
deriveDraftLabel?: (value: TData, scope: ParsedRef) => string | undefined;
|
|
856
|
+
}
|
|
857
|
+
interface ClipboardConfig<TData = unknown> {
|
|
858
|
+
/** Enable in-shell Copy / Paste. Default `true`. */
|
|
859
|
+
enabled?: boolean;
|
|
860
|
+
/** Optional transform on Copy. Defaults to a deep clone. */
|
|
931
861
|
onCopy?: (source: {
|
|
932
862
|
value: TData;
|
|
933
863
|
scope: ParsedRef;
|
|
934
864
|
}) => TData;
|
|
935
|
-
/**
|
|
936
|
-
* Optional transform on Paste. Receives the clipboard payload and the
|
|
937
|
-
* destination scope/current value. Return the value to apply, or `null`
|
|
938
|
-
* to abort the paste. Defaults to replacing the destination's value with
|
|
939
|
-
* the clipboard's.
|
|
940
|
-
*/
|
|
865
|
+
/** Optional transform on Paste. Return `null` to abort. */
|
|
941
866
|
onPaste?: (clipboard: {
|
|
942
867
|
value: TData;
|
|
943
868
|
sourceScope: ParsedRef;
|
|
@@ -945,21 +870,12 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
945
870
|
scope: ParsedRef;
|
|
946
871
|
currentValue: TData | null;
|
|
947
872
|
}) => TData | null;
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
* (`item`, `scope`, `view`); platform context like `appId` /
|
|
955
|
-
* `collectionId` lives in the host's URL and stays untouched.
|
|
956
|
-
*
|
|
957
|
-
* Pass an `adapter` to integrate with a host router (React Router,
|
|
958
|
-
* SmartLinks `persistentQueryParams`, etc.) — without one the shell
|
|
959
|
-
* uses a default `window.location` + `window.history` adapter that
|
|
960
|
-
* also handles hash routing.
|
|
961
|
-
*/
|
|
962
|
-
deepLink?: DeepLinkOptions;
|
|
873
|
+
}
|
|
874
|
+
interface ActionsConfig {
|
|
875
|
+
/** Override resting labels for `save` / `discard` / `delete` (etc.). */
|
|
876
|
+
labels?: Partial<Record<RecordsAdminActionKey, string>>;
|
|
877
|
+
/** Optional icon component rendered before each action label. */
|
|
878
|
+
icons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
|
|
963
879
|
}
|
|
964
880
|
/**
|
|
965
881
|
* Controls the small tab strip that appears above the editor body inside the
|
|
@@ -1651,6 +1567,16 @@ interface UseCollectionItemsArgs {
|
|
|
1651
1567
|
* the query disabled.
|
|
1652
1568
|
*/
|
|
1653
1569
|
scope: ParsedRef | null;
|
|
1570
|
+
/**
|
|
1571
|
+
* When the scope is a rule (kind === 'rule'), pass the rule's `facetRule`
|
|
1572
|
+
* here. Items belonging to a rule are records that carry the *same*
|
|
1573
|
+
* facetRule — they share anchors only by coincidence (typically empty),
|
|
1574
|
+
* so anchor equality alone isn't enough to identify them. When this is
|
|
1575
|
+
* provided we match rule records by facetRule equality and ignore
|
|
1576
|
+
* anchors. When absent, anchor-based matching applies (and rule records
|
|
1577
|
+
* are skipped, since they belong on the Rules tab).
|
|
1578
|
+
*/
|
|
1579
|
+
facetRule?: FacetRule | null;
|
|
1654
1580
|
/** Per-page size requested from the SDK (default 100). */
|
|
1655
1581
|
pageSize?: number;
|
|
1656
1582
|
/**
|