@proveanything/smartlinks-utils-ui 0.10.8 → 0.11.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.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { FacetRule, MatchedAt, RecordTarget, AppRecord, MatchResult, ResolveAllEntry } from '@proveanything/smartlinks/dist/types/appObjects';
2
+ import { FacetRule, MatchedAt, AppRecord, RecordTarget, MatchResult, ResolveAllEntry } from '@proveanything/smartlinks/dist/types/appObjects';
3
+ import { ReactNode, ComponentType } from 'react';
4
4
  import { LucideIcon } from 'lucide-react';
5
5
  import * as _tanstack_query_core from '@tanstack/query-core';
6
6
  import * as _proveanything_smartlinks from '@proveanything/smartlinks';
@@ -93,6 +93,21 @@ interface RecordSummary<TData = unknown> {
93
93
  * browser uses this to render a friendly rule summary as the row subtitle.
94
94
  */
95
95
  facetRule?: FacetRule | null;
96
+ /**
97
+ * Optional visual hint for the leading status icon on the default row
98
+ * renderer. When set, takes precedence over the status-derived icon
99
+ * (configured / inherited / empty). Used by lifecycle rail buckets
100
+ * (success/warning/etc) and any host that wants per-row iconography
101
+ * without supplying a full `renderListRow`.
102
+ */
103
+ iconHint?: ReactNode;
104
+ /**
105
+ * Optional semantic tone for the leading status icon. Drives the icon
106
+ * colour via `ra-status-icon--<tone>` CSS classes. Has no effect unless
107
+ * `iconHint` is also set (or the tone is one that maps to a built-in
108
+ * default icon).
109
+ */
110
+ toneHint?: 'success' | 'warning' | 'danger' | 'muted' | 'info' | 'default';
96
111
  }
97
112
  interface ResolvedRecord<TData = unknown> {
98
113
  data: TData | null;
@@ -755,6 +770,17 @@ interface ItemColumn<TData = unknown> {
755
770
  width?: string;
756
771
  /** Right-align the cell (numeric columns). */
757
772
  align?: 'left' | 'right' | 'center';
773
+ /**
774
+ * When supplied, the column header becomes clickable and toggles
775
+ * asc → desc → none on the loaded records. The framework sorts
776
+ * client-side over whatever pages have been fetched; if more pages
777
+ * exist a small "Sorting first N — Load more for full set" hint is
778
+ * shown above the table so admins know they're sorting a subset.
779
+ *
780
+ * Return a primitive (`string` / `number` / `Date` / `boolean`) — the
781
+ * framework handles nulls (always sorted last) and stable ordering.
782
+ */
783
+ sortBy?: (record: RecordSummary<TData>) => string | number | Date | boolean | null | undefined;
758
784
  }
759
785
  /**
760
786
  * Context passed to right-pane item-view slot renderers.
@@ -993,6 +1019,15 @@ interface RailConfig<TData = unknown> {
993
1019
  onGroupExpanded?: (key: string) => void;
994
1020
  /** Visual density. Default `comfortable`. */
995
1021
  density?: 'comfortable' | 'compact';
1022
+ /**
1023
+ * Page size requested from the SDK for the records-driven rail
1024
+ * (Rules / Global / All tabs). Default 100. Raise for apps that
1025
+ * routinely have hundreds of rule-targeted records and want fewer
1026
+ * "Load more" clicks; lower to reduce initial payload on large
1027
+ * collections. The footer remains visible whenever more pages exist
1028
+ * so admins always have a path to record N+1.
1029
+ */
1030
+ pageSize?: number;
996
1031
  }
997
1032
  interface EditorPreviewConfig<TData = unknown> {
998
1033
  /**
@@ -1048,6 +1083,40 @@ interface ItemsConfig<TData = unknown> {
1048
1083
  cardSize?: 'sm' | 'md' | 'lg';
1049
1084
  /** What the rail shows once an item is open. Default `'siblings'`. */
1050
1085
  railMode?: CollectionRailMode;
1086
+ /**
1087
+ * Optional projector that derives `label` / `subtitle` / `thumbnail`
1088
+ * (and any other `RecordSummary` fields) from a raw record. Runs for
1089
+ * every item in the collection-cardinality right-pane list. The
1090
+ * shell's default tries common keys (`title`, `name`, `label`,
1091
+ * `question`, …) — supply this when your record shape doesn't match
1092
+ * those, or when you want the global / all-items list to read from a
1093
+ * different field.
1094
+ *
1095
+ * `base` already carries the framework-derived fields (id, scope,
1096
+ * status, etc.); return a merged `RecordSummary` (e.g.
1097
+ * `{ ...base, label: rec.data?.headline ?? base.label }`).
1098
+ */
1099
+ toSummary?: (rec: AppRecord, base: RecordSummary<TData>) => RecordSummary<TData>;
1100
+ /**
1101
+ * Page size requested from the SDK for the right-pane item list (and
1102
+ * the sibling rail, since both share `useCollectionItems`). Default
1103
+ * 100. Raise for apps where a single scope routinely holds hundreds
1104
+ * of items (votes, attestations, ledger entries) so admins don't
1105
+ * have to "Load more" on every visit. The footer always renders when
1106
+ * more pages exist — the goal is to never silently truncate.
1107
+ */
1108
+ pageSize?: number;
1109
+ /**
1110
+ * Optional projector returning extra strings to include in the
1111
+ * built-in item-list search match. The framework always searches
1112
+ * `label` + `subtitle`; this hook lets hosts add fields that aren't
1113
+ * on the summary (e.g. body text, tags, internal codes).
1114
+ *
1115
+ * Set `searchable: false` to disable the search box entirely.
1116
+ */
1117
+ searchableFields?: (record: RecordSummary<TData>) => Array<string | undefined | null>;
1118
+ /** Disable the built-in search input. Default `true` (enabled). */
1119
+ searchable?: boolean;
1051
1120
  }
1052
1121
  interface UnsavedConfig<TData = unknown> {
1053
1122
  /**
@@ -1163,6 +1232,8 @@ interface Props$f {
1163
1232
  declare const StatusDot: ({ source, status, className }: Props$f) => react_jsx_runtime.JSX.Element;
1164
1233
 
1165
1234
  type StatusTone = 'own' | 'shared' | 'missing';
1235
+ /** Semantic tones used by host-driven iconography (e.g. lifecycle buckets). */
1236
+ type SemanticTone = 'success' | 'warning' | 'danger' | 'muted' | 'info' | 'default';
1166
1237
  interface Props$e {
1167
1238
  source?: RecordSource;
1168
1239
  status?: RecordStatus;
@@ -1171,8 +1242,21 @@ interface Props$e {
1171
1242
  size?: string;
1172
1243
  /** Optional accessible label — defaults to the tone name. */
1173
1244
  label?: string;
1245
+ /**
1246
+ * Host-supplied icon override. Either a React element (rendered as-is)
1247
+ * or any ReactNode. When set, takes precedence over the status-derived
1248
+ * icon. Pair with `semanticTone` to drive colour.
1249
+ */
1250
+ iconHint?: ReactNode;
1251
+ /**
1252
+ * Host-supplied semantic tone (success/warning/danger/muted/info). When
1253
+ * set, drives the icon colour AND — if no `iconHint` is supplied —
1254
+ * picks a sensible default lucide icon per tone (CheckCircle2 / Alert /
1255
+ * XCircle / MinusCircle / Info).
1256
+ */
1257
+ semanticTone?: SemanticTone;
1174
1258
  }
1175
- declare const StatusIcon: ({ source, status, className, size, label }: Props$e) => react_jsx_runtime.JSX.Element;
1259
+ declare const StatusIcon: ({ source, status, className, size, label, iconHint, semanticTone, }: Props$e) => react_jsx_runtime.JSX.Element;
1176
1260
  /** Short label rendered next to / under the row title. */
1177
1261
  declare const statusToneLabel: (tone: StatusTone) => string;
1178
1262
 
@@ -2038,9 +2122,25 @@ declare const useScopeCounts: (args: UseScopeCountsArgs) => UseScopeCountsResult
2038
2122
  /** React Query key factory for cache invalidation from save/delete sites. */
2039
2123
  declare const scopeCountsQueryKey: (collectionId: string, appId: string, recordType?: string) => (string | null)[];
2040
2124
 
2041
- declare const useIntroDismissed: (SL: SmartLinksSDK, collectionId: string, appId: string, recordType?: string) => {
2125
+ /**
2126
+ * Records-admin intro dismiss state. Thin shim over the library-level
2127
+ * `useIntroState` so the shell shares one persistence model with every
2128
+ * other admin app:
2129
+ *
2130
+ * • Global "show inline help" preference on the user record
2131
+ * (`SL.userAppData('prefs').showHints`) — flipped once, applies
2132
+ * everywhere. When `false` the intro is collapsed by default but the
2133
+ * `?` reopen button is still rendered.
2134
+ * • Per-browser, per-app temporary dismiss in `localStorage`
2135
+ * (`sl:intro-dismissed:${appId}[:recordType]`).
2136
+ *
2137
+ * `collectionId` is no longer used (the old per-collection persistence on
2138
+ * `appConfiguration._meta.introDismissed` was removed) but kept in the
2139
+ * signature for back-compat with existing callers.
2140
+ */
2141
+ declare const useIntroDismissed: (SL: SmartLinksSDK, _collectionId: string, appId: string, recordType?: string) => {
2042
2142
  dismissed: boolean;
2043
- dismiss: () => Promise<void>;
2143
+ dismiss: () => void;
2044
2144
  undismiss: () => void;
2045
2145
  };
2046
2146
 
@@ -2400,9 +2500,25 @@ interface Props$5<T> {
2400
2500
  onCopy?: () => void;
2401
2501
  onDuplicate?: () => void;
2402
2502
  } | null;
2503
+ /**
2504
+ * Optional projector returning extra strings to include in the search
2505
+ * match. Framework always searches `label` + `subtitle`.
2506
+ */
2507
+ searchableFields?: (record: RecordSummary<T>) => Array<string | undefined | null>;
2508
+ /** Disable the search box. Default `true`. */
2509
+ searchable?: boolean;
2510
+ /**
2511
+ * Pagination — when the underlying `useCollectionItems` reports more
2512
+ * pages, the list renders a footer with "Showing X of Y · Load more"
2513
+ * so admins always have a path to record N+1.
2514
+ */
2515
+ total?: number;
2516
+ hasNextPage?: boolean;
2517
+ isFetchingNextPage?: boolean;
2518
+ onLoadMore?: () => void;
2403
2519
  i18n: RecordsAdminI18n;
2404
2520
  }
2405
- declare function ItemListView<T>({ items, isLoading, error, ctx, itemNoun, ruleSummary, view, views, onViewChange, renderItemList, renderItemCard, renderItemEmpty, itemColumns, cardSize, rowActions, rowClipboard, i18n, }: Props$5<T>): react_jsx_runtime.JSX.Element;
2521
+ declare function ItemListView<T>({ items, isLoading, error, ctx, itemNoun, ruleSummary, view, views, onViewChange, renderItemList, renderItemCard, renderItemEmpty, itemColumns, cardSize, rowActions, rowClipboard, searchableFields, searchable, total, hasNextPage, isFetchingNextPage, onLoadMore, i18n, }: Props$5<T>): react_jsx_runtime.JSX.Element;
2406
2522
 
2407
2523
  interface Props$4 {
2408
2524
  options: ItemView[];
@@ -2412,12 +2528,23 @@ interface Props$4 {
2412
2528
  }
2413
2529
  declare const ItemViewSwitcher: ({ options, value, onChange, i18n }: Props$4) => react_jsx_runtime.JSX.Element | null;
2414
2530
 
2531
+ type SortDir = 'asc' | 'desc' | null;
2532
+ interface SortState {
2533
+ key: string | null;
2534
+ dir: SortDir;
2535
+ }
2415
2536
  interface Props$3<T> {
2416
2537
  items: RecordSummary<T>[];
2417
2538
  columns?: ItemColumn<T>[];
2418
2539
  selectedId?: string;
2419
2540
  onOpen: (itemId: string) => void;
2420
2541
  onDelete: (itemId: string) => void;
2542
+ /** Current sort state (controlled by ItemListView). */
2543
+ sort?: SortState;
2544
+ /** Toggle sort for a given column key (asc → desc → none). */
2545
+ onToggleSort?: (key: string) => void;
2546
+ /** Sort key + direction for the fallback (label / updated) columns. */
2547
+ fallbackSortKey?: 'label' | 'updated';
2421
2548
  /** Host-supplied per-record menu actions for each row's `…` kebab. */
2422
2549
  rowActions?: (record: RecordSummary<T>) => RecordAction[] | null | undefined;
2423
2550
  /** Per-record Copy / Duplicate wiring from the shell clipboard. */
@@ -2427,7 +2554,7 @@ interface Props$3<T> {
2427
2554
  } | null;
2428
2555
  i18n: Pick<RecordsAdminI18n, 'itemColumnLabel' | 'itemColumnUpdated' | 'itemActions' | 'delete'>;
2429
2556
  }
2430
- declare function DefaultItemTable<T>({ items, columns, selectedId, onOpen, onDelete, rowActions, rowClipboard, i18n, }: Props$3<T>): react_jsx_runtime.JSX.Element;
2557
+ declare function DefaultItemTable<T>({ items, columns, selectedId, onOpen, onDelete, sort, onToggleSort, rowActions, rowClipboard, i18n, }: Props$3<T>): react_jsx_runtime.JSX.Element;
2431
2558
 
2432
2559
  interface Props$2<T> {
2433
2560
  items: RecordSummary<T>[];
@@ -2504,9 +2631,14 @@ interface Props<T> {
2504
2631
  dirtyKeys?: ReadonlySet<string>;
2505
2632
  /** Subset of `dirtyKeys` whose last save attempt failed. */
2506
2633
  errorKeys?: ReadonlySet<string>;
2634
+ /** Pagination passthrough from `useCollectionItems`. */
2635
+ total?: number;
2636
+ hasNextPage?: boolean;
2637
+ isFetchingNextPage?: boolean;
2638
+ onLoadMore?: () => void;
2507
2639
  i18n: Pick<RecordsAdminI18n, 'backToScopes' | 'siblingsHeading' | 'noItemsTitle' | 'noItemsBody' | 'backToList' | 'newItem'>;
2508
2640
  }
2509
- declare function SiblingRail<T>({ items, selectedItemId, isLoading, error, onBack, onSelect, contextKind, contextSummary, onCreate, itemNoun, dirtyKeys, errorKeys, i18n, }: Props<T>): react_jsx_runtime.JSX.Element;
2641
+ declare function SiblingRail<T>({ items, selectedItemId, isLoading, error, onBack, onSelect, contextKind, contextSummary, onCreate, itemNoun, dirtyKeys, errorKeys, i18n, total, hasNextPage, isFetchingNextPage, onLoadMore, }: Props<T>): react_jsx_runtime.JSX.Element;
2510
2642
 
2511
2643
  interface ClipboardEntry<T = unknown> {
2512
2644
  value: T;