@proveanything/smartlinks-utils-ui 0.3.0 → 0.3.2

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.
Files changed (38) hide show
  1. package/README.md +10 -1
  2. package/dist/chunk-4LHF5JB7.js +54 -0
  3. package/dist/chunk-4LHF5JB7.js.map +1 -0
  4. package/dist/{chunk-GN2P3MOG.js → chunk-7UBXTFZQ.js} +16 -62
  5. package/dist/chunk-7UBXTFZQ.js.map +1 -0
  6. package/dist/{chunk-S6KH3YV4.js → chunk-JQPS5XPJ.js} +2 -2
  7. package/dist/{chunk-S6KH3YV4.js.map → chunk-JQPS5XPJ.js.map} +1 -1
  8. package/dist/chunk-MZ6JSCXO.js +247 -0
  9. package/dist/chunk-MZ6JSCXO.js.map +1 -0
  10. package/dist/{chunk-4Z46C4MJ.js → chunk-OTJV62XV.js} +2 -2
  11. package/dist/{chunk-4Z46C4MJ.js.map → chunk-OTJV62XV.js.map} +1 -1
  12. package/dist/{chunk-XA5J6CZL.js → chunk-UDYVH7QF.js} +212 -23
  13. package/dist/chunk-UDYVH7QF.js.map +1 -0
  14. package/dist/chunk-WFNEZQCD.js +28 -0
  15. package/dist/chunk-WFNEZQCD.js.map +1 -0
  16. package/dist/components/AssetPicker/index.d.ts +27 -1
  17. package/dist/components/AssetPicker/index.js +2 -1
  18. package/dist/components/ConditionsEditor/index.d.ts +5 -130
  19. package/dist/components/ConditionsEditor/index.js +3 -1
  20. package/dist/components/FacetRuleEditor/index.d.ts +42 -0
  21. package/dist/components/FacetRuleEditor/index.js +5 -0
  22. package/dist/components/FacetRuleEditor/index.js.map +1 -0
  23. package/dist/components/FontPicker/index.js +2 -1
  24. package/dist/components/IconPicker/index.js +2 -1
  25. package/dist/components/RecordsAdmin/index.d.ts +220 -30
  26. package/dist/components/RecordsAdmin/index.js +714 -369
  27. package/dist/components/RecordsAdmin/index.js.map +1 -1
  28. package/dist/index.d.ts +5 -2
  29. package/dist/index.js +7 -4
  30. package/dist/types-a2DdgZ2H.d.ts +128 -0
  31. package/dist/{index-BmKyfKiK.d.ts → useAssets-BM1bzzkq.d.ts} +38 -1
  32. package/package.json +17 -4
  33. package/dist/chunk-GN2P3MOG.js.map +0 -1
  34. package/dist/chunk-XA5J6CZL.js.map +0 -1
  35. package/dist/components/RecordsAdmin/index.css +0 -40
  36. package/dist/components/RecordsAdmin/index.css.map +0 -1
  37. package/dist/index.css +0 -1288
  38. package/dist/index.css.map +0 -1
@@ -1,2 +1,28 @@
1
- export { a as AssetItem, c as AssetPicker, d as AssetPickerMode, e as AssetPickerProps, f as AssetPickerSelection, g as AssetScope, h as AssetViewMode, u as useAssets } from '../../index-BmKyfKiK.js';
1
+ export { a as AssetItem, c as AssetPicker, d as AssetPickerMode, e as AssetPickerProps, f as AssetPickerSelection, g as AssetScope, h as AssetViewMode, u as useAssets } from '../../useAssets-BM1bzzkq.js';
2
2
  import 'react';
3
+
4
+ interface AppRegistryEntry {
5
+ /** Installed app instance id (matches the asset's `appId`). */
6
+ id: string;
7
+ /** Friendly display name (falls back to id if missing). */
8
+ name: string;
9
+ faIcon?: string;
10
+ hidden?: boolean;
11
+ category?: string;
12
+ }
13
+ interface UseAppRegistryReturn {
14
+ apps: AppRegistryEntry[];
15
+ loading: boolean;
16
+ /** Returns the friendly name for an appId, or the id itself when unknown. */
17
+ getAppName: (appId: string | undefined | null) => string;
18
+ /** Returns the full registry entry, or undefined if the id is unknown. */
19
+ getApp: (appId: string | undefined | null) => AppRegistryEntry | undefined;
20
+ }
21
+ /**
22
+ * Loads the app registry for a collection. When `collectionId` is falsy, returns
23
+ * an empty registry — callers can safely use `getAppName(id)` which falls back to
24
+ * the raw id in that case.
25
+ */
26
+ declare function useAppRegistry(collectionId: string | undefined): UseAppRegistryReturn;
27
+
28
+ export { type AppRegistryEntry, type UseAppRegistryReturn, useAppRegistry };
@@ -1,4 +1,5 @@
1
- export { AssetPicker, useAssets } from '../../chunk-XA5J6CZL.js';
1
+ export { AssetPicker, useAppRegistry, useAssets } from '../../chunk-UDYVH7QF.js';
2
+ import '../../chunk-WFNEZQCD.js';
2
3
  import '../../chunk-L7FQ52F5.js';
3
4
  //# sourceMappingURL=index.js.map
4
5
  //# sourceMappingURL=index.js.map
@@ -1,132 +1,7 @@
1
- import React$1 from 'react';
1
+ import React from 'react';
2
+ import { d as ConditionsEditorProps } from '../../types-a2DdgZ2H.js';
3
+ export { C as Condition, a as ConditionGroup, b as ConditionType, c as ConditionTypeMeta, F as FacetOption, e as FacetValueOption, S as SelectOption, V as VersionOption } from '../../types-a2DdgZ2H.js';
2
4
 
3
- /** Condition type identifiers */
4
- type ConditionType = 'version' | 'country' | 'value' | 'user' | 'date' | 'device' | 'tag' | 'facet' | 'geofence' | 'product' | 'itemStatus' | 'condition';
5
- /** A single condition rule — shape varies by type */
6
- interface Condition {
7
- type?: ConditionType | null;
8
- contains?: boolean;
9
- versions?: Array<{
10
- title?: string;
11
- value?: string | null;
12
- } | string>;
13
- countries?: string[];
14
- useRegions?: boolean;
15
- regions?: string[];
16
- field?: string;
17
- fieldType?: 'boolean' | 'integer' | 'text';
18
- validationType?: 'equal' | 'not' | 'greater' | 'less';
19
- value?: string | number | boolean;
20
- userType?: 'valid' | 'invalid' | 'owner' | 'group' | 'admin';
21
- groupIds?: string[];
22
- dateTest?: 'before' | 'after' | 'between';
23
- beforeDate?: string;
24
- afterDate?: string;
25
- rangeDate?: string;
26
- displays?: string[];
27
- tags?: string[];
28
- facetKey?: string;
29
- valueKeys?: string[];
30
- lat1?: number;
31
- lng1?: number;
32
- lat2?: number;
33
- lng2?: number;
34
- productIds?: string[];
35
- statusType?: 'hasProof' | 'noProof' | 'isClaimable' | 'notClaimable' | 'hasOwner' | 'isVirtual';
36
- conditionId?: string;
37
- passes?: boolean;
38
- }
39
- /** Top-level condition group */
40
- interface ConditionGroup {
41
- type: 'and' | 'or';
42
- conditions: Condition[];
43
- /** Only for global/saved conditions */
44
- title?: string;
45
- disabled?: boolean;
46
- }
47
- /** Metadata for a condition type */
48
- interface ConditionTypeMeta {
49
- value: ConditionType;
50
- title: string;
51
- description: string;
52
- icon: string;
53
- color: string;
54
- helpText: string;
55
- }
56
- /** Version option provided to the editor */
57
- interface VersionOption {
58
- title: string;
59
- value: string | null;
60
- }
61
- /** A selectable option with label + value */
62
- interface SelectOption {
63
- title: string;
64
- value: string;
65
- description?: string;
66
- }
67
- /** Props for the conditions editor */
68
- interface ConditionsEditorProps {
69
- /** The current condition group (controlled) */
70
- value: ConditionGroup;
71
- /** Called when conditions change */
72
- onChange: (value: ConditionGroup) => void;
73
- /** Display mode: inline renders directly, dialog opens in a modal */
74
- mode?: 'inline' | 'dialog';
75
- /** Custom trigger element for dialog mode */
76
- trigger?: React.ReactNode;
77
- /** Controlled open state for dialog mode */
78
- open?: boolean;
79
- /** Called when dialog closes */
80
- onClose?: () => void;
81
- /** If true, shows title + disabled fields for saved/global conditions */
82
- isGlobal?: boolean;
83
- /** Available version options (from collection) */
84
- versions?: VersionOption[];
85
- /** Available tag/label options (from collection) */
86
- tags?: string[];
87
- /** Available product options for product condition */
88
- products?: SelectOption[];
89
- /** Available saved conditions for condition references */
90
- savedConditions?: SelectOption[];
91
- /** Available user groups */
92
- userGroups?: SelectOption[];
93
- /**
94
- * Available facet definitions for the 'facet' condition. If omitted and
95
- * `collectionId` is provided, the editor will lazy-fetch them via
96
- * `SL.facets.publicList(collectionId, { includeValues: true })`.
97
- */
98
- facets?: FacetOption[];
99
- /**
100
- * Optional collection id used to auto-fetch facets (and any other
101
- * collection-scoped lookups) when the corresponding prop is not supplied.
102
- */
103
- collectionId?: string;
104
- /**
105
- * Optional explicit facet fetcher. Called with the resolved `collectionId`
106
- * and must return `FacetOption[]`. By default the editor calls
107
- * `SL.facets.publicList(collectionId, { includeValues: true })` directly —
108
- * only provide this if you need to override that data source.
109
- */
110
- getFacets?: (collectionId: string) => Promise<FacetOption[]>;
111
- /** Whether the editor is read-only */
112
- readOnly?: boolean;
113
- /** Additional CSS class */
114
- className?: string;
115
- }
116
- /** A facet definition + its selectable values, as exposed to the editor. */
117
- interface FacetOption {
118
- key: string;
119
- name: string;
120
- cardinality?: 'single' | 'multi';
121
- values: FacetValueOption[];
122
- }
123
- interface FacetValueOption {
124
- key: string;
125
- name: string;
126
- color?: string | null;
127
- description?: string | null;
128
- }
5
+ declare const ConditionsEditor: React.FC<ConditionsEditorProps>;
129
6
 
130
- declare const ConditionsEditor: React$1.FC<ConditionsEditorProps>;
131
-
132
- export { type Condition, type ConditionGroup, type ConditionType, type ConditionTypeMeta, ConditionsEditor, type ConditionsEditorProps, type FacetOption, type FacetValueOption, type SelectOption, type VersionOption };
7
+ export { ConditionsEditor, ConditionsEditorProps };
@@ -1,4 +1,6 @@
1
- export { ConditionsEditor } from '../../chunk-GN2P3MOG.js';
1
+ export { ConditionsEditor } from '../../chunk-7UBXTFZQ.js';
2
+ import '../../chunk-WFNEZQCD.js';
3
+ import '../../chunk-4LHF5JB7.js';
2
4
  import '../../chunk-L7FQ52F5.js';
3
5
  //# sourceMappingURL=index.js.map
4
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { FacetRule } from '@proveanything/smartlinks/dist/types/appObjects';
3
+ export { FacetRule, FacetRuleClause } from '@proveanything/smartlinks/dist/types/appObjects';
4
+ import { F as FacetOption } from '../../types-a2DdgZ2H.js';
5
+
6
+ interface FacetRuleEditorProps {
7
+ /** The current rule (controlled). `null` ⇒ no rule yet. */
8
+ value: FacetRule | null;
9
+ /** Fires whenever the rule changes. */
10
+ onChange: (next: FacetRule | null) => void;
11
+ /**
12
+ * Known facets for the collection. If omitted **and** `collectionId` is set,
13
+ * the editor lazy-fetches them via `SL.facets.publicList`. Free-text entry
14
+ * is **not** supported — admins must pick from defined facets.
15
+ */
16
+ facets?: FacetOption[];
17
+ collectionId?: string;
18
+ getFacets?: (collectionId: string) => Promise<FacetOption[]>;
19
+ /**
20
+ * Live "matches N products" preview. Pass these to enable; omit to hide
21
+ * the preview chip. Typically wired through `useRulePreview`.
22
+ */
23
+ preview?: {
24
+ totalMatches: number | null;
25
+ sampleProductIds?: string[];
26
+ isLoading?: boolean;
27
+ isStale?: boolean;
28
+ error?: Error | null;
29
+ };
30
+ readOnly?: boolean;
31
+ /** Renders a "Remove rule" affordance. */
32
+ onClear?: () => void;
33
+ /** Optional label rendered above the editor. */
34
+ title?: string;
35
+ /** Optional helper text rendered below the title. */
36
+ description?: string;
37
+ className?: string;
38
+ }
39
+
40
+ declare const FacetRuleEditor: React.FC<FacetRuleEditorProps>;
41
+
42
+ export { FacetOption, FacetRuleEditor, type FacetRuleEditorProps };
@@ -0,0 +1,5 @@
1
+ export { FacetRuleEditor } from '../../chunk-MZ6JSCXO.js';
2
+ import '../../chunk-4LHF5JB7.js';
3
+ import '../../chunk-L7FQ52F5.js';
4
+ //# sourceMappingURL=index.js.map
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1,4 +1,5 @@
1
- export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontPicker, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from '../../chunk-4Z46C4MJ.js';
1
+ export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontPicker, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from '../../chunk-OTJV62XV.js';
2
+ import '../../chunk-WFNEZQCD.js';
2
3
  import '../../chunk-L7FQ52F5.js';
3
4
  //# sourceMappingURL=index.js.map
4
5
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
- export { IconPicker, parseFaClass, toFaClass } from '../../chunk-S6KH3YV4.js';
1
+ export { IconPicker, parseFaClass, toFaClass } from '../../chunk-JQPS5XPJ.js';
2
+ import '../../chunk-WFNEZQCD.js';
2
3
  import '../../chunk-L7FQ52F5.js';
3
4
  //# sourceMappingURL=index.js.map
4
5
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
+ import * as _proveanything_smartlinks_dist_types_appObjects from '@proveanything/smartlinks/dist/types/appObjects';
4
+ import { MatchedAt, FacetRule, RecordScope, AppRecord, RecordTarget, MatchResult, MatchEntry } from '@proveanything/smartlinks/dist/types/appObjects';
5
+ import { LucideIcon } from 'lucide-react';
3
6
  import * as _tanstack_query_core from '@tanstack/query-core';
4
- import { RecordScope, AppRecord, RecordTarget, MatchResult } from '@proveanything/smartlinks/dist/types/appObjects';
5
7
 
6
8
  type ScopeKind = 'product' | 'facet' | 'variant' | 'batch';
7
9
  /** Parsed `ref` string — see `data/refs.ts`. Format: `kind:id` or chain. */
@@ -59,6 +61,14 @@ interface ResolvedRecord<TData = unknown> {
59
61
  sourceRef?: string;
60
62
  /** The parent value that would be inherited if this scope cleared its override. */
61
63
  parentValue?: TData | null;
64
+ /**
65
+ * Which resolution tier the SDK reported caused the match.
66
+ * Use this for badges like "Inherited from product" / "Matched by rule".
67
+ * Present when the resolver ran via SDK 1.10 `match()`/`resolveAll()`.
68
+ */
69
+ matchedAt?: MatchedAt;
70
+ /** The rule that fired. Present only when `matchedAt === 'rule'`. */
71
+ matchedRule?: FacetRule;
62
72
  }
63
73
 
64
74
  interface EditorContext<TData = unknown> {
@@ -123,42 +133,42 @@ type CollectedSort = {
123
133
 
124
134
  type TelemetryEvent = {
125
135
  type: 'record.save';
126
- recordType: string;
136
+ recordType?: string;
127
137
  ref: string;
128
138
  isCreate: boolean;
129
139
  } | {
130
140
  type: 'record.delete';
131
- recordType: string;
141
+ recordType?: string;
132
142
  ref: string;
133
143
  } | {
134
144
  type: 'scope.change';
135
- recordType: string;
145
+ recordType?: string;
136
146
  from: ScopeKind;
137
147
  to: ScopeKind;
138
148
  } | {
139
149
  type: 'intro.dismiss';
140
- recordType: string;
150
+ recordType?: string;
141
151
  } | {
142
152
  type: 'csv.import';
143
- recordType: string;
153
+ recordType?: string;
144
154
  rows: number;
145
155
  errors: number;
146
156
  } | {
147
157
  type: 'csv.export';
148
- recordType: string;
158
+ recordType?: string;
149
159
  rows: number;
150
160
  } | {
151
161
  type: 'bulk.apply';
152
- recordType: string;
162
+ recordType?: string;
153
163
  targetCount: number;
154
164
  } | {
155
165
  type: 'presentation.change';
156
- recordType: string;
166
+ recordType?: string;
157
167
  from: RecordPresentation;
158
168
  to: RecordPresentation;
159
169
  } | {
160
170
  type: 'item.create';
161
- recordType: string;
171
+ recordType?: string;
162
172
  scopeRef: string;
163
173
  };
164
174
 
@@ -212,6 +222,52 @@ interface RecordsAdminI18n {
212
222
  }
213
223
  declare const DEFAULT_I18N: RecordsAdminI18n;
214
224
 
225
+ interface RecordsAdminIcons {
226
+ scope: Record<ScopeKind | 'universal', LucideIcon>;
227
+ status: {
228
+ own: LucideIcon;
229
+ inherited: LucideIcon;
230
+ missing: LucideIcon;
231
+ };
232
+ action: {
233
+ add: LucideIcon;
234
+ edit: LucideIcon;
235
+ duplicate: LucideIcon;
236
+ delete: LucideIcon;
237
+ import: LucideIcon;
238
+ export: LucideIcon;
239
+ more: LucideIcon;
240
+ };
241
+ preview: {
242
+ eye: LucideIcon;
243
+ switch: LucideIcon;
244
+ };
245
+ empty: {
246
+ default: LucideIcon;
247
+ search: LucideIcon;
248
+ };
249
+ intro: {
250
+ info: LucideIcon;
251
+ };
252
+ /** Header — used when no `headerIcon` prop is passed. Apps can override
253
+ * `byRecordType[recordType]` for a contextual icon, or `default` as the
254
+ * catch-all. */
255
+ header: {
256
+ default: LucideIcon;
257
+ byRecordType: Record<string, LucideIcon>;
258
+ };
259
+ group: {
260
+ chevron: LucideIcon;
261
+ };
262
+ }
263
+ /** Library defaults — every consumer gets these unless `icons` is overridden. */
264
+ declare const DEFAULT_ICONS: RecordsAdminIcons;
265
+ /** Deep-merge an `icons` prop onto the defaults. */
266
+ declare function mergeIcons(override?: Partial<RecordsAdminIcons>): RecordsAdminIcons;
267
+ /** Look up the right header icon based on prop precedence:
268
+ * explicit `headerIcon` > `icons.header.byRecordType[type]` > `icons.header.default`. */
269
+ declare function pickHeaderIcon(icons: RecordsAdminIcons, recordType?: string): LucideIcon;
270
+
215
271
  /** Minimal SDK shape consumed by the shell. */
216
272
  type SmartLinksSDK = any;
217
273
  /** Slot context passed to renderCard / renderListRow. */
@@ -224,7 +280,10 @@ interface RecordsAdminShellProps<TData = unknown> {
224
280
  SL: SmartLinksSDK;
225
281
  appId: string;
226
282
  collectionId: string;
227
- recordType: string;
283
+ /** Logical record type for this app. Optional — when omitted, records are
284
+ * saved against the app id alone (no type qualifier). Set this only when an
285
+ * app stores multiple distinct record types and needs to query by type. */
286
+ recordType?: string;
228
287
  label: string;
229
288
  scopes: ScopeKind[];
230
289
  defaultScope?: ScopeKind;
@@ -332,6 +391,45 @@ interface RecordsAdminShellProps<TData = unknown> {
332
391
  * timestamp+random string.
333
392
  */
334
393
  generateItemId?: () => string;
394
+ /** Display title shown in the header card. Falls back to `label`, then `recordType`. */
395
+ title?: string;
396
+ /** Single-line muted subtitle under the header title. */
397
+ subtitle?: string;
398
+ /** Icon shown in the header card. Falls back to `icons.header.byRecordType[recordType]`
399
+ * or `icons.header.default`. Pass a Lucide icon component or any ReactNode. */
400
+ headerIcon?: ReactNode;
401
+ /** Right-aligned header content — typically a primary "+ New" button + secondary controls. */
402
+ headerActions?: ReactNode;
403
+ /** Show a counts strip in the header (e.g. Shared · Products). Off by default —
404
+ * most apps don't need it. When `true`, the shell renders built-in counts unless
405
+ * `statsItems` is also provided. */
406
+ showStats?: boolean;
407
+ /** Show the contextual icon to the left of the header title. Default true.
408
+ * Set to `false` if the recordType icon (database, etc.) feels off-brand. */
409
+ showHeaderIcon?: boolean;
410
+ /** Fully custom stats strip content. When provided, replaces the built-in
411
+ * Shared/Products counts. Each item renders as a value + uppercase label. */
412
+ statsItems?: Array<{
413
+ label: string;
414
+ value: string | number;
415
+ }>;
416
+ /** Override the default Lucide icons used by the shell (scope tabs, statuses,
417
+ * empty states, action menus, etc.). Deep-merged onto `DEFAULT_ICONS`. */
418
+ icons?: Partial<RecordsAdminIcons>;
419
+ /** When supplied, the records list is rendered as accordion-style groups.
420
+ * Return `null` to put a record in the default "Other" bucket. */
421
+ groupBy?: (record: RecordSummary) => {
422
+ key: string;
423
+ label: string;
424
+ icon?: ReactNode;
425
+ } | null;
426
+ /** Custom empty-state renderer for the records rail. Falls back to the styled
427
+ * built-in empty state (icon + title + body + optional CTAs). */
428
+ renderEmptyState?: (ctx: {
429
+ scope: ScopeKind;
430
+ }) => ReactNode;
431
+ /** Visual density. Default `comfortable`. */
432
+ density?: 'comfortable' | 'compact';
335
433
  i18n?: Partial<RecordsAdminI18n>;
336
434
  onTelemetry?: (event: TelemetryEvent) => void;
337
435
  className?: string;
@@ -372,8 +470,12 @@ interface Props$9 {
372
470
  onChange: (s: ScopeKind) => void;
373
471
  /** When true, tabs render disabled (used while collection flags are loading). */
374
472
  loading?: boolean;
473
+ /** Optional per-scope counts displayed as tiny badges. */
474
+ counts?: Partial<Record<ScopeKind, number>>;
475
+ /** Override icons used per scope. Falls back to DEFAULT_ICONS.scope. */
476
+ icons?: RecordsAdminIcons['scope'];
375
477
  }
376
- declare const ScopeTabs: ({ scopes, active, onChange, loading }: Props$9) => react_jsx_runtime.JSX.Element;
478
+ declare const ScopeTabs: ({ scopes, active, onChange, loading, counts, icons, }: Props$9) => react_jsx_runtime.JSX.Element;
377
479
 
378
480
  interface Props$8 {
379
481
  source?: RecordSource;
@@ -408,17 +510,23 @@ interface Props$6 {
408
510
  renderListRow?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
409
511
  /** Optional override for `grid` / `gallery` cards. */
410
512
  renderCard?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
513
+ /** Optional grouping function. Returning null buckets the row under "Other". */
514
+ groupBy?: (record: RecordSummary) => {
515
+ key: string;
516
+ label: string;
517
+ icon?: ReactNode;
518
+ } | null;
411
519
  }
412
- declare const RecordList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, }: Props$6) => react_jsx_runtime.JSX.Element;
413
- declare const ProductList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, }: Props$6) => react_jsx_runtime.JSX.Element;
414
- declare const FacetList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, }: Props$6) => react_jsx_runtime.JSX.Element;
415
- declare const VariantList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, }: Props$6) => react_jsx_runtime.JSX.Element;
416
- declare const BatchList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, }: Props$6) => react_jsx_runtime.JSX.Element;
520
+ declare const RecordList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, }: Props$6) => react_jsx_runtime.JSX.Element;
521
+ declare const ProductList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, }: Props$6) => react_jsx_runtime.JSX.Element;
522
+ declare const FacetList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, }: Props$6) => react_jsx_runtime.JSX.Element;
523
+ declare const VariantList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, }: Props$6) => react_jsx_runtime.JSX.Element;
524
+ declare const BatchList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow, renderCard, groupBy, }: Props$6) => react_jsx_runtime.JSX.Element;
417
525
 
418
526
  interface DefaultRecordRowProps {
419
527
  record: RecordSummary;
420
528
  ctx: RecordSlotContext;
421
- /** Drop the status dot + subtitle (used by the `compact` preset). */
529
+ /** Drop the icon + subtitle (used by the `compact` preset). */
422
530
  compact?: boolean;
423
531
  }
424
532
  declare const DefaultRecordRow: ({ record, ctx, compact }: DefaultRecordRowProps) => react_jsx_runtime.JSX.Element;
@@ -439,11 +547,17 @@ interface PresentationSwitcherProps {
439
547
  }
440
548
  declare const PresentationSwitcher: ({ options, value, onChange, i18n }: PresentationSwitcherProps) => react_jsx_runtime.JSX.Element | null;
441
549
 
442
- declare const EmptyState: ({ title, body, action }: {
550
+ interface EmptyStateProps {
443
551
  title: string;
444
552
  body?: ReactNode;
553
+ /** Primary call-to-action — typically "+ Add your first …". */
445
554
  action?: ReactNode;
446
- }) => react_jsx_runtime.JSX.Element;
555
+ /** Optional secondary action — typically "Import from CSV". */
556
+ secondaryAction?: ReactNode;
557
+ /** Lucide icon component. Defaults to `Inbox`. */
558
+ icon?: LucideIcon;
559
+ }
560
+ declare const EmptyState: ({ title, body, action, secondaryAction, icon: Icon, }: EmptyStateProps) => react_jsx_runtime.JSX.Element;
447
561
  declare const LoadingState: () => react_jsx_runtime.JSX.Element;
448
562
  declare const ErrorState: ({ error }: {
449
563
  error: Error;
@@ -599,26 +713,33 @@ declare const ScopeBreadcrumb: ({ scope }: {
599
713
  scope: ParsedRef;
600
714
  }) => react_jsx_runtime.JSX.Element | null;
601
715
 
716
+ type IntroTone = 'info' | 'success' | 'warning';
602
717
  interface Props$1 {
603
718
  title: string;
604
719
  body: ReactNode;
605
720
  onDismiss: () => void;
721
+ /** Visual tone — controls icon and surface tint. */
722
+ tone?: IntroTone;
723
+ /** Optional "Learn more" link or button rendered inline after the body. */
724
+ action?: ReactNode;
606
725
  }
607
- declare const IntroCard: ({ title, body, onDismiss }: Props$1) => react_jsx_runtime.JSX.Element;
726
+ declare const IntroCard: ({ title, body, onDismiss, tone, action }: Props$1) => react_jsx_runtime.JSX.Element;
608
727
 
609
728
  interface Props {
610
729
  label: string;
611
- recordType: string;
612
730
  introHidden: boolean;
613
731
  onShowIntro?: () => void;
614
732
  }
615
- declare const UtilityRow: ({ label, recordType, introHidden, onShowIntro }: Props) => react_jsx_runtime.JSX.Element;
733
+ declare const UtilityRow: ({ label, introHidden, onShowIntro }: Props) => react_jsx_runtime.JSX.Element | null;
616
734
 
617
735
  interface RecordsCtx {
618
736
  SL: SmartLinksSDK;
619
737
  collectionId: string;
620
738
  appId: string;
621
- recordType: string;
739
+ /** Optional — when omitted, records are stored against the app id alone
740
+ * (no type qualifier). Set this only when an app uses multiple record types
741
+ * and needs to query/scope by type. */
742
+ recordType?: string;
622
743
  }
623
744
  /** Shape of a single record write — uses the SDK's structured `scope`. */
624
745
  interface RecordWrite<T = unknown> {
@@ -761,7 +882,8 @@ declare function useRecordEditor<T>(args: UseRecordEditorArgs<T>): EditorContext
761
882
  interface UseResolvedRecordArgs {
762
883
  SL: SmartLinksSDK;
763
884
  appId: string;
764
- recordType: string;
885
+ /** Optional — see `RecordsAdminShellProps.recordType`. */
886
+ recordType?: string;
765
887
  collectionId: string;
766
888
  productId?: string;
767
889
  variantId?: string;
@@ -780,8 +902,76 @@ declare function useResolvedRecord<T = unknown>(args: UseResolvedRecordArgs): {
780
902
  source: RecordSource;
781
903
  sourceRef?: string;
782
904
  parentValue?: T | null | undefined;
905
+ matchedAt?: _proveanything_smartlinks_dist_types_appObjects.MatchedAt;
906
+ matchedRule?: _proveanything_smartlinks_dist_types_appObjects.FacetRule;
783
907
  };
784
908
 
909
+ interface UseResolveAllRecordsArgs {
910
+ SL: SmartLinksSDK;
911
+ collectionId: string;
912
+ appId: string;
913
+ /** Limit to a single record type. Omit to return every type. */
914
+ recordType?: string;
915
+ /** Product context — at minimum a productId in most apps. */
916
+ context: {
917
+ productId?: string;
918
+ variantId?: string;
919
+ batchId?: string;
920
+ proofId?: string;
921
+ /**
922
+ * Facet assignments for the product. Used for both legacy facet refs
923
+ * and `facetRule` evaluation server-side.
924
+ * e.g. `{ brand: 'samsung', type: ['tv', 'laptop'] }`
925
+ */
926
+ facets?: Record<string, string | string[]>;
927
+ };
928
+ /** Restrict to specific tiers (e.g. only `['rule', 'product']`). */
929
+ tiers?: MatchedAt[];
930
+ /** Safety cap. Default 500, max 5000. */
931
+ limit?: number;
932
+ /** Point-in-time evaluation for scheduled records. ISO 8601. */
933
+ at?: string;
934
+ includeScheduled?: boolean;
935
+ includeExpired?: boolean;
936
+ /**
937
+ * `false` to use the public (visibility-filtered) endpoint.
938
+ * Defaults to `false` so this hook is safe to call from public surfaces.
939
+ */
940
+ admin?: boolean;
941
+ enabled?: boolean;
942
+ staleTime?: number;
943
+ }
944
+ interface UseResolveAllResult {
945
+ /** All matching records, sorted most-specific first. Each appears once. */
946
+ records: MatchEntry[];
947
+ /** True when the result hit the `limit` safety cap. */
948
+ truncated: boolean;
949
+ isLoading: boolean;
950
+ error: Error | null;
951
+ refetch: () => void;
952
+ }
953
+ declare function useResolveAllRecords(args: UseResolveAllRecordsArgs): UseResolveAllResult;
954
+
955
+ interface UseRulePreviewArgs {
956
+ SL: SmartLinksSDK;
957
+ collectionId: string;
958
+ appId: string;
959
+ rule: FacetRule | null;
960
+ /** Sample size. Default 20, max 200. */
961
+ limit?: number;
962
+ /** Debounce window in ms while the admin types. Default 350ms. */
963
+ debounceMs?: number;
964
+ enabled?: boolean;
965
+ }
966
+ interface UseRulePreviewResult {
967
+ totalMatches: number | null;
968
+ sampleProductIds: string[];
969
+ isLoading: boolean;
970
+ isStale: boolean;
971
+ error: Error | null;
972
+ }
973
+ declare function useRulePreview(args: UseRulePreviewArgs): UseRulePreviewResult;
974
+
785
975
  interface UseScopeProbeArgs {
786
976
  SL: SmartLinksSDK;
787
977
  collectionId: string;
@@ -803,7 +993,7 @@ declare const useScopeProbe: ({ SL, collectionId, admin, enabled }: UseScopeProb
803
993
  error: Error | null;
804
994
  };
805
995
 
806
- declare const useIntroDismissed: (SL: SmartLinksSDK, collectionId: string, appId: string, recordType: string) => {
996
+ declare const useIntroDismissed: (SL: SmartLinksSDK, collectionId: string, appId: string, recordType?: string) => {
807
997
  dismissed: boolean;
808
998
  dismiss: () => Promise<void>;
809
999
  undismiss: () => void;
@@ -864,7 +1054,7 @@ interface CollectedRecord<T = unknown> {
864
1054
  interface UseCollectedRecordsArgs {
865
1055
  SL: SmartLinksSDK;
866
1056
  appId: string;
867
- recordType: string;
1057
+ recordType?: string;
868
1058
  collectionId: string;
869
1059
  productId?: string;
870
1060
  variantId?: string;
@@ -905,7 +1095,7 @@ interface MergedRecord<T = unknown> {
905
1095
  interface UseMergedRecordArgs<T> {
906
1096
  SL: SmartLinksSDK;
907
1097
  appId: string;
908
- recordType: string;
1098
+ recordType?: string;
909
1099
  collectionId: string;
910
1100
  productId?: string;
911
1101
  variantId?: string;
@@ -1002,7 +1192,7 @@ declare const useDirtyNavigation: ({ strategy, isDirty, save, reset, confirm, i1
1002
1192
 
1003
1193
  declare function usePresentationPref(args: {
1004
1194
  appId: string;
1005
- recordType: string;
1195
+ recordType?: string;
1006
1196
  options: RecordPresentation[];
1007
1197
  defaultValue: RecordPresentation;
1008
1198
  }): [RecordPresentation, (next: RecordPresentation) => void];
@@ -1080,4 +1270,4 @@ declare const exportCsv: <T>(records: RecordSummary<T>[], schema: CsvSchema<T>)
1080
1270
  declare const importCsv: <T>(file: File, schema: CsvSchema<T>, ctx: RecordsCtx) => Promise<ImportReport>;
1081
1271
  declare const downloadBlob: (blob: Blob, filename: string) => void;
1082
1272
 
1083
- export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, type CollectedRecord, type CollectedSort, type CsvSchema, type CsvSchemaColumn, DEFAULT_I18N, DefaultRecordCard, DefaultRecordRow, DeleteButton, type DirtyStrategy, DrawerPreview, type EditorContext, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, type MergeStrategy, type MergedRecord, type NavConfirmI18n, type ParsedRef, 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, RecordsAdminShell, type RecordsAdminShellProps, ResolvedPreview, type ResolvedRecord, ScopeBreadcrumb, type ScopeKind, ScopeTabs, SidePreview, type SmartLinksSDK, StatusDot, StatusFilterPills, TabbedPreview, type TelemetryEvent, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, parseRef, parsedRefToScope, parsedRefToTarget, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordEditor, useRecordList, useResolvedRecord, useScopeProbe, useUnsavedGuard };
1273
+ export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, 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, 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 UseResolveAllRecordsArgs, type UseResolveAllResult, type UseRulePreviewArgs, type UseRulePreviewResult, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };