@richardmcquiston01/dashboard-widgets-toolkit 0.9.0 → 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.
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, RefObject } from 'react';
2
- import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, L as Locale, f as DashboardLayout, A as AlertListWidgetData, B as BarListWidgetData, g as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, h as TextWidgetData, i as WidgetData, j as ResolveOptions, k as WidgetContext, l as WidgetProviders } from './scale-CrXxawQn.cjs';
2
+ import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, A as AlertListWidgetData, B as BarListWidgetData, g as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, h as DetailSort, i as TextWidgetData, j as WidgetData, k as LayoutPersistence, S as StoreScope, P as PageItem, l as NormalizeOptions, m as ResolveOptions, n as WidgetContext, o as WidgetProviders } from './storage-VaaysVnZ.cjs';
3
3
 
4
4
  interface WidgetCardProps {
5
5
  readonly title: string;
@@ -145,14 +145,16 @@ interface DetailLoadState {
145
145
  * `undefined`, `fallback` (for example the card's own complete data) is used
146
146
  * instead. `reload` runs it again. Keep `load` and `fallback` referentially
147
147
  * stable (`useCallback` / `useMemo`): a new value restarts the load.
148
+ * `optionValues` (the widget's resolved options) go to the loader as
149
+ * `options.options`.
148
150
  */
149
- declare function useDetailData(definition: WidgetDefinition, load: DetailLoader | undefined, enabled: boolean, fallback?: DetailData): {
151
+ declare function useDetailData(definition: WidgetDefinition, load: DetailLoader | undefined, enabled: boolean, fallback?: DetailData, optionValues?: OptionValues): {
150
152
  readonly state: DetailLoadState;
151
153
  readonly reload: () => void;
152
154
  };
153
155
 
154
156
  /** Every element that carries a stable `dwt-*` class, for `classNames`. */
155
- type DashboardClassSlot = 'dashboard' | 'hiddenBar' | 'toolbar' | 'grid' | 'card' | 'cardHeader' | 'cardTitle' | 'cardDescription' | 'cardActions' | 'cardBody' | 'cardFooter' | 'button' | 'status' | 'empty' | 'error' | 'text' | 'kpi' | 'gauge' | 'table' | 'barList' | 'alertList' | 'chart' | 'legend' | 'tooltip' | 'tableTwin' | 'detail';
157
+ type DashboardClassSlot = 'dashboard' | 'hiddenBar' | 'toolbar' | 'pageBar' | 'grid' | 'card' | 'cardHeader' | 'cardTitle' | 'cardDescription' | 'cardActions' | 'cardBody' | 'cardFooter' | 'button' | 'status' | 'empty' | 'error' | 'text' | 'kpi' | 'gauge' | 'table' | 'barList' | 'alertList' | 'chart' | 'legend' | 'tooltip' | 'tableTwin' | 'detail';
156
158
  /**
157
159
  * Extra classes per slot, appended to the `dwt-*` class (never replacing
158
160
  * it), e.g. `{ card: 'rounded-lg shadow-sm' }` for Tailwind.
@@ -190,6 +192,30 @@ interface DashboardLabels {
190
192
  readonly locked: (title: string) => string;
191
193
  /** The lock icon on a card shown to an administrator (`overrideLocks`). */
192
194
  readonly lockedForViewers: (title: string) => string;
195
+ /** Pages: names the tab list, and each tab ("Page 2 of 3: Sales"). */
196
+ readonly pageBar: string;
197
+ readonly pageTabName: (index: number, count: number, title: string) => string;
198
+ readonly previousPageButton: string;
199
+ readonly nextPageButton: string;
200
+ /** Page management while editing. */
201
+ readonly managePages: string;
202
+ readonly addPage: string;
203
+ readonly renamePage: (title: string) => string;
204
+ readonly pageTitle: string;
205
+ readonly savePageTitle: string;
206
+ readonly cancelPageTitle: string;
207
+ readonly deletePage: (title: string) => string;
208
+ readonly confirmDeletePage: (title: string) => string;
209
+ readonly movePageLeft: (title: string) => string;
210
+ readonly movePageRight: (title: string) => string;
211
+ /** The select on each card that moves it to another page. */
212
+ readonly moveToPage: (title: string) => string;
213
+ readonly moveToPagePlaceholder: string;
214
+ readonly moveToPageOption: (title: string, rowsFree: number) => string;
215
+ readonly newPageOption: string;
216
+ readonly movedToPage: (title: string, pageTitle: string) => string;
217
+ readonly pageFull: (pageTitle: string, maxRows: number) => string;
218
+ readonly emptyPage: string;
193
219
  /** Added to the accessible name of links that open in a new tab. */
194
220
  readonly opensInNewTab: string;
195
221
  /** The card's View button, opening the detail view. */
@@ -277,6 +303,19 @@ interface DashboardProps extends WidgetSettings {
277
303
  readonly defaultLayout?: DashboardLayout;
278
304
  /** Show the built-in Customize/Done/Reset toolbar (toggle mode). Default true. */
279
305
  readonly toolbar?: boolean;
306
+ /**
307
+ * The page in view (a page key) when the layout has pages. Controlled with
308
+ * `onActivePageChange`; without it the dashboard keeps its own, starting on
309
+ * `defaultActivePage` or the first page. Pages never listed fall back to
310
+ * the first.
311
+ */
312
+ readonly activePage?: string;
313
+ readonly defaultActivePage?: string;
314
+ readonly onActivePageChange?: (pageKey: string) => void;
315
+ /** Rows a page holds unless the page says otherwise. Default 4. */
316
+ readonly maxRows?: number;
317
+ /** Most pages the viewer can add while editing. Default: no limit. */
318
+ readonly maxPages?: number;
280
319
  readonly onRetry?: (key: string) => void;
281
320
  /**
282
321
  * Loads the full data for a widget's detail view (widgets whose definition
@@ -345,10 +384,12 @@ declare function GaugeWidget({ data, }: {
345
384
  readonly data: GaugeWidgetData;
346
385
  }): ReactNode;
347
386
  /** TABLE: a data table; cells with a safe `href` become links. */
348
- declare function TableWidget({ data, controls, }: {
387
+ declare function TableWidget({ data, controls, initialSort, }: {
349
388
  readonly data: TableWidgetData;
350
389
  /** Search box and sortable headers; see `WidgetDefinition.tableControls`. */
351
390
  readonly controls?: ResolvedTableControls | undefined;
391
+ /** The header sort to start with, for example from a `sort` option. */
392
+ readonly initialSort?: DetailSort | undefined;
352
393
  }): ReactNode;
353
394
  /**
354
395
  * BAR_LIST: labelled horizontal bars. One series, so one color (slot 1)
@@ -362,12 +403,69 @@ declare function AlertListWidget({ data, }: {
362
403
  readonly data: AlertListWidgetData;
363
404
  }): ReactNode;
364
405
  /** Renders any payload with the renderer for its kind. */
365
- declare function WidgetContent({ data, tableControls, }: {
406
+ declare function WidgetContent({ data, tableControls, initialSort, }: {
366
407
  readonly data: WidgetData;
367
408
  /** Search and sort for TABLE data; see `resolveTableControls`. */
368
409
  readonly tableControls?: ResolvedTableControls | undefined;
410
+ /** TABLE header sort to start with; see `sortFromOptions`. */
411
+ readonly initialSort?: DetailSort | undefined;
369
412
  }): ReactNode;
370
413
 
414
+ type StoredLayoutStatus = 'loading' | 'ready' | 'saving' | 'error' | 'conflict';
415
+ interface UseStoredLayoutOptions {
416
+ /** From `createLayoutPersistence`. Keep it referentially stable. */
417
+ readonly persistence: LayoutPersistence;
418
+ /** Which dashboard and viewer. Changing its key loads the other layout. */
419
+ readonly scope: StoreScope;
420
+ /** Keep stable (module constant or `useMemo`). */
421
+ readonly definitions: readonly PageItem[];
422
+ /** The organization default: shown until loaded and when nothing is stored. */
423
+ readonly defaultLayout: DashboardLayout;
424
+ /** Wait this long after the last change before saving. Default 500 ms. */
425
+ readonly saveDelayMs?: number;
426
+ /** From the server render, to avoid a flash; used instead of `defaultLayout` first. */
427
+ readonly initialLayout?: DashboardLayout;
428
+ readonly normalizeOptions?: NormalizeOptions;
429
+ }
430
+ interface StoredLayoutConflict {
431
+ /** The layout this viewer was saving. */
432
+ readonly mine: DashboardLayout;
433
+ /** The layout stored by someone else. */
434
+ readonly theirs: DashboardLayout;
435
+ }
436
+ interface UseStoredLayoutResult {
437
+ /** Pass to `Dashboard` as `layout`. */
438
+ readonly layout: DashboardLayout;
439
+ /** Pass to `Dashboard` as `onLayoutChange`. Saves after `saveDelayMs`. */
440
+ readonly setLayout: (layout: DashboardLayout) => void;
441
+ /** The pre-edit snapshot, or null. */
442
+ readonly backup: DashboardLayout | null;
443
+ /** Stores a snapshot at once (not debounced). Pass null to clear it in memory only. */
444
+ readonly setBackup: (layout: DashboardLayout | null) => void;
445
+ readonly status: StoredLayoutStatus;
446
+ /** The latest failure, specific enough to log or show; null when none. */
447
+ readonly error: string | null;
448
+ /** Set while `status` is `'conflict'`. */
449
+ readonly conflict: StoredLayoutConflict | null;
450
+ /** Settle a conflict: keep this viewer's layout (overwrite) or take the stored one. */
451
+ readonly resolveConflict: (choice: 'mine' | 'theirs') => void;
452
+ /**
453
+ * A change made in another tab or device while this one had unsaved edits.
454
+ * Without unsaved edits it is applied automatically and this stays null.
455
+ */
456
+ readonly remoteLayout: DashboardLayout | null;
457
+ /** Use or ignore `remoteLayout`. */
458
+ readonly resolveRemote: (choice: 'use' | 'ignore') => void;
459
+ }
460
+ /**
461
+ * Joins a `LayoutPersistence` to `Dashboard`. The dashboard never waits on
462
+ * storage: it shows `initialLayout` or `defaultLayout` while loading, and a
463
+ * failed load or save keeps the in-memory layout working and reports `error`.
464
+ * Saves are debounced and flushed when the page is hidden. Effects don't run
465
+ * on the server, so a server render shows the initial or default layout.
466
+ */
467
+ declare function useStoredLayout(options: UseStoredLayoutOptions): UseStoredLayoutResult;
468
+
371
469
  interface UseWidgetsOptions extends ResolveOptions {
372
470
  /**
373
471
  * When each widget's provider starts. `'mount'` (default): right after the
@@ -383,12 +481,21 @@ interface UseWidgetsOptions extends ResolveOptions {
383
481
  * tab is hidden, and a widget still loading is not restarted.
384
482
  */
385
483
  readonly refreshMs?: number;
484
+ /**
485
+ * The viewer's chosen option values by widget key (see
486
+ * `WidgetDefinition.options`). Changing them reloads only the widgets whose
487
+ * resolved values changed; it never recreates the loader, so it may be a
488
+ * fresh object each render.
489
+ */
490
+ readonly optionValues?: Readonly<Record<string, Readonly<Record<string, unknown>> | undefined>>;
386
491
  }
387
492
  interface UseWidgetsResult {
388
493
  /** Pass to `Dashboard` or `WidgetGrid`: placeholders first, then results. */
389
494
  readonly widgets: readonly DashboardWidget[];
390
495
  /** Reload one widget (for example from the error card's Retry) or all. */
391
496
  readonly refresh: (key?: string) => void;
497
+ /** Choose option values for one widget; same effect as `optionValues`. */
498
+ readonly setOptions: (key: string, chosen: Readonly<Record<string, unknown>>) => void;
392
499
  /**
393
500
  * For `loadWhen: 'visible'`: attach to any element that contains the cards,
394
501
  * for example a wrapper `<div ref={gridRef}>` around `Dashboard`.
@@ -407,4 +514,4 @@ interface UseWidgetsResult {
407
514
  */
408
515
  declare function useWidgets<C extends WidgetContext>(definitions: readonly WidgetDefinition[], providers: WidgetProviders<C>, context: C, options?: UseWidgetsOptions): UseWidgetsResult;
409
516
 
410
- export { AlertListWidget, BarListWidget, DEFAULT_LABELS, DEFAULT_SERIES_COLORS, Dashboard, type DashboardClassNames, type DashboardClassSlot, type DashboardLabels, type DashboardProps, type DetailLoadState, type DetailLoader, GaugeWidget, GraphWidget, KpiWidget, ResolvedWidgetCard, type ResolvedWidgetCardProps, TableWidget, TextWidget, Thumbnail, type UseWidgetsOptions, type UseWidgetsResult, WidgetCard, type WidgetCardProps, WidgetContent, WidgetDetail, WidgetDetailDialog, type WidgetDetailDialogProps, type WidgetDetailProps, WidgetGrid, type WidgetGridProps, WidgetLink, type WidgetSettings, WidgetSettingsProvider, barPath, buildChartModel, describeChart, joinClassNames, seriesColor, useDetailData, useWidgetSettings, useWidgets, widgetTitle };
517
+ export { AlertListWidget, BarListWidget, DEFAULT_LABELS, DEFAULT_SERIES_COLORS, Dashboard, type DashboardClassNames, type DashboardClassSlot, type DashboardLabels, type DashboardProps, type DetailLoadState, type DetailLoader, GaugeWidget, GraphWidget, KpiWidget, ResolvedWidgetCard, type ResolvedWidgetCardProps, type StoredLayoutConflict, type StoredLayoutStatus, TableWidget, TextWidget, Thumbnail, type UseStoredLayoutOptions, type UseStoredLayoutResult, type UseWidgetsOptions, type UseWidgetsResult, WidgetCard, type WidgetCardProps, WidgetContent, WidgetDetail, WidgetDetailDialog, type WidgetDetailDialogProps, type WidgetDetailProps, WidgetGrid, type WidgetGridProps, WidgetLink, type WidgetSettings, WidgetSettingsProvider, barPath, buildChartModel, describeChart, joinClassNames, seriesColor, useDetailData, useStoredLayout, useWidgetSettings, useWidgets, widgetTitle };
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, RefObject } from 'react';
2
- import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, L as Locale, f as DashboardLayout, A as AlertListWidgetData, B as BarListWidgetData, g as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, h as TextWidgetData, i as WidgetData, j as ResolveOptions, k as WidgetContext, l as WidgetProviders } from './scale-CrXxawQn.js';
2
+ import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, A as AlertListWidgetData, B as BarListWidgetData, g as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, h as DetailSort, i as TextWidgetData, j as WidgetData, k as LayoutPersistence, S as StoreScope, P as PageItem, l as NormalizeOptions, m as ResolveOptions, n as WidgetContext, o as WidgetProviders } from './storage-VaaysVnZ.js';
3
3
 
4
4
  interface WidgetCardProps {
5
5
  readonly title: string;
@@ -145,14 +145,16 @@ interface DetailLoadState {
145
145
  * `undefined`, `fallback` (for example the card's own complete data) is used
146
146
  * instead. `reload` runs it again. Keep `load` and `fallback` referentially
147
147
  * stable (`useCallback` / `useMemo`): a new value restarts the load.
148
+ * `optionValues` (the widget's resolved options) go to the loader as
149
+ * `options.options`.
148
150
  */
149
- declare function useDetailData(definition: WidgetDefinition, load: DetailLoader | undefined, enabled: boolean, fallback?: DetailData): {
151
+ declare function useDetailData(definition: WidgetDefinition, load: DetailLoader | undefined, enabled: boolean, fallback?: DetailData, optionValues?: OptionValues): {
150
152
  readonly state: DetailLoadState;
151
153
  readonly reload: () => void;
152
154
  };
153
155
 
154
156
  /** Every element that carries a stable `dwt-*` class, for `classNames`. */
155
- type DashboardClassSlot = 'dashboard' | 'hiddenBar' | 'toolbar' | 'grid' | 'card' | 'cardHeader' | 'cardTitle' | 'cardDescription' | 'cardActions' | 'cardBody' | 'cardFooter' | 'button' | 'status' | 'empty' | 'error' | 'text' | 'kpi' | 'gauge' | 'table' | 'barList' | 'alertList' | 'chart' | 'legend' | 'tooltip' | 'tableTwin' | 'detail';
157
+ type DashboardClassSlot = 'dashboard' | 'hiddenBar' | 'toolbar' | 'pageBar' | 'grid' | 'card' | 'cardHeader' | 'cardTitle' | 'cardDescription' | 'cardActions' | 'cardBody' | 'cardFooter' | 'button' | 'status' | 'empty' | 'error' | 'text' | 'kpi' | 'gauge' | 'table' | 'barList' | 'alertList' | 'chart' | 'legend' | 'tooltip' | 'tableTwin' | 'detail';
156
158
  /**
157
159
  * Extra classes per slot, appended to the `dwt-*` class (never replacing
158
160
  * it), e.g. `{ card: 'rounded-lg shadow-sm' }` for Tailwind.
@@ -190,6 +192,30 @@ interface DashboardLabels {
190
192
  readonly locked: (title: string) => string;
191
193
  /** The lock icon on a card shown to an administrator (`overrideLocks`). */
192
194
  readonly lockedForViewers: (title: string) => string;
195
+ /** Pages: names the tab list, and each tab ("Page 2 of 3: Sales"). */
196
+ readonly pageBar: string;
197
+ readonly pageTabName: (index: number, count: number, title: string) => string;
198
+ readonly previousPageButton: string;
199
+ readonly nextPageButton: string;
200
+ /** Page management while editing. */
201
+ readonly managePages: string;
202
+ readonly addPage: string;
203
+ readonly renamePage: (title: string) => string;
204
+ readonly pageTitle: string;
205
+ readonly savePageTitle: string;
206
+ readonly cancelPageTitle: string;
207
+ readonly deletePage: (title: string) => string;
208
+ readonly confirmDeletePage: (title: string) => string;
209
+ readonly movePageLeft: (title: string) => string;
210
+ readonly movePageRight: (title: string) => string;
211
+ /** The select on each card that moves it to another page. */
212
+ readonly moveToPage: (title: string) => string;
213
+ readonly moveToPagePlaceholder: string;
214
+ readonly moveToPageOption: (title: string, rowsFree: number) => string;
215
+ readonly newPageOption: string;
216
+ readonly movedToPage: (title: string, pageTitle: string) => string;
217
+ readonly pageFull: (pageTitle: string, maxRows: number) => string;
218
+ readonly emptyPage: string;
193
219
  /** Added to the accessible name of links that open in a new tab. */
194
220
  readonly opensInNewTab: string;
195
221
  /** The card's View button, opening the detail view. */
@@ -277,6 +303,19 @@ interface DashboardProps extends WidgetSettings {
277
303
  readonly defaultLayout?: DashboardLayout;
278
304
  /** Show the built-in Customize/Done/Reset toolbar (toggle mode). Default true. */
279
305
  readonly toolbar?: boolean;
306
+ /**
307
+ * The page in view (a page key) when the layout has pages. Controlled with
308
+ * `onActivePageChange`; without it the dashboard keeps its own, starting on
309
+ * `defaultActivePage` or the first page. Pages never listed fall back to
310
+ * the first.
311
+ */
312
+ readonly activePage?: string;
313
+ readonly defaultActivePage?: string;
314
+ readonly onActivePageChange?: (pageKey: string) => void;
315
+ /** Rows a page holds unless the page says otherwise. Default 4. */
316
+ readonly maxRows?: number;
317
+ /** Most pages the viewer can add while editing. Default: no limit. */
318
+ readonly maxPages?: number;
280
319
  readonly onRetry?: (key: string) => void;
281
320
  /**
282
321
  * Loads the full data for a widget's detail view (widgets whose definition
@@ -345,10 +384,12 @@ declare function GaugeWidget({ data, }: {
345
384
  readonly data: GaugeWidgetData;
346
385
  }): ReactNode;
347
386
  /** TABLE: a data table; cells with a safe `href` become links. */
348
- declare function TableWidget({ data, controls, }: {
387
+ declare function TableWidget({ data, controls, initialSort, }: {
349
388
  readonly data: TableWidgetData;
350
389
  /** Search box and sortable headers; see `WidgetDefinition.tableControls`. */
351
390
  readonly controls?: ResolvedTableControls | undefined;
391
+ /** The header sort to start with, for example from a `sort` option. */
392
+ readonly initialSort?: DetailSort | undefined;
352
393
  }): ReactNode;
353
394
  /**
354
395
  * BAR_LIST: labelled horizontal bars. One series, so one color (slot 1)
@@ -362,12 +403,69 @@ declare function AlertListWidget({ data, }: {
362
403
  readonly data: AlertListWidgetData;
363
404
  }): ReactNode;
364
405
  /** Renders any payload with the renderer for its kind. */
365
- declare function WidgetContent({ data, tableControls, }: {
406
+ declare function WidgetContent({ data, tableControls, initialSort, }: {
366
407
  readonly data: WidgetData;
367
408
  /** Search and sort for TABLE data; see `resolveTableControls`. */
368
409
  readonly tableControls?: ResolvedTableControls | undefined;
410
+ /** TABLE header sort to start with; see `sortFromOptions`. */
411
+ readonly initialSort?: DetailSort | undefined;
369
412
  }): ReactNode;
370
413
 
414
+ type StoredLayoutStatus = 'loading' | 'ready' | 'saving' | 'error' | 'conflict';
415
+ interface UseStoredLayoutOptions {
416
+ /** From `createLayoutPersistence`. Keep it referentially stable. */
417
+ readonly persistence: LayoutPersistence;
418
+ /** Which dashboard and viewer. Changing its key loads the other layout. */
419
+ readonly scope: StoreScope;
420
+ /** Keep stable (module constant or `useMemo`). */
421
+ readonly definitions: readonly PageItem[];
422
+ /** The organization default: shown until loaded and when nothing is stored. */
423
+ readonly defaultLayout: DashboardLayout;
424
+ /** Wait this long after the last change before saving. Default 500 ms. */
425
+ readonly saveDelayMs?: number;
426
+ /** From the server render, to avoid a flash; used instead of `defaultLayout` first. */
427
+ readonly initialLayout?: DashboardLayout;
428
+ readonly normalizeOptions?: NormalizeOptions;
429
+ }
430
+ interface StoredLayoutConflict {
431
+ /** The layout this viewer was saving. */
432
+ readonly mine: DashboardLayout;
433
+ /** The layout stored by someone else. */
434
+ readonly theirs: DashboardLayout;
435
+ }
436
+ interface UseStoredLayoutResult {
437
+ /** Pass to `Dashboard` as `layout`. */
438
+ readonly layout: DashboardLayout;
439
+ /** Pass to `Dashboard` as `onLayoutChange`. Saves after `saveDelayMs`. */
440
+ readonly setLayout: (layout: DashboardLayout) => void;
441
+ /** The pre-edit snapshot, or null. */
442
+ readonly backup: DashboardLayout | null;
443
+ /** Stores a snapshot at once (not debounced). Pass null to clear it in memory only. */
444
+ readonly setBackup: (layout: DashboardLayout | null) => void;
445
+ readonly status: StoredLayoutStatus;
446
+ /** The latest failure, specific enough to log or show; null when none. */
447
+ readonly error: string | null;
448
+ /** Set while `status` is `'conflict'`. */
449
+ readonly conflict: StoredLayoutConflict | null;
450
+ /** Settle a conflict: keep this viewer's layout (overwrite) or take the stored one. */
451
+ readonly resolveConflict: (choice: 'mine' | 'theirs') => void;
452
+ /**
453
+ * A change made in another tab or device while this one had unsaved edits.
454
+ * Without unsaved edits it is applied automatically and this stays null.
455
+ */
456
+ readonly remoteLayout: DashboardLayout | null;
457
+ /** Use or ignore `remoteLayout`. */
458
+ readonly resolveRemote: (choice: 'use' | 'ignore') => void;
459
+ }
460
+ /**
461
+ * Joins a `LayoutPersistence` to `Dashboard`. The dashboard never waits on
462
+ * storage: it shows `initialLayout` or `defaultLayout` while loading, and a
463
+ * failed load or save keeps the in-memory layout working and reports `error`.
464
+ * Saves are debounced and flushed when the page is hidden. Effects don't run
465
+ * on the server, so a server render shows the initial or default layout.
466
+ */
467
+ declare function useStoredLayout(options: UseStoredLayoutOptions): UseStoredLayoutResult;
468
+
371
469
  interface UseWidgetsOptions extends ResolveOptions {
372
470
  /**
373
471
  * When each widget's provider starts. `'mount'` (default): right after the
@@ -383,12 +481,21 @@ interface UseWidgetsOptions extends ResolveOptions {
383
481
  * tab is hidden, and a widget still loading is not restarted.
384
482
  */
385
483
  readonly refreshMs?: number;
484
+ /**
485
+ * The viewer's chosen option values by widget key (see
486
+ * `WidgetDefinition.options`). Changing them reloads only the widgets whose
487
+ * resolved values changed; it never recreates the loader, so it may be a
488
+ * fresh object each render.
489
+ */
490
+ readonly optionValues?: Readonly<Record<string, Readonly<Record<string, unknown>> | undefined>>;
386
491
  }
387
492
  interface UseWidgetsResult {
388
493
  /** Pass to `Dashboard` or `WidgetGrid`: placeholders first, then results. */
389
494
  readonly widgets: readonly DashboardWidget[];
390
495
  /** Reload one widget (for example from the error card's Retry) or all. */
391
496
  readonly refresh: (key?: string) => void;
497
+ /** Choose option values for one widget; same effect as `optionValues`. */
498
+ readonly setOptions: (key: string, chosen: Readonly<Record<string, unknown>>) => void;
392
499
  /**
393
500
  * For `loadWhen: 'visible'`: attach to any element that contains the cards,
394
501
  * for example a wrapper `<div ref={gridRef}>` around `Dashboard`.
@@ -407,4 +514,4 @@ interface UseWidgetsResult {
407
514
  */
408
515
  declare function useWidgets<C extends WidgetContext>(definitions: readonly WidgetDefinition[], providers: WidgetProviders<C>, context: C, options?: UseWidgetsOptions): UseWidgetsResult;
409
516
 
410
- export { AlertListWidget, BarListWidget, DEFAULT_LABELS, DEFAULT_SERIES_COLORS, Dashboard, type DashboardClassNames, type DashboardClassSlot, type DashboardLabels, type DashboardProps, type DetailLoadState, type DetailLoader, GaugeWidget, GraphWidget, KpiWidget, ResolvedWidgetCard, type ResolvedWidgetCardProps, TableWidget, TextWidget, Thumbnail, type UseWidgetsOptions, type UseWidgetsResult, WidgetCard, type WidgetCardProps, WidgetContent, WidgetDetail, WidgetDetailDialog, type WidgetDetailDialogProps, type WidgetDetailProps, WidgetGrid, type WidgetGridProps, WidgetLink, type WidgetSettings, WidgetSettingsProvider, barPath, buildChartModel, describeChart, joinClassNames, seriesColor, useDetailData, useWidgetSettings, useWidgets, widgetTitle };
517
+ export { AlertListWidget, BarListWidget, DEFAULT_LABELS, DEFAULT_SERIES_COLORS, Dashboard, type DashboardClassNames, type DashboardClassSlot, type DashboardLabels, type DashboardProps, type DetailLoadState, type DetailLoader, GaugeWidget, GraphWidget, KpiWidget, ResolvedWidgetCard, type ResolvedWidgetCardProps, type StoredLayoutConflict, type StoredLayoutStatus, TableWidget, TextWidget, Thumbnail, type UseStoredLayoutOptions, type UseStoredLayoutResult, type UseWidgetsOptions, type UseWidgetsResult, WidgetCard, type WidgetCardProps, WidgetContent, WidgetDetail, WidgetDetailDialog, type WidgetDetailDialogProps, type WidgetDetailProps, WidgetGrid, type WidgetGridProps, WidgetLink, type WidgetSettings, WidgetSettingsProvider, barPath, buildChartModel, describeChart, joinClassNames, seriesColor, useDetailData, useStoredLayout, useWidgetSettings, useWidgets, widgetTitle };