@proveanything/smartlinks-utils-ui 0.3.8 → 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.
- package/dist/chunk-3BLWNYM4.js +28 -0
- package/dist/chunk-3BLWNYM4.js.map +1 -0
- package/dist/chunk-TY2UIZ24.js +172 -0
- package/dist/chunk-TY2UIZ24.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 +680 -49
- package/dist/components/RecordsAdmin/index.js +1627 -424
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/records-66QWR67J.js +3 -0
- package/dist/records-66QWR67J.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-NIAIQRFC.js +0 -28
- package/dist/chunk-NIAIQRFC.js.map +0 -1
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { 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
|
-
|
|
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
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
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' | '
|
|
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,32 @@ 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;
|
|
232
|
+
} | {
|
|
233
|
+
type: 'clipboard.copy';
|
|
234
|
+
recordType?: string;
|
|
235
|
+
sourceRef: string;
|
|
236
|
+
} | {
|
|
237
|
+
type: 'clipboard.paste';
|
|
238
|
+
recordType?: string;
|
|
239
|
+
sourceRef: string;
|
|
240
|
+
destinationRef: string;
|
|
241
|
+
replaced: boolean;
|
|
174
242
|
};
|
|
175
243
|
|
|
176
244
|
interface RecordsAdminI18n {
|
|
@@ -218,13 +286,30 @@ interface RecordsAdminI18n {
|
|
|
218
286
|
unsavedBannerBody: string;
|
|
219
287
|
/** Presentation mode switcher labels. */
|
|
220
288
|
presentationList: string;
|
|
221
|
-
presentationGrid: string;
|
|
222
|
-
presentationGallery: string;
|
|
223
289
|
presentationCompact: string;
|
|
290
|
+
/** Right-pane item view (collection cardinality) switcher labels. */
|
|
291
|
+
itemViewTable: string;
|
|
292
|
+
itemViewCards: string;
|
|
293
|
+
itemViewGallery: string;
|
|
224
294
|
/** Collection cardinality affordances. */
|
|
225
295
|
newItem: string;
|
|
226
296
|
noItemsTitle: string;
|
|
227
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;
|
|
228
313
|
/**
|
|
229
314
|
* Empty-state copy for the LEFT browse rail (the list itself is empty).
|
|
230
315
|
* Defaults to a friendly "no records exist yet" message — distinct from
|
|
@@ -232,9 +317,107 @@ interface RecordsAdminI18n {
|
|
|
232
317
|
*/
|
|
233
318
|
railEmptyTitle: string;
|
|
234
319
|
railEmptyBody: string;
|
|
320
|
+
/** Clipboard / copy-paste affordance. */
|
|
321
|
+
copy: string;
|
|
322
|
+
paste: string;
|
|
323
|
+
pasteFrom: string;
|
|
324
|
+
pasteReplace: string;
|
|
325
|
+
clipboardEmpty: string;
|
|
326
|
+
copyToast: string;
|
|
327
|
+
pasteToast: string;
|
|
328
|
+
/** Confirm dialog when pasting onto a destination with an existing saved value. */
|
|
329
|
+
pasteConfirmTitle: string;
|
|
330
|
+
pasteConfirmBody: string;
|
|
331
|
+
pasteConfirmReplace: string;
|
|
332
|
+
pasteConfirmCancel: string;
|
|
333
|
+
/** Cross-scope warning copy (e.g. variant → product). */
|
|
334
|
+
pasteWarnTitle: string;
|
|
335
|
+
pasteWarnContinue: string;
|
|
235
336
|
}
|
|
236
337
|
declare const DEFAULT_I18N: RecordsAdminI18n;
|
|
237
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
|
+
|
|
238
421
|
interface RecordsAdminIcons {
|
|
239
422
|
scope: Record<ScopeKind | 'universal', LucideIcon>;
|
|
240
423
|
status: {
|
|
@@ -281,6 +464,17 @@ declare function mergeIcons(override?: Partial<RecordsAdminIcons>): RecordsAdmin
|
|
|
281
464
|
* explicit `headerIcon` > `icons.header.byRecordType[type]` > `icons.header.default`. */
|
|
282
465
|
declare function pickHeaderIcon(icons: RecordsAdminIcons, recordType?: string): LucideIcon;
|
|
283
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Footer / banner action keys whose label and icon can be customised by
|
|
469
|
+
* the host. `save`, `discard`, `delete` are wired today. `saveAll` /
|
|
470
|
+
* `revertAll` are reserved for future "all dirty" affordances; passing
|
|
471
|
+
* them now is harmless and forward-compatible.
|
|
472
|
+
*/
|
|
473
|
+
type RecordsAdminActionKey = 'save' | 'discard' | 'delete' | 'saveAll' | 'revertAll';
|
|
474
|
+
/** Lightweight icon contract — matches Lucide's component signature. */
|
|
475
|
+
type RecordsAdminActionIcon = ComponentType<{
|
|
476
|
+
className?: string;
|
|
477
|
+
}>;
|
|
284
478
|
/** Minimal SDK shape consumed by the shell. */
|
|
285
479
|
type SmartLinksSDK = any;
|
|
286
480
|
/** Slot context passed to renderCard / renderListRow. */
|
|
@@ -288,6 +482,68 @@ interface RecordSlotContext {
|
|
|
288
482
|
selected: boolean;
|
|
289
483
|
onSelect: () => void;
|
|
290
484
|
isDirty?: boolean;
|
|
485
|
+
/**
|
|
486
|
+
* When the host enables `enableClipboard`, the row context menu uses this
|
|
487
|
+
* callback to copy the row's resolved value into the shell-managed
|
|
488
|
+
* clipboard. Wired by the shell — apps don't need to implement it.
|
|
489
|
+
*/
|
|
490
|
+
onCopy?: () => void;
|
|
491
|
+
/**
|
|
492
|
+
* Paste the current clipboard entry onto this row. Disabled when there is
|
|
493
|
+
* nothing to paste, when the source ref equals this row, or when the
|
|
494
|
+
* cross-scope rules deny it.
|
|
495
|
+
*/
|
|
496
|
+
onPaste?: () => void;
|
|
497
|
+
/**
|
|
498
|
+
* Whether `onPaste` will succeed without a confirm. Lets the row menu
|
|
499
|
+
* label the action accurately (e.g. "Paste (replace)" when destination
|
|
500
|
+
* already has a saved value).
|
|
501
|
+
*/
|
|
502
|
+
pasteWillReplace?: boolean;
|
|
503
|
+
/** True when the clipboard is non-empty — drives Paste menu visibility. */
|
|
504
|
+
canPaste?: boolean;
|
|
505
|
+
/** Friendly label for "Paste from {sourceLabel}" in row menus. */
|
|
506
|
+
clipboardSourceLabel?: string;
|
|
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;
|
|
291
547
|
}
|
|
292
548
|
interface RecordsAdminShellProps<TData = unknown> {
|
|
293
549
|
SL: SmartLinksSDK;
|
|
@@ -339,6 +595,12 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
339
595
|
* Default false.
|
|
340
596
|
*/
|
|
341
597
|
previewScopePicker?: boolean;
|
|
598
|
+
/**
|
|
599
|
+
* Editor tab strip behaviour. See {@link RecordsAdminEditorTabsMode}.
|
|
600
|
+
* Default `'off'` — the redundant single-tab strip is hidden when the
|
|
601
|
+
* product has no variants/batches.
|
|
602
|
+
*/
|
|
603
|
+
editorTabs?: RecordsAdminEditorTabsMode;
|
|
342
604
|
/**
|
|
343
605
|
* How to handle unsaved edits when the user navigates to a different
|
|
344
606
|
* record/scope/tab.
|
|
@@ -361,6 +623,24 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
361
623
|
intro?: {
|
|
362
624
|
title: string;
|
|
363
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;
|
|
364
644
|
};
|
|
365
645
|
csvSchema?: CsvSchema<TData>;
|
|
366
646
|
classify?: (record: RecordSummary<TData>) => RecordStatus;
|
|
@@ -374,13 +654,9 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
374
654
|
/** Initial presentation when nothing is persisted. Default first of `presentations`. */
|
|
375
655
|
defaultPresentation?: RecordPresentation;
|
|
376
656
|
/**
|
|
377
|
-
* Optional custom
|
|
378
|
-
*
|
|
379
|
-
|
|
380
|
-
renderCard?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
|
|
381
|
-
/**
|
|
382
|
-
* Optional custom list-row renderer used by `list` / `compact` presentations.
|
|
383
|
-
* 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`).
|
|
384
660
|
*/
|
|
385
661
|
renderListRow?: (record: RecordSummary<TData>, ctx: RecordSlotContext) => ReactNode;
|
|
386
662
|
/**
|
|
@@ -393,8 +669,11 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
393
669
|
/**
|
|
394
670
|
* Whether each scope holds at most one record (`singleton`, default) or
|
|
395
671
|
* many (`collection`, e.g. FAQs / recipes / SOPs). In collection mode the
|
|
396
|
-
* shell treats scopes as folders containing items
|
|
397
|
-
*
|
|
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`).
|
|
398
677
|
*/
|
|
399
678
|
cardinality?: RecordCardinality;
|
|
400
679
|
/** Display name for an item in collection mode (defaults to `'item'`). */
|
|
@@ -404,6 +683,47 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
404
683
|
* timestamp+random string.
|
|
405
684
|
*/
|
|
406
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;
|
|
407
727
|
/** Display title shown in the header card. Falls back to `label`, then `recordType`. */
|
|
408
728
|
title?: string;
|
|
409
729
|
/** Single-line muted subtitle under the header title. */
|
|
@@ -459,7 +779,83 @@ interface RecordsAdminShellProps<TData = unknown> {
|
|
|
459
779
|
i18n?: Partial<RecordsAdminI18n>;
|
|
460
780
|
onTelemetry?: (event: TelemetryEvent) => void;
|
|
461
781
|
className?: string;
|
|
782
|
+
/**
|
|
783
|
+
* Override the resting label for footer / banner actions. When a key is
|
|
784
|
+
* omitted the shell falls back to the i18n default ("Save", "Discard",
|
|
785
|
+
* "Delete"). Loading / disabled states (e.g. "Saving…") remain owned by
|
|
786
|
+
* the shell — only the resting label is customisable here.
|
|
787
|
+
*
|
|
788
|
+
* Hosts that need translated labels should pass already-translated
|
|
789
|
+
* strings; the shell stays locale-agnostic.
|
|
790
|
+
*/
|
|
791
|
+
actionLabels?: Partial<Record<RecordsAdminActionKey, string>>;
|
|
792
|
+
/**
|
|
793
|
+
* Optional icon component rendered before each action label (sized
|
|
794
|
+
* `h-4 w-4`). Omit a key to preserve current look — the editor footer
|
|
795
|
+
* renders Save/Discard without icons by default. Delete retains its
|
|
796
|
+
* built-in `Trash2` unless overridden here.
|
|
797
|
+
*/
|
|
798
|
+
actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
|
|
799
|
+
/**
|
|
800
|
+
* Enable in-shell Copy / Paste between scopes for the current `recordType`.
|
|
801
|
+
* Default `true`. The clipboard is scoped per `(appId, recordType)` and
|
|
802
|
+
* persists in `sessionStorage` so it survives host route changes.
|
|
803
|
+
*/
|
|
804
|
+
enableClipboard?: boolean;
|
|
805
|
+
/**
|
|
806
|
+
* Optional transform on Copy. Receives the resolved value at the source
|
|
807
|
+
* scope and returns what should be stored in the clipboard. Use this to
|
|
808
|
+
* strip per-scope-only fields (e.g. country of origin) that shouldn't
|
|
809
|
+
* propagate. Defaults to a deep clone of the resolved value.
|
|
810
|
+
*/
|
|
811
|
+
onCopy?: (source: {
|
|
812
|
+
value: TData;
|
|
813
|
+
scope: ParsedRef;
|
|
814
|
+
}) => TData;
|
|
815
|
+
/**
|
|
816
|
+
* Optional transform on Paste. Receives the clipboard payload and the
|
|
817
|
+
* destination scope/current value. Return the value to apply, or `null`
|
|
818
|
+
* to abort the paste. Defaults to replacing the destination's value with
|
|
819
|
+
* the clipboard's.
|
|
820
|
+
*/
|
|
821
|
+
onPaste?: (clipboard: {
|
|
822
|
+
value: TData;
|
|
823
|
+
sourceScope: ParsedRef;
|
|
824
|
+
}, destination: {
|
|
825
|
+
scope: ParsedRef;
|
|
826
|
+
currentValue: TData | null;
|
|
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;
|
|
462
843
|
}
|
|
844
|
+
/**
|
|
845
|
+
* Controls the small tab strip that appears above the editor body inside the
|
|
846
|
+
* product drill-down.
|
|
847
|
+
*
|
|
848
|
+
* - `'off'` *(default)* — single-tab strip is hidden when the current product
|
|
849
|
+
* has no variants and no batches (the editor header below already names the
|
|
850
|
+
* record, so the strip is redundant). The strip still renders whenever
|
|
851
|
+
* variants or batches exist — at that point it's a real navigational
|
|
852
|
+
* choice between the product, its variants, and its batches.
|
|
853
|
+
* - `'multi'` — *reserved for a future release.* Will allow multiple records
|
|
854
|
+
* to be open at once with per-tab close buttons and a Save-all banner.
|
|
855
|
+
* Today this value behaves like `'off'` and emits a one-time console
|
|
856
|
+
* warning so consumers can opt in early without breaking when it ships.
|
|
857
|
+
*/
|
|
858
|
+
type RecordsAdminEditorTabsMode = 'off' | 'multi';
|
|
463
859
|
|
|
464
860
|
declare function RecordsAdminShell<TData = unknown>(props: RecordsAdminShellProps<TData>): react_jsx_runtime.JSX.Element;
|
|
465
861
|
|
|
@@ -490,7 +886,7 @@ interface RecordBrowserProps {
|
|
|
490
886
|
}
|
|
491
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;
|
|
492
888
|
|
|
493
|
-
interface Props$
|
|
889
|
+
interface Props$f {
|
|
494
890
|
scopes: ScopeKind[];
|
|
495
891
|
active: ScopeKind;
|
|
496
892
|
onChange: (s: ScopeKind) => void;
|
|
@@ -501,17 +897,17 @@ interface Props$9 {
|
|
|
501
897
|
/** Override icons used per scope. Falls back to DEFAULT_ICONS.scope. */
|
|
502
898
|
icons?: RecordsAdminIcons['scope'];
|
|
503
899
|
}
|
|
504
|
-
declare const ScopeTabs: ({ scopes, active, onChange, loading, counts, icons, }: Props$
|
|
900
|
+
declare const ScopeTabs: ({ scopes, active, onChange, loading, counts, icons, }: Props$f) => react_jsx_runtime.JSX.Element;
|
|
505
901
|
|
|
506
|
-
interface Props$
|
|
902
|
+
interface Props$e {
|
|
507
903
|
source?: RecordSource;
|
|
508
904
|
status?: RecordStatus;
|
|
509
905
|
className?: string;
|
|
510
906
|
}
|
|
511
907
|
/** Emerald = own data, amber = inherited, muted = empty */
|
|
512
|
-
declare const StatusDot: ({ source, status, className }: Props$
|
|
908
|
+
declare const StatusDot: ({ source, status, className }: Props$e) => react_jsx_runtime.JSX.Element;
|
|
513
909
|
|
|
514
|
-
interface Props$
|
|
910
|
+
interface Props$d {
|
|
515
911
|
value: 'all' | RecordStatus;
|
|
516
912
|
onChange: (v: 'all' | RecordStatus) => void;
|
|
517
913
|
counts: {
|
|
@@ -526,32 +922,42 @@ interface Props$7 {
|
|
|
526
922
|
* active filter is always rendered so users never lose context. */
|
|
527
923
|
hideZero?: Array<'all' | RecordStatus>;
|
|
528
924
|
}
|
|
529
|
-
declare const StatusFilterPills: ({ value, onChange, counts, i18n, hideZero }: Props$
|
|
925
|
+
declare const StatusFilterPills: ({ value, onChange, counts, i18n, hideZero }: Props$d) => react_jsx_runtime.JSX.Element;
|
|
530
926
|
|
|
531
|
-
interface Props$
|
|
927
|
+
interface Props$c {
|
|
532
928
|
items: RecordSummary[];
|
|
533
929
|
selectedRef?: string;
|
|
534
930
|
onSelect: (item: RecordSummary) => void;
|
|
535
931
|
/** When set, the matching row gets a small "unsaved" indicator. */
|
|
536
932
|
dirtyRef?: string;
|
|
537
|
-
/**
|
|
933
|
+
/** Rail row density. Defaults to `list`. */
|
|
538
934
|
presentation?: RecordPresentation;
|
|
539
|
-
/** Optional
|
|
935
|
+
/** Optional custom row renderer (still dense — applied to both densities). */
|
|
540
936
|
renderListRow?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
|
|
541
|
-
/** Optional override for `grid` / `gallery` cards. */
|
|
542
|
-
renderCard?: (record: RecordSummary, ctx: RecordSlotContext) => ReactNode;
|
|
543
937
|
/** Optional grouping function. Returning null buckets the row under "Other". */
|
|
544
938
|
groupBy?: (record: RecordSummary) => {
|
|
545
939
|
key: string;
|
|
546
940
|
label: string;
|
|
547
941
|
icon?: ReactNode;
|
|
548
942
|
} | null;
|
|
943
|
+
/**
|
|
944
|
+
* Optional clipboard wiring per row. When provided the shell's Copy /
|
|
945
|
+
* Paste affordance appears in each row's context menu. Returning `null`
|
|
946
|
+
* for a row hides the menu for that row.
|
|
947
|
+
*/
|
|
948
|
+
rowClipboard?: (record: RecordSummary) => {
|
|
949
|
+
onCopy?: () => void;
|
|
950
|
+
onPaste?: () => void;
|
|
951
|
+
canPaste?: boolean;
|
|
952
|
+
pasteWillReplace?: boolean;
|
|
953
|
+
clipboardSourceLabel?: string;
|
|
954
|
+
} | null;
|
|
549
955
|
}
|
|
550
|
-
declare const RecordList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow,
|
|
551
|
-
declare const ProductList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow,
|
|
552
|
-
declare const FacetList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow,
|
|
553
|
-
declare const VariantList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow,
|
|
554
|
-
declare const BatchList: ({ items, selectedRef, onSelect, dirtyRef, presentation, renderListRow,
|
|
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;
|
|
555
961
|
|
|
556
962
|
interface DefaultRecordRowProps {
|
|
557
963
|
record: RecordSummary;
|
|
@@ -593,7 +999,7 @@ declare const ErrorState: ({ error }: {
|
|
|
593
999
|
error: Error;
|
|
594
1000
|
}) => react_jsx_runtime.JSX.Element;
|
|
595
1001
|
|
|
596
|
-
interface Props$
|
|
1002
|
+
interface Props$b {
|
|
597
1003
|
i18n: RecordsAdminI18n;
|
|
598
1004
|
onApplyToMany?: () => void;
|
|
599
1005
|
onCopyFrom?: () => void;
|
|
@@ -601,9 +1007,9 @@ interface Props$5 {
|
|
|
601
1007
|
onImportCsv?: () => void;
|
|
602
1008
|
onExportCsv?: () => void;
|
|
603
1009
|
}
|
|
604
|
-
declare const BulkActionsMenu: ({ i18n, onApplyToMany, onCopyFrom, onClearMany, onImportCsv, onExportCsv, }: Props$
|
|
1010
|
+
declare const BulkActionsMenu: ({ i18n, onApplyToMany, onCopyFrom, onClearMany, onImportCsv, onExportCsv, }: Props$b) => react_jsx_runtime.JSX.Element | null;
|
|
605
1011
|
|
|
606
|
-
interface Props$
|
|
1012
|
+
interface Props$a<T> {
|
|
607
1013
|
ctx: EditorContext<T>;
|
|
608
1014
|
i18n: RecordsAdminI18n;
|
|
609
1015
|
children: ReactNode;
|
|
@@ -628,8 +1034,25 @@ interface Props$4<T> {
|
|
|
628
1034
|
* without it competing with the friendly name as a subtitle.
|
|
629
1035
|
*/
|
|
630
1036
|
headerMeta?: string;
|
|
1037
|
+
/**
|
|
1038
|
+
* Clipboard footer actions. The shell wires these when `enableClipboard`
|
|
1039
|
+
* is on. Copy is always offered when there's an editing scope; Paste is
|
|
1040
|
+
* disabled when the clipboard is empty or the cross-scope rules deny it.
|
|
1041
|
+
*/
|
|
1042
|
+
clipboard?: {
|
|
1043
|
+
onCopy: () => void;
|
|
1044
|
+
onPaste: () => void;
|
|
1045
|
+
canCopy: boolean;
|
|
1046
|
+
canPaste: boolean;
|
|
1047
|
+
pasteSourceLabel?: string;
|
|
1048
|
+
pasteWillReplace?: boolean;
|
|
1049
|
+
};
|
|
1050
|
+
/** Host-provided labels for save / discard / delete (resting state only). */
|
|
1051
|
+
actionLabels?: Partial<Record<RecordsAdminActionKey, string>>;
|
|
1052
|
+
/** Host-provided icons rendered before save / discard / delete labels. */
|
|
1053
|
+
actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
|
|
631
1054
|
}
|
|
632
|
-
declare function RecordEditor<T>({ ctx, i18n, children, preview, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, }: Props$
|
|
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;
|
|
633
1056
|
|
|
634
1057
|
interface InheritanceCtx {
|
|
635
1058
|
parentValue?: Record<string, unknown> | null;
|
|
@@ -647,10 +1070,10 @@ interface MarkerProps {
|
|
|
647
1070
|
}
|
|
648
1071
|
declare const InheritanceMarker: ({ field, inheritedValue, value, children }: MarkerProps) => react_jsx_runtime.JSX.Element;
|
|
649
1072
|
|
|
650
|
-
interface Props$
|
|
1073
|
+
interface Props$9 {
|
|
651
1074
|
children: ReactNode;
|
|
652
1075
|
}
|
|
653
|
-
declare const ResolvedPreview: ({ children }: Props$
|
|
1076
|
+
declare const ResolvedPreview: ({ children }: Props$9) => react_jsx_runtime.JSX.Element;
|
|
654
1077
|
|
|
655
1078
|
interface ProductChildItem {
|
|
656
1079
|
/** Variant or batch id (the `<id>` part of `variant:<id>` / `batch:<id>`). */
|
|
@@ -681,7 +1104,7 @@ declare const useProductChildren: (args: UseProductChildrenArgs) => {
|
|
|
681
1104
|
};
|
|
682
1105
|
|
|
683
1106
|
type DrillTab = 'product' | 'variant' | 'batch';
|
|
684
|
-
interface Props$
|
|
1107
|
+
interface Props$8 {
|
|
685
1108
|
productLabel: string;
|
|
686
1109
|
/** Which child types are available on the collection. */
|
|
687
1110
|
showVariants: boolean;
|
|
@@ -697,8 +1120,16 @@ interface Props$2 {
|
|
|
697
1120
|
batchesLoading: boolean;
|
|
698
1121
|
/** Editor body rendered to the right of the picker. */
|
|
699
1122
|
children: ReactNode;
|
|
1123
|
+
/**
|
|
1124
|
+
* When true, the drill-down tab strip is hidden even when only the
|
|
1125
|
+
* `product` tab would render (i.e. no variants / batches). The editor
|
|
1126
|
+
* header below already names the record so the single-tab strip is
|
|
1127
|
+
* redundant. The strip still appears whenever variants or batches are
|
|
1128
|
+
* available — at that point it's a real navigational choice.
|
|
1129
|
+
*/
|
|
1130
|
+
hideSingleTab?: boolean;
|
|
700
1131
|
}
|
|
701
|
-
declare const ProductDrillDown: ({ productLabel, showVariants, showBatches, active, onChange, selectedChildId, onSelectChild, variants, batches, variantsLoading, batchesLoading, children, }: Props$
|
|
1132
|
+
declare const ProductDrillDown: ({ productLabel, showVariants, showBatches, active, onChange, selectedChildId, onSelectChild, variants, batches, variantsLoading, batchesLoading, children, hideSingleTab, }: Props$8) => react_jsx_runtime.JSX.Element;
|
|
702
1133
|
|
|
703
1134
|
type PreviewMode = 'inline' | 'side' | 'tab' | 'drawer';
|
|
704
1135
|
interface CommonProps {
|
|
@@ -765,7 +1196,7 @@ declare const ScopeBreadcrumb: ({ scope }: {
|
|
|
765
1196
|
}) => react_jsx_runtime.JSX.Element | null;
|
|
766
1197
|
|
|
767
1198
|
type IntroTone = 'info' | 'success' | 'warning';
|
|
768
|
-
interface Props$
|
|
1199
|
+
interface Props$7 {
|
|
769
1200
|
title: string;
|
|
770
1201
|
body: ReactNode;
|
|
771
1202
|
onDismiss: () => void;
|
|
@@ -774,14 +1205,16 @@ interface Props$1 {
|
|
|
774
1205
|
/** Optional "Learn more" link or button rendered inline after the body. */
|
|
775
1206
|
action?: ReactNode;
|
|
776
1207
|
}
|
|
777
|
-
declare const IntroCard: ({ title, body, onDismiss, tone, action }: Props$
|
|
1208
|
+
declare const IntroCard: ({ title, body, onDismiss, tone, action }: Props$7) => react_jsx_runtime.JSX.Element;
|
|
778
1209
|
|
|
779
|
-
interface Props {
|
|
1210
|
+
interface Props$6 {
|
|
780
1211
|
label: string;
|
|
1212
|
+
/** Optional override for the button label. When set, takes precedence over `label`. */
|
|
1213
|
+
customLabel?: string;
|
|
781
1214
|
introHidden: boolean;
|
|
782
1215
|
onShowIntro?: () => void;
|
|
783
1216
|
}
|
|
784
|
-
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;
|
|
785
1218
|
|
|
786
1219
|
interface RecordsCtx {
|
|
787
1220
|
SL: SmartLinksSDK;
|
|
@@ -958,6 +1391,68 @@ declare function useResolvedRecord<T = unknown>(args: UseResolvedRecordArgs): {
|
|
|
958
1391
|
matchedRule?: _proveanything_smartlinks_dist_types_appObjects.FacetRule;
|
|
959
1392
|
};
|
|
960
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
|
+
|
|
961
1456
|
interface UseResolveAllRecordsArgs {
|
|
962
1457
|
SL: SmartLinksSDK;
|
|
963
1458
|
collectionId: string;
|
|
@@ -1271,6 +1766,122 @@ declare function usePresentationPref(args: {
|
|
|
1271
1766
|
options: RecordPresentation[];
|
|
1272
1767
|
defaultValue: RecordPresentation;
|
|
1273
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;
|
|
1851
|
+
|
|
1852
|
+
interface ClipboardEntry<T = unknown> {
|
|
1853
|
+
value: T;
|
|
1854
|
+
sourceScope: ScopeKind | 'collection';
|
|
1855
|
+
sourceRef: string;
|
|
1856
|
+
/** Friendly label captured at copy time so paste targets can show
|
|
1857
|
+
* "Paste from {sourceLabel}" without re-fetching the source. */
|
|
1858
|
+
sourceLabel?: string;
|
|
1859
|
+
/** ISO timestamp — debug/telemetry only. */
|
|
1860
|
+
copiedAt: string;
|
|
1861
|
+
}
|
|
1862
|
+
interface UseRecordClipboardArgs {
|
|
1863
|
+
/** Required — clipboard is scoped per app to prevent cross-app paste. */
|
|
1864
|
+
appId: string;
|
|
1865
|
+
/** Required — also scoped per record type within the app. */
|
|
1866
|
+
recordType: string;
|
|
1867
|
+
}
|
|
1868
|
+
interface UseRecordClipboardReturn<T = unknown> {
|
|
1869
|
+
entry: ClipboardEntry<T> | null;
|
|
1870
|
+
hasEntry: boolean;
|
|
1871
|
+
set: (entry: Omit<ClipboardEntry<T>, 'copiedAt'>) => void;
|
|
1872
|
+
clear: () => void;
|
|
1873
|
+
}
|
|
1874
|
+
declare function useRecordClipboard<T = unknown>(args: UseRecordClipboardArgs): UseRecordClipboardReturn<T>;
|
|
1875
|
+
type PasteCompatibility = 'allowed' | 'warn' | 'denied';
|
|
1876
|
+
interface PasteCompatibilityResult {
|
|
1877
|
+
status: PasteCompatibility;
|
|
1878
|
+
/** Optional short reason — surfaced as a tooltip on the Paste button. */
|
|
1879
|
+
reason?: string;
|
|
1880
|
+
}
|
|
1881
|
+
/** Sane defaults — host can override entirely via `onPaste` returning null. */
|
|
1882
|
+
declare function checkPasteCompatibility(source: ParsedRef, destination: ParsedRef): PasteCompatibilityResult;
|
|
1883
|
+
/** Deep clone — uses `structuredClone` when available, JSON fallback otherwise. */
|
|
1884
|
+
declare function cloneValue<T>(value: T): T;
|
|
1274
1885
|
|
|
1275
1886
|
interface DeleteButtonProps {
|
|
1276
1887
|
/** Performs the delete. Should resolve when the SDK call completes. */
|
|
@@ -1287,8 +1898,16 @@ interface DeleteButtonProps {
|
|
|
1287
1898
|
/** Auto-revert timeout in ms (default 3000). */
|
|
1288
1899
|
revertMs?: number;
|
|
1289
1900
|
disabled?: boolean;
|
|
1901
|
+
/**
|
|
1902
|
+
* Optional icon override for the resting state. Defaults to Lucide
|
|
1903
|
+
* `Trash2`. The confirm-state icon stays `Trash2` so the destructive
|
|
1904
|
+
* intent reads consistently regardless of the host's branding.
|
|
1905
|
+
*/
|
|
1906
|
+
icon?: ComponentType<{
|
|
1907
|
+
className?: string;
|
|
1908
|
+
}>;
|
|
1290
1909
|
}
|
|
1291
|
-
declare const DeleteButton: ({ onConfirm, onBeforeDelete, label, confirmLabel, revertMs, disabled, }: DeleteButtonProps) => react_jsx_runtime.JSX.Element;
|
|
1910
|
+
declare const DeleteButton: ({ onConfirm, onBeforeDelete, label, confirmLabel, revertMs, disabled, icon, }: DeleteButtonProps) => react_jsx_runtime.JSX.Element;
|
|
1292
1911
|
|
|
1293
1912
|
declare const parseRef: (raw: string) => ParsedRef;
|
|
1294
1913
|
interface BuildRefArgs {
|
|
@@ -1299,6 +1918,7 @@ interface BuildRefArgs {
|
|
|
1299
1918
|
variantId?: string;
|
|
1300
1919
|
batchId?: string;
|
|
1301
1920
|
proofId?: string;
|
|
1921
|
+
itemId?: string;
|
|
1302
1922
|
}
|
|
1303
1923
|
declare const buildRef: (a: BuildRefArgs) => string;
|
|
1304
1924
|
/**
|
|
@@ -1306,6 +1926,17 @@ declare const buildRef: (a: BuildRefArgs) => string;
|
|
|
1306
1926
|
* `supportedScopes` prunes scopes the app doesn't care about.
|
|
1307
1927
|
*/
|
|
1308
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;
|
|
1309
1940
|
|
|
1310
1941
|
interface ResolveArgs {
|
|
1311
1942
|
ctx: RecordsCtx;
|
|
@@ -1345,4 +1976,4 @@ declare const exportCsv: <T>(records: RecordSummary<T>[], schema: CsvSchema<T>)
|
|
|
1345
1976
|
declare const importCsv: <T>(file: File, schema: CsvSchema<T>, ctx: RecordsCtx) => Promise<ImportReport>;
|
|
1346
1977
|
declare const downloadBlob: (blob: Blob, filename: string) => void;
|
|
1347
1978
|
|
|
1348
|
-
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, useFacetBrowse, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, 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 };
|