@richardmcquiston01/dashboard-widgets-toolkit 0.9.0 → 0.10.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/core.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as WidgetDefinition, W as WidgetSize, a as WidgetFill, D as DashboardWidget, k as WidgetContext, j as ResolveOptions, l as WidgetProviders, m as WidgetKind, n as Result, o as WidgetPayload } from './scale-CrXxawQn.cjs';
2
- export { p as AlertListItem, A as AlertListWidgetData, q as BarListItem, B as BarListWidgetData, C as CachedPayload, r as DEFAULT_COMPARISON_LABEL, s as DEFAULT_CURRENCY, t as DEFAULT_DETAIL_PAGE_SIZE, u as DEFAULT_EMPTY_TEXT, v as DETAIL_MODES, f as DashboardLayout, w as DeltaDirection, x as DeltaSentiment, y as DetailCell, z as DetailColumn, d as DetailData, E as DetailMode, F as DetailPage, H as DetailProvider, c as DetailProviderOptions, I as DetailProviders, e as DetailQuery, J as DetailSort, M as EMPTY_LAYOUT, O as EmptyWidget, P as EnforceLocksOptions, Q as Err, S as ErrorWidget, U as FormatOptions, g as GaugeWidgetData, V as GraphPoint, X as GraphSeries, G as GraphWidgetData, Y as KpiDelta, Z as KpiDeltaOptions, K as KpiWidgetData, _ as LayoutItem, $ as LoadingWidget, L as Locale, a0 as MAX_DETAIL_PAGE_SIZE, a1 as MAX_GRAPH_SERIES, N as NiceDomain, a2 as Ok, a3 as OkWidget, a4 as ProviderOptions, a5 as ResolvedDetailOptions, R as ResolvedTableControls, a6 as ResolvedWidget, a7 as ResolvedWidgetLock, a8 as SortDirection, a9 as TableCell, aa as TableColumn, T as TableWidgetData, h as TextWidgetData, ab as VALUE_FORMATS, ac as ValueFormat, ad as WIDGET_FILLS, ae as WIDGET_KINDS, af as WIDGET_SIZES, ag as WidgetCache, i as WidgetData, ah as WidgetDataOf, ai as WidgetDetailOptions, aj as WidgetEmptyState, ak as WidgetLock, al as WidgetProvider, am as WidgetStatus, an as WidgetTableControls, ao as cacheKeyFor, ap as defaultDetailQuery, aq as defineWidget, ar as deriveDetailData, as as describeUnknownError, at as emptyTextFor, au as emptyWidget, av as enforceLocks, aw as err, ax as failedWidget, ay as formatCount, az as formatPercentChange, aA as formatValue, aB as hiddenWidgets, aC as hideWidget, aD as isHidden, aE as isMinimized, aF as isWidgetEmptyState, aG as isWidgetKind, aH as isWidgetVisibleTo, aI as kpiDelta, aJ as labelStride, aK as loadingWidgets, aL as minimizeWidget, aM as moveWidget, aN as moveWidgetBy, aO as moveWidgetDown, aP as moveWidgetUp, aQ as niceDomain, aR as niceStep, aS as ok, aT as parseDetailQuery, aU as parseLayout, aV as percentChange, aW as pruneLayout, aX as queryRows, aY as resolveDetailOptions, aZ as resolvePayload, a_ as resolveTableControls, a$ as resolveWidget, b0 as resolveWidgetLock, b1 as resolveWidgets, b2 as restoreWidget, b3 as serializeDetailQuery, b4 as serializeLayout, b5 as shareOf, b6 as showWidget, b7 as sortDefinitions, b8 as tableDetailData, b9 as toggleHidden, ba as toggleMinimized, bb as validateDetailData, bc as visibleWidgets, bd as widgetsFor } from './scale-CrXxawQn.cjs';
1
+ import { b as WidgetDefinition, W as WidgetSize, a as WidgetFill, D as DashboardWidget, k as WidgetContext, j as ResolveOptions, l as WidgetProviders, m as LayoutItem, f as DashboardLayout, n as Result, o as LayoutPage, p as WidgetKind, q as WidgetPayload } from './scale-N69bo7wo.cjs';
2
+ export { r as AlertListItem, A as AlertListWidgetData, s as BarListItem, B as BarListWidgetData, C as CachedPayload, t as DEFAULT_COMPARISON_LABEL, u as DEFAULT_CURRENCY, v as DEFAULT_DETAIL_PAGE_SIZE, w as DEFAULT_EMPTY_TEXT, x as DETAIL_MODES, y as DeltaDirection, z as DeltaSentiment, E as DetailCell, F as DetailColumn, d as DetailData, H as DetailMode, I as DetailPage, J as DetailProvider, c as DetailProviderOptions, M as DetailProviders, e as DetailQuery, O as DetailSort, P as EMPTY_LAYOUT, Q as EmptyWidget, S as EnforceLocksOptions, U as Err, V as ErrorWidget, X as FormatOptions, g as GaugeWidgetData, Y as GraphPoint, Z as GraphSeries, G as GraphWidgetData, _ as KpiDelta, $ as KpiDeltaOptions, K as KpiWidgetData, a0 as LoadingWidget, L as Locale, a1 as MAX_DETAIL_PAGE_SIZE, a2 as MAX_GRAPH_SERIES, a3 as MAX_PAGE_ROWS, a4 as MAX_PAGE_TITLE_LENGTH, a5 as MAX_PARSED_PAGES, N as NiceDomain, a6 as Ok, a7 as OkWidget, a8 as ProviderOptions, a9 as ResolvedDetailOptions, R as ResolvedTableControls, aa as ResolvedWidget, ab as ResolvedWidgetLock, ac as SortDirection, ad as TableCell, ae as TableColumn, T as TableWidgetData, h as TextWidgetData, af as VALUE_FORMATS, ag as ValueFormat, ah as WIDGET_FILLS, ai as WIDGET_KINDS, aj as WIDGET_SIZES, ak as WidgetCache, i as WidgetData, al as WidgetDataOf, am as WidgetDetailOptions, an as WidgetEmptyState, ao as WidgetLock, ap as WidgetProvider, aq as WidgetStatus, ar as WidgetTableControls, as as cacheKeyFor, at as defaultDetailQuery, au as defineWidget, av as deriveDetailData, aw as describeUnknownError, ax as emptyTextFor, ay as emptyWidget, az as enforceLocks, aA as err, aB as failedWidget, aC as formatCount, aD as formatPercentChange, aE as formatValue, aF as hiddenWidgets, aG as hideWidget, aH as isHidden, aI as isMinimized, aJ as isWidgetEmptyState, aK as isWidgetKind, aL as isWidgetVisibleTo, aM as kpiDelta, aN as labelStride, aO as loadingWidgets, aP as minimizeWidget, aQ as moveWidget, aR as moveWidgetBy, aS as moveWidgetDown, aT as moveWidgetUp, aU as niceDomain, aV as niceStep, aW as ok, aX as parseDetailQuery, aY as parseLayout, aZ as percentChange, a_ as pruneLayout, a$ as queryRows, b0 as resolveDetailOptions, b1 as resolvePayload, b2 as resolveTableControls, b3 as resolveWidget, b4 as resolveWidgetLock, b5 as resolveWidgets, b6 as restoreWidget, b7 as serializeDetailQuery, b8 as serializeLayout, b9 as shareOf, ba as showWidget, bb as sortDefinitions, bc as tableDetailData, bd as toggleHidden, be as toggleMinimized, bf as validateDetailData, bg as visibleWidgets, bh as widgetsFor } from './scale-N69bo7wo.cjs';
3
3
 
4
4
  /**
5
5
  * Maker Toolkit compatibility. Its API (`apps/api/src/widgets`) serves
@@ -77,6 +77,26 @@ declare function fillColumnSpans(items: readonly GridItem[], columns: number, la
77
77
  * `width` (see `itemWidth`) and width-fillers share the leftover twelfths.
78
78
  */
79
79
  declare function fillWidthSpans(items: readonly GridItem[]): Map<string, number>;
80
+ /** One row of a placed grid: the widgets in it and their final column spans. */
81
+ interface PlacedRow {
82
+ readonly keys: readonly string[];
83
+ /** Column spans, in `keys` order, after width-fillers took the leftovers. */
84
+ readonly spans: readonly number[];
85
+ }
86
+ /**
87
+ * The rows `items` occupy in a 12-column grid, exactly as `fillWidthSpans`
88
+ * places them: left to right, a widget that doesn't fit in the rest of a row
89
+ * starts the next row whole (a widget is never split), and width-fillers then
90
+ * grow into the leftover columns. Growth never changes how many rows there
91
+ * are.
92
+ */
93
+ declare function placeRows(items: readonly GridItem[]): readonly PlacedRow[];
94
+ /**
95
+ * How many of `items`, in order, fit in `maxRows` rows of a 12-column grid.
96
+ * Placement is left to right, so this is the length of the longest prefix
97
+ * whose rows number at most `maxRows`.
98
+ */
99
+ declare function fitCount(items: readonly GridItem[], maxRows: number): number;
80
100
 
81
101
  /**
82
102
  * Loads widgets one by one, after the first render, and reports each result
@@ -122,6 +142,117 @@ interface WidgetLoader {
122
142
  }
123
143
  declare function createWidgetLoader<C extends WidgetContext>(options: WidgetLoaderOptions<C>): WidgetLoader;
124
144
 
145
+ /**
146
+ * Pages of widgets: a dashboard split into pages, like the home screens of a
147
+ * phone. Each page is a small layout (order, hidden, minimized) with a name
148
+ * and a capacity of `maxRows` rows of 12 columns. Pure functions, in the
149
+ * style of `layout.ts`: inputs are never mutated, a refusal is a `Result`
150
+ * with a specific message, and a no-op returns the same object.
151
+ *
152
+ * A layout without `pages` has one implicit page (`DEFAULT_PAGE_KEY`), so
153
+ * everything here also works on layouts saved before pages existed.
154
+ */
155
+
156
+ /** The key of the implicit page of a layout that has no `pages`. */
157
+ declare const DEFAULT_PAGE_KEY = "default";
158
+ /** Rows a page holds unless it (or the dashboard) says otherwise. */
159
+ declare const DEFAULT_PAGE_ROWS = 4;
160
+ /** What the page functions need from a widget definition. */
161
+ type PageItem = LayoutItem & GridItem & {
162
+ /** Used in messages; the key stands in when absent. */
163
+ readonly title?: string;
164
+ };
165
+ interface PageOptions {
166
+ /** Rows a page holds when it has no `maxRows` of its own. Default 4. */
167
+ readonly maxRows?: number;
168
+ }
169
+ /** Whether the layout has pages of its own (rather than one implicit page). */
170
+ declare function hasPages(layout: DashboardLayout): boolean;
171
+ /**
172
+ * The layout's pages. A layout without `pages` has one implicit page called
173
+ * "Page 1" made from its top-level lists.
174
+ */
175
+ declare function pageList(layout: DashboardLayout): readonly LayoutPage[];
176
+ /**
177
+ * One page as an ordinary layout, so every function in `layout.ts` (move,
178
+ * hide, minimize, `visibleWidgets`) works on it unchanged. For a layout with
179
+ * no pages this is the layout itself. Undefined for an unknown page.
180
+ */
181
+ declare function pageLayout(layout: DashboardLayout, pageKey: string): DashboardLayout | undefined;
182
+ /**
183
+ * Writes a page's layout (changed with the functions in `layout.ts`) back
184
+ * into the whole layout. Returns the same object when nothing changed or the
185
+ * page doesn't exist.
186
+ */
187
+ declare function withPageLayout(layout: DashboardLayout, pageKey: string, next: DashboardLayout): DashboardLayout;
188
+ /** The key of the page a `page` reference names: a key, else a title. */
189
+ declare function resolvePageKey(layout: DashboardLayout, reference: string | undefined): string | undefined;
190
+ /**
191
+ * Which page each widget shows on: the page that lists it (in its order or
192
+ * hidden list), else its home page (`definition.page`, else the first page).
193
+ * A widget locked against moving always shows on its home page, so a viewer's
194
+ * saved layout can't move it. Definitions keep their input order.
195
+ */
196
+ declare function assignPages<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout): Map<string, T[]>;
197
+ /** The key of the page a widget shows on; undefined if it isn't a definition. */
198
+ declare function pageOf<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout, key: string): string | undefined;
199
+ /** A page's visible widgets, in display order (minimized ones included). */
200
+ declare function pageWidgets<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string): T[];
201
+ /** How full a page is. */
202
+ interface PageRoom {
203
+ readonly maxRows: number;
204
+ readonly rowsUsed: number;
205
+ readonly rowsFree: number;
206
+ }
207
+ /** Rows a page allows, uses and has left, as the grid will draw them. */
208
+ declare function pageRoom<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string, options?: PageOptions): PageRoom | undefined;
209
+ /** The first `page-N` key no page uses. */
210
+ declare function nextPageKey(layout: DashboardLayout): string;
211
+ interface AddPageOptions {
212
+ /** The new page's title. Default: the next free "Page N". */
213
+ readonly title?: string;
214
+ /** The new page's key. Default: the next free `page-N`. */
215
+ readonly key?: string;
216
+ }
217
+ /**
218
+ * Adds an empty page after the last one. A layout without pages gains an
219
+ * explicit first page holding everything it had.
220
+ */
221
+ declare function addPage(layout: DashboardLayout, options?: AddPageOptions): Result<DashboardLayout>;
222
+ /** Renames a page. The same layout comes back when the title is unchanged. */
223
+ declare function renamePage(layout: DashboardLayout, pageKey: string, title: string): Result<DashboardLayout>;
224
+ /**
225
+ * Moves a page `offset` places (negative is earlier), clamped at the ends.
226
+ * Returns the same layout when nothing moves.
227
+ */
228
+ declare function movePage(layout: DashboardLayout, pageKey: string, offset: number): DashboardLayout;
229
+ /**
230
+ * Removes a page. Its widgets move to the end of the previous page (the next
231
+ * one when it was first), keeping their hidden and minimized state. Refused
232
+ * for the only page, and when the widgets wouldn't fit on the pages left.
233
+ */
234
+ declare function removePage<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string, options?: PageOptions): Result<DashboardLayout>;
235
+ /**
236
+ * Moves a widget to the end of another page, keeping its hidden and
237
+ * minimized state. Refused for an unknown widget or page, for a widget locked
238
+ * against moving, and when a visible widget wouldn't fit in the page's rows.
239
+ */
240
+ declare function moveWidgetToPage<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, widgetKey: string, targetKey: string, options?: PageOptions): Result<DashboardLayout>;
241
+ interface NormalizeOptions extends PageOptions {
242
+ /** Skip lock enforcement, for a user who may rearrange locked widgets. */
243
+ readonly overrideLocks?: boolean;
244
+ }
245
+ /**
246
+ * Repairs a layout so it can be trusted, for the place it is saved: unknown
247
+ * widgets are dropped, locks are enforced, and in a paged layout each widget
248
+ * lives on one page, titles are trimmed, unique and short, widgets no page
249
+ * lists yet are placed (on their home page), and a page that holds too many
250
+ * rows has its overflow moved, in order, to the next page with room or a new
251
+ * page after it. Nothing is hidden or dropped to make room. Idempotent;
252
+ * returns the same object when nothing changes.
253
+ */
254
+ declare function normalizeLayout<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, options?: NormalizeOptions): DashboardLayout;
255
+
125
256
  /**
126
257
  * Link and image URL checks. Payloads often come from an API, so a link is
127
258
  * only rendered when it can't run script: http(s), mailto, or a relative
@@ -159,4 +290,4 @@ declare function validateWidgetData(value: unknown, options?: ValidateWidgetData
159
290
  */
160
291
  declare function validateWidgetDefinition(value: unknown): Result<WidgetDefinition>;
161
292
 
162
- export { DashboardWidget, type GridItem, type LegacyWidgetDefinition, MAX_REPORTED_PROBLEMS, MAX_WIDGET_WIDTH, MIN_WIDGET_WIDTH, type RefreshOptions, ResolveOptions, Result, type ValidateWidgetDataOptions, WIDTH_COLUMNS, WidgetContext, WidgetDefinition, WidgetFill, WidgetKind, type WidgetLoader, type WidgetLoaderOptions, WidgetPayload, WidgetProviders, WidgetSize, baseColumnSpan, createWidgetLoader, fillColumnSpans, fillWidthSpans, fillsHeight, fillsWidth, fromLegacyDefinition, isSafeHref, isSafeImageUrl, isWidgetWidth, itemWidth, upgradeLegacyWidgetData, usesWidthColumns, validateWidgetData, validateWidgetDefinition, widthForSize };
293
+ export { type AddPageOptions, DEFAULT_PAGE_KEY, DEFAULT_PAGE_ROWS, DashboardLayout, DashboardWidget, type GridItem, LayoutItem, LayoutPage, type LegacyWidgetDefinition, MAX_REPORTED_PROBLEMS, MAX_WIDGET_WIDTH, MIN_WIDGET_WIDTH, type NormalizeOptions, type PageItem, type PageOptions, type PageRoom, type PlacedRow, type RefreshOptions, ResolveOptions, Result, type ValidateWidgetDataOptions, WIDTH_COLUMNS, WidgetContext, WidgetDefinition, WidgetFill, WidgetKind, type WidgetLoader, type WidgetLoaderOptions, WidgetPayload, WidgetProviders, WidgetSize, addPage, assignPages, baseColumnSpan, createWidgetLoader, fillColumnSpans, fillWidthSpans, fillsHeight, fillsWidth, fitCount, fromLegacyDefinition, hasPages, isSafeHref, isSafeImageUrl, isWidgetWidth, itemWidth, movePage, moveWidgetToPage, nextPageKey, normalizeLayout, pageLayout, pageList, pageOf, pageRoom, pageWidgets, placeRows, removePage, renamePage, resolvePageKey, upgradeLegacyWidgetData, usesWidthColumns, validateWidgetData, validateWidgetDefinition, widthForSize, withPageLayout };
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as WidgetDefinition, W as WidgetSize, a as WidgetFill, D as DashboardWidget, k as WidgetContext, j as ResolveOptions, l as WidgetProviders, m as WidgetKind, n as Result, o as WidgetPayload } from './scale-CrXxawQn.js';
2
- export { p as AlertListItem, A as AlertListWidgetData, q as BarListItem, B as BarListWidgetData, C as CachedPayload, r as DEFAULT_COMPARISON_LABEL, s as DEFAULT_CURRENCY, t as DEFAULT_DETAIL_PAGE_SIZE, u as DEFAULT_EMPTY_TEXT, v as DETAIL_MODES, f as DashboardLayout, w as DeltaDirection, x as DeltaSentiment, y as DetailCell, z as DetailColumn, d as DetailData, E as DetailMode, F as DetailPage, H as DetailProvider, c as DetailProviderOptions, I as DetailProviders, e as DetailQuery, J as DetailSort, M as EMPTY_LAYOUT, O as EmptyWidget, P as EnforceLocksOptions, Q as Err, S as ErrorWidget, U as FormatOptions, g as GaugeWidgetData, V as GraphPoint, X as GraphSeries, G as GraphWidgetData, Y as KpiDelta, Z as KpiDeltaOptions, K as KpiWidgetData, _ as LayoutItem, $ as LoadingWidget, L as Locale, a0 as MAX_DETAIL_PAGE_SIZE, a1 as MAX_GRAPH_SERIES, N as NiceDomain, a2 as Ok, a3 as OkWidget, a4 as ProviderOptions, a5 as ResolvedDetailOptions, R as ResolvedTableControls, a6 as ResolvedWidget, a7 as ResolvedWidgetLock, a8 as SortDirection, a9 as TableCell, aa as TableColumn, T as TableWidgetData, h as TextWidgetData, ab as VALUE_FORMATS, ac as ValueFormat, ad as WIDGET_FILLS, ae as WIDGET_KINDS, af as WIDGET_SIZES, ag as WidgetCache, i as WidgetData, ah as WidgetDataOf, ai as WidgetDetailOptions, aj as WidgetEmptyState, ak as WidgetLock, al as WidgetProvider, am as WidgetStatus, an as WidgetTableControls, ao as cacheKeyFor, ap as defaultDetailQuery, aq as defineWidget, ar as deriveDetailData, as as describeUnknownError, at as emptyTextFor, au as emptyWidget, av as enforceLocks, aw as err, ax as failedWidget, ay as formatCount, az as formatPercentChange, aA as formatValue, aB as hiddenWidgets, aC as hideWidget, aD as isHidden, aE as isMinimized, aF as isWidgetEmptyState, aG as isWidgetKind, aH as isWidgetVisibleTo, aI as kpiDelta, aJ as labelStride, aK as loadingWidgets, aL as minimizeWidget, aM as moveWidget, aN as moveWidgetBy, aO as moveWidgetDown, aP as moveWidgetUp, aQ as niceDomain, aR as niceStep, aS as ok, aT as parseDetailQuery, aU as parseLayout, aV as percentChange, aW as pruneLayout, aX as queryRows, aY as resolveDetailOptions, aZ as resolvePayload, a_ as resolveTableControls, a$ as resolveWidget, b0 as resolveWidgetLock, b1 as resolveWidgets, b2 as restoreWidget, b3 as serializeDetailQuery, b4 as serializeLayout, b5 as shareOf, b6 as showWidget, b7 as sortDefinitions, b8 as tableDetailData, b9 as toggleHidden, ba as toggleMinimized, bb as validateDetailData, bc as visibleWidgets, bd as widgetsFor } from './scale-CrXxawQn.js';
1
+ import { b as WidgetDefinition, W as WidgetSize, a as WidgetFill, D as DashboardWidget, k as WidgetContext, j as ResolveOptions, l as WidgetProviders, m as LayoutItem, f as DashboardLayout, n as Result, o as LayoutPage, p as WidgetKind, q as WidgetPayload } from './scale-N69bo7wo.js';
2
+ export { r as AlertListItem, A as AlertListWidgetData, s as BarListItem, B as BarListWidgetData, C as CachedPayload, t as DEFAULT_COMPARISON_LABEL, u as DEFAULT_CURRENCY, v as DEFAULT_DETAIL_PAGE_SIZE, w as DEFAULT_EMPTY_TEXT, x as DETAIL_MODES, y as DeltaDirection, z as DeltaSentiment, E as DetailCell, F as DetailColumn, d as DetailData, H as DetailMode, I as DetailPage, J as DetailProvider, c as DetailProviderOptions, M as DetailProviders, e as DetailQuery, O as DetailSort, P as EMPTY_LAYOUT, Q as EmptyWidget, S as EnforceLocksOptions, U as Err, V as ErrorWidget, X as FormatOptions, g as GaugeWidgetData, Y as GraphPoint, Z as GraphSeries, G as GraphWidgetData, _ as KpiDelta, $ as KpiDeltaOptions, K as KpiWidgetData, a0 as LoadingWidget, L as Locale, a1 as MAX_DETAIL_PAGE_SIZE, a2 as MAX_GRAPH_SERIES, a3 as MAX_PAGE_ROWS, a4 as MAX_PAGE_TITLE_LENGTH, a5 as MAX_PARSED_PAGES, N as NiceDomain, a6 as Ok, a7 as OkWidget, a8 as ProviderOptions, a9 as ResolvedDetailOptions, R as ResolvedTableControls, aa as ResolvedWidget, ab as ResolvedWidgetLock, ac as SortDirection, ad as TableCell, ae as TableColumn, T as TableWidgetData, h as TextWidgetData, af as VALUE_FORMATS, ag as ValueFormat, ah as WIDGET_FILLS, ai as WIDGET_KINDS, aj as WIDGET_SIZES, ak as WidgetCache, i as WidgetData, al as WidgetDataOf, am as WidgetDetailOptions, an as WidgetEmptyState, ao as WidgetLock, ap as WidgetProvider, aq as WidgetStatus, ar as WidgetTableControls, as as cacheKeyFor, at as defaultDetailQuery, au as defineWidget, av as deriveDetailData, aw as describeUnknownError, ax as emptyTextFor, ay as emptyWidget, az as enforceLocks, aA as err, aB as failedWidget, aC as formatCount, aD as formatPercentChange, aE as formatValue, aF as hiddenWidgets, aG as hideWidget, aH as isHidden, aI as isMinimized, aJ as isWidgetEmptyState, aK as isWidgetKind, aL as isWidgetVisibleTo, aM as kpiDelta, aN as labelStride, aO as loadingWidgets, aP as minimizeWidget, aQ as moveWidget, aR as moveWidgetBy, aS as moveWidgetDown, aT as moveWidgetUp, aU as niceDomain, aV as niceStep, aW as ok, aX as parseDetailQuery, aY as parseLayout, aZ as percentChange, a_ as pruneLayout, a$ as queryRows, b0 as resolveDetailOptions, b1 as resolvePayload, b2 as resolveTableControls, b3 as resolveWidget, b4 as resolveWidgetLock, b5 as resolveWidgets, b6 as restoreWidget, b7 as serializeDetailQuery, b8 as serializeLayout, b9 as shareOf, ba as showWidget, bb as sortDefinitions, bc as tableDetailData, bd as toggleHidden, be as toggleMinimized, bf as validateDetailData, bg as visibleWidgets, bh as widgetsFor } from './scale-N69bo7wo.js';
3
3
 
4
4
  /**
5
5
  * Maker Toolkit compatibility. Its API (`apps/api/src/widgets`) serves
@@ -77,6 +77,26 @@ declare function fillColumnSpans(items: readonly GridItem[], columns: number, la
77
77
  * `width` (see `itemWidth`) and width-fillers share the leftover twelfths.
78
78
  */
79
79
  declare function fillWidthSpans(items: readonly GridItem[]): Map<string, number>;
80
+ /** One row of a placed grid: the widgets in it and their final column spans. */
81
+ interface PlacedRow {
82
+ readonly keys: readonly string[];
83
+ /** Column spans, in `keys` order, after width-fillers took the leftovers. */
84
+ readonly spans: readonly number[];
85
+ }
86
+ /**
87
+ * The rows `items` occupy in a 12-column grid, exactly as `fillWidthSpans`
88
+ * places them: left to right, a widget that doesn't fit in the rest of a row
89
+ * starts the next row whole (a widget is never split), and width-fillers then
90
+ * grow into the leftover columns. Growth never changes how many rows there
91
+ * are.
92
+ */
93
+ declare function placeRows(items: readonly GridItem[]): readonly PlacedRow[];
94
+ /**
95
+ * How many of `items`, in order, fit in `maxRows` rows of a 12-column grid.
96
+ * Placement is left to right, so this is the length of the longest prefix
97
+ * whose rows number at most `maxRows`.
98
+ */
99
+ declare function fitCount(items: readonly GridItem[], maxRows: number): number;
80
100
 
81
101
  /**
82
102
  * Loads widgets one by one, after the first render, and reports each result
@@ -122,6 +142,117 @@ interface WidgetLoader {
122
142
  }
123
143
  declare function createWidgetLoader<C extends WidgetContext>(options: WidgetLoaderOptions<C>): WidgetLoader;
124
144
 
145
+ /**
146
+ * Pages of widgets: a dashboard split into pages, like the home screens of a
147
+ * phone. Each page is a small layout (order, hidden, minimized) with a name
148
+ * and a capacity of `maxRows` rows of 12 columns. Pure functions, in the
149
+ * style of `layout.ts`: inputs are never mutated, a refusal is a `Result`
150
+ * with a specific message, and a no-op returns the same object.
151
+ *
152
+ * A layout without `pages` has one implicit page (`DEFAULT_PAGE_KEY`), so
153
+ * everything here also works on layouts saved before pages existed.
154
+ */
155
+
156
+ /** The key of the implicit page of a layout that has no `pages`. */
157
+ declare const DEFAULT_PAGE_KEY = "default";
158
+ /** Rows a page holds unless it (or the dashboard) says otherwise. */
159
+ declare const DEFAULT_PAGE_ROWS = 4;
160
+ /** What the page functions need from a widget definition. */
161
+ type PageItem = LayoutItem & GridItem & {
162
+ /** Used in messages; the key stands in when absent. */
163
+ readonly title?: string;
164
+ };
165
+ interface PageOptions {
166
+ /** Rows a page holds when it has no `maxRows` of its own. Default 4. */
167
+ readonly maxRows?: number;
168
+ }
169
+ /** Whether the layout has pages of its own (rather than one implicit page). */
170
+ declare function hasPages(layout: DashboardLayout): boolean;
171
+ /**
172
+ * The layout's pages. A layout without `pages` has one implicit page called
173
+ * "Page 1" made from its top-level lists.
174
+ */
175
+ declare function pageList(layout: DashboardLayout): readonly LayoutPage[];
176
+ /**
177
+ * One page as an ordinary layout, so every function in `layout.ts` (move,
178
+ * hide, minimize, `visibleWidgets`) works on it unchanged. For a layout with
179
+ * no pages this is the layout itself. Undefined for an unknown page.
180
+ */
181
+ declare function pageLayout(layout: DashboardLayout, pageKey: string): DashboardLayout | undefined;
182
+ /**
183
+ * Writes a page's layout (changed with the functions in `layout.ts`) back
184
+ * into the whole layout. Returns the same object when nothing changed or the
185
+ * page doesn't exist.
186
+ */
187
+ declare function withPageLayout(layout: DashboardLayout, pageKey: string, next: DashboardLayout): DashboardLayout;
188
+ /** The key of the page a `page` reference names: a key, else a title. */
189
+ declare function resolvePageKey(layout: DashboardLayout, reference: string | undefined): string | undefined;
190
+ /**
191
+ * Which page each widget shows on: the page that lists it (in its order or
192
+ * hidden list), else its home page (`definition.page`, else the first page).
193
+ * A widget locked against moving always shows on its home page, so a viewer's
194
+ * saved layout can't move it. Definitions keep their input order.
195
+ */
196
+ declare function assignPages<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout): Map<string, T[]>;
197
+ /** The key of the page a widget shows on; undefined if it isn't a definition. */
198
+ declare function pageOf<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout, key: string): string | undefined;
199
+ /** A page's visible widgets, in display order (minimized ones included). */
200
+ declare function pageWidgets<T extends LayoutItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string): T[];
201
+ /** How full a page is. */
202
+ interface PageRoom {
203
+ readonly maxRows: number;
204
+ readonly rowsUsed: number;
205
+ readonly rowsFree: number;
206
+ }
207
+ /** Rows a page allows, uses and has left, as the grid will draw them. */
208
+ declare function pageRoom<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string, options?: PageOptions): PageRoom | undefined;
209
+ /** The first `page-N` key no page uses. */
210
+ declare function nextPageKey(layout: DashboardLayout): string;
211
+ interface AddPageOptions {
212
+ /** The new page's title. Default: the next free "Page N". */
213
+ readonly title?: string;
214
+ /** The new page's key. Default: the next free `page-N`. */
215
+ readonly key?: string;
216
+ }
217
+ /**
218
+ * Adds an empty page after the last one. A layout without pages gains an
219
+ * explicit first page holding everything it had.
220
+ */
221
+ declare function addPage(layout: DashboardLayout, options?: AddPageOptions): Result<DashboardLayout>;
222
+ /** Renames a page. The same layout comes back when the title is unchanged. */
223
+ declare function renamePage(layout: DashboardLayout, pageKey: string, title: string): Result<DashboardLayout>;
224
+ /**
225
+ * Moves a page `offset` places (negative is earlier), clamped at the ends.
226
+ * Returns the same layout when nothing moves.
227
+ */
228
+ declare function movePage(layout: DashboardLayout, pageKey: string, offset: number): DashboardLayout;
229
+ /**
230
+ * Removes a page. Its widgets move to the end of the previous page (the next
231
+ * one when it was first), keeping their hidden and minimized state. Refused
232
+ * for the only page, and when the widgets wouldn't fit on the pages left.
233
+ */
234
+ declare function removePage<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, pageKey: string, options?: PageOptions): Result<DashboardLayout>;
235
+ /**
236
+ * Moves a widget to the end of another page, keeping its hidden and
237
+ * minimized state. Refused for an unknown widget or page, for a widget locked
238
+ * against moving, and when a visible widget wouldn't fit in the page's rows.
239
+ */
240
+ declare function moveWidgetToPage<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, widgetKey: string, targetKey: string, options?: PageOptions): Result<DashboardLayout>;
241
+ interface NormalizeOptions extends PageOptions {
242
+ /** Skip lock enforcement, for a user who may rearrange locked widgets. */
243
+ readonly overrideLocks?: boolean;
244
+ }
245
+ /**
246
+ * Repairs a layout so it can be trusted, for the place it is saved: unknown
247
+ * widgets are dropped, locks are enforced, and in a paged layout each widget
248
+ * lives on one page, titles are trimmed, unique and short, widgets no page
249
+ * lists yet are placed (on their home page), and a page that holds too many
250
+ * rows has its overflow moved, in order, to the next page with room or a new
251
+ * page after it. Nothing is hidden or dropped to make room. Idempotent;
252
+ * returns the same object when nothing changes.
253
+ */
254
+ declare function normalizeLayout<T extends PageItem>(definitions: readonly T[], layout: DashboardLayout, options?: NormalizeOptions): DashboardLayout;
255
+
125
256
  /**
126
257
  * Link and image URL checks. Payloads often come from an API, so a link is
127
258
  * only rendered when it can't run script: http(s), mailto, or a relative
@@ -159,4 +290,4 @@ declare function validateWidgetData(value: unknown, options?: ValidateWidgetData
159
290
  */
160
291
  declare function validateWidgetDefinition(value: unknown): Result<WidgetDefinition>;
161
292
 
162
- export { DashboardWidget, type GridItem, type LegacyWidgetDefinition, MAX_REPORTED_PROBLEMS, MAX_WIDGET_WIDTH, MIN_WIDGET_WIDTH, type RefreshOptions, ResolveOptions, Result, type ValidateWidgetDataOptions, WIDTH_COLUMNS, WidgetContext, WidgetDefinition, WidgetFill, WidgetKind, type WidgetLoader, type WidgetLoaderOptions, WidgetPayload, WidgetProviders, WidgetSize, baseColumnSpan, createWidgetLoader, fillColumnSpans, fillWidthSpans, fillsHeight, fillsWidth, fromLegacyDefinition, isSafeHref, isSafeImageUrl, isWidgetWidth, itemWidth, upgradeLegacyWidgetData, usesWidthColumns, validateWidgetData, validateWidgetDefinition, widthForSize };
293
+ export { type AddPageOptions, DEFAULT_PAGE_KEY, DEFAULT_PAGE_ROWS, DashboardLayout, DashboardWidget, type GridItem, LayoutItem, LayoutPage, type LegacyWidgetDefinition, MAX_REPORTED_PROBLEMS, MAX_WIDGET_WIDTH, MIN_WIDGET_WIDTH, type NormalizeOptions, type PageItem, type PageOptions, type PageRoom, type PlacedRow, type RefreshOptions, ResolveOptions, Result, type ValidateWidgetDataOptions, WIDTH_COLUMNS, WidgetContext, WidgetDefinition, WidgetFill, WidgetKind, type WidgetLoader, type WidgetLoaderOptions, WidgetPayload, WidgetProviders, WidgetSize, addPage, assignPages, baseColumnSpan, createWidgetLoader, fillColumnSpans, fillWidthSpans, fillsHeight, fillsWidth, fitCount, fromLegacyDefinition, hasPages, isSafeHref, isSafeImageUrl, isWidgetWidth, itemWidth, movePage, moveWidgetToPage, nextPageKey, normalizeLayout, pageLayout, pageList, pageOf, pageRoom, pageWidgets, placeRows, removePage, renamePage, resolvePageKey, upgradeLegacyWidgetData, usesWidthColumns, validateWidgetData, validateWidgetDefinition, widthForSize, withPageLayout };