@richardmcquiston01/dashboard-widgets-toolkit 0.1.0 → 0.4.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/README.md +113 -8
- package/dist/core.cjs +690 -64
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +87 -18
- package/dist/core.d.ts +87 -18
- package/dist/core.js +666 -65
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +690 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +666 -65
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1594 -72
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +164 -14
- package/dist/react.d.ts +164 -14
- package/dist/react.js +1592 -74
- package/dist/react.js.map +1 -1
- package/dist/{scale-WlRozDCf.d.cts → scale-dWDGE1zW.d.cts} +327 -108
- package/dist/{scale-WlRozDCf.d.ts → scale-dWDGE1zW.d.ts} +327 -108
- package/dist/styles.css +156 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
`@richardmcquiston01/dashboard-widgets-toolkit` is a framework-agnostic
|
|
9
9
|
dashboard widget toolkit: typed widget definitions and data payloads (KPI,
|
|
10
10
|
gauge, table, bar list, alert list, chart), user layout (order, hide,
|
|
11
|
-
|
|
11
|
+
minimize), and React renderers. Bring your own data providers.
|
|
12
12
|
|
|
13
13
|
It has three parts:
|
|
14
14
|
|
|
@@ -179,11 +179,16 @@ export function ShopDashboard({ widgets }: { widgets: ResolvedWidget[] }) {
|
|
|
179
179
|
|
|
180
180
|
`Dashboard` orders widgets by the saved layout (saved order first, new widgets
|
|
181
181
|
appended by `sortOrder`, hidden ones removed), and gives each card move
|
|
182
|
-
earlier/later, hide and
|
|
183
|
-
widgets back.
|
|
182
|
+
earlier/later, hide and minimize buttons, plus a "Hidden:" bar to bring
|
|
183
|
+
widgets back. A minimized widget leaves the grid (so it stops taking space)
|
|
184
|
+
and waits in a "Minimized:" bar until the viewer expands it. Without `onLayoutChange` it is read-only. Use `loadingWidgets`
|
|
184
185
|
for placeholders while data loads, and `WidgetGrid` for a plain grid with no
|
|
185
186
|
layout controls.
|
|
186
187
|
|
|
188
|
+
Links open in the same tab unless you set `linkTarget` (for example
|
|
189
|
+
`"_blank"`); links that open a new tab get a small external-link icon and
|
|
190
|
+
"(opens in a new tab)" for screen readers (label `opensInNewTab`).
|
|
191
|
+
|
|
187
192
|
### Examples
|
|
188
193
|
|
|
189
194
|
**Layout functions on their own** (pure; the input is never mutated):
|
|
@@ -232,7 +237,7 @@ override its custom properties:
|
|
|
232
237
|
|
|
233
238
|
```css
|
|
234
239
|
.dwt-dashboard {
|
|
235
|
-
--dwt-series-1: #567d62; /* your brand
|
|
240
|
+
--dwt-series-1: #567d62; /* your brand color for single-series charts */
|
|
236
241
|
--dwt-radius: 4px;
|
|
237
242
|
}
|
|
238
243
|
```
|
|
@@ -240,12 +245,112 @@ override its custom properties:
|
|
|
240
245
|
Dark mode follows the OS setting unless the page sets `data-theme="light"`;
|
|
241
246
|
`data-theme="dark"` or a `dark` class on `<html>` forces it.
|
|
242
247
|
|
|
248
|
+
**Widget width.** Give a widget a `width` to say how much of the row it
|
|
249
|
+
takes, in twelfths (like a 12-column grid): an integer from 2 to 12. A table
|
|
250
|
+
with many columns might want half the row:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
defineWidget({ key: 'top-products', title: 'Most popular products', kind: 'TABLE', width: 8 });
|
|
254
|
+
defineWidget({ key: 'ratings', title: 'Rating breakdown', kind: 'BAR_LIST', width: 4 });
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
When any widget in a grid sets `width`, the grid becomes 12 columns
|
|
258
|
+
(`dwt-grid--twelve`) and each card spans `--dwt-width` columns. Widgets
|
|
259
|
+
without a `width` use one from their `defaultSize` (small 3, medium 4, large
|
|
260
|
+
6, full 12). Narrow grids give widgets more room: under 900px a widget gets
|
|
261
|
+
twice its width, under 560px it takes the whole row. `fill: 'width'` still
|
|
262
|
+
works, sharing the twelfths left over in a row. The validator rejects
|
|
263
|
+
anything but an integer from 2 to 12.
|
|
264
|
+
|
|
265
|
+
**Detail view.** Set `detail: true` (or `{ title, pageSize, mode }`) on a
|
|
266
|
+
definition and `Dashboard` adds a "View" eye button to the card (the title is
|
|
267
|
+
clickable too). It opens a modal dialog with search, per-column filters,
|
|
268
|
+
sortable headers and paging. Where the data comes from:
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
<Dashboard
|
|
272
|
+
widgets={widgets}
|
|
273
|
+
loadDetail={(definition, { signal, query }) => fetchAllRows(definition.key, signal)}
|
|
274
|
+
/>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
- `loadDetail` (close over your own context; the package never fetches)
|
|
278
|
+
returns a `DetailData` table: columns with a `key`, rows of cells with
|
|
279
|
+
`text` and an optional `value` used for sorting and filtering.
|
|
280
|
+
- Without it, a TABLE with no `footer` and a BAR_LIST show their own card data;
|
|
281
|
+
other widgets get no View button until you pass `loadDetail`.
|
|
282
|
+
- `onOpenDetail={(key) => navigate(...)}` replaces the built-in dialog so you
|
|
283
|
+
can open your own page.
|
|
284
|
+
- The pieces are exported for your own layout: `WidgetDetail` (controlled by
|
|
285
|
+
a `DetailQuery`), `WidgetDetailDialog` and `useDetailData`. In the core,
|
|
286
|
+
`queryRows` does the filtering, sorting and paging (case- and
|
|
287
|
+
accent-insensitive, numeric-aware), `serializeDetailQuery` /
|
|
288
|
+
`parseDetailQuery` keep the query in a URL, and `validateDetailData` checks
|
|
289
|
+
what your loader returns.
|
|
290
|
+
|
|
291
|
+
Server-side paging and URL deep links are next; see
|
|
292
|
+
[docs/design/detail-view.md](./docs/design/detail-view.md).
|
|
293
|
+
|
|
294
|
+
**Filling space.** By default each card is only as big as its content, so a
|
|
295
|
+
short card beside a tall one leaves a gap. Set `fill` on a widget definition
|
|
296
|
+
to have it use the free space in its grid row:
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
defineWidget({ key: 'countries', title: 'Orders by country', kind: 'BAR_LIST', fill: 'height' });
|
|
300
|
+
defineWidget({ key: 'notes', title: 'Notes', kind: 'TEXT', fill: 'width' });
|
|
301
|
+
defineWidget({ key: 'trend', title: 'Trend', kind: 'GRAPH', defaultSize: 'large', fill: 'both' });
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
| `fill` | Effect |
|
|
305
|
+
| -------- | ------------------------------------------------------------------- |
|
|
306
|
+
| `height` | Stretches the card to the height of its row (`dwt-card--fill-height`). |
|
|
307
|
+
| `width` | Widens the card to take the columns left over in its row (`dwt-card--fill-width`). |
|
|
308
|
+
| `both` | Both. |
|
|
309
|
+
|
|
310
|
+
`Dashboard` and `WidgetGrid` work out the spans from the rendered grid (so it
|
|
311
|
+
follows your CSS and the container width) and set `grid-column: span N` on
|
|
312
|
+
width-filling cards; on the server, and before the first measurement, the
|
|
313
|
+
grid simply lays out normally. The same helper is exported from the core as
|
|
314
|
+
`fillColumnSpans(items, columns)` for custom layouts, and `WidgetCard` takes
|
|
315
|
+
`fill` and `columnSpan` props.
|
|
316
|
+
|
|
317
|
+
**Loading data after the page renders.** Render the dashboard first and let
|
|
318
|
+
each widget's data arrive on its own. `useWidgets` returns placeholders
|
|
319
|
+
immediately (so first paint and server rendering never wait), starts every
|
|
320
|
+
provider after mount, and replaces each card as its own data arrives:
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
import { Dashboard, useWidgets } from '@richardmcquiston01/dashboard-widgets-toolkit/react';
|
|
324
|
+
|
|
325
|
+
const { widgets, refresh } = useWidgets(definitions, providers, context, {
|
|
326
|
+
timeoutMs: 8000, // a provider that takes longer becomes an error card
|
|
327
|
+
refreshMs: 60_000, // optional polling; skips widgets still loading
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
return <Dashboard widgets={widgets} onRetry={(key) => refresh(key)} />;
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Providers receive an `AbortSignal` as a third argument (`(context, definition,
|
|
334
|
+
{ signal })`); pass it to `fetch` so a timeout, a refresh or leaving the page
|
|
335
|
+
stops the request. Existing two-argument providers keep working.
|
|
336
|
+
|
|
337
|
+
- `loadWhen: 'visible'` also waits until a card is near the viewport. Attach
|
|
338
|
+
the returned `gridRef` to an element around the dashboard.
|
|
339
|
+
- `cache` (your own `{ get, set }` storage: memory, `localStorage`, ...) shows
|
|
340
|
+
the last payload instantly as `stale` while a fresh load runs. Cached
|
|
341
|
+
payloads are validated again, and a failing cache never fails a widget.
|
|
342
|
+
- Keep `definitions`, `providers`, `context` and `cache` referentially stable
|
|
343
|
+
(module constants or `useMemo`); a changed value restarts loading.
|
|
344
|
+
- Not using React? `createWidgetLoader` (core) is the same logic with
|
|
345
|
+
`subscribe`/`getSnapshot`, `load`, `refresh` and `dispose`; `resolveWidget`
|
|
346
|
+
and `resolveWidgets` accept `timeoutMs`, `signal` and `cache` too.
|
|
347
|
+
|
|
243
348
|
**Charts.** `GRAPH` widgets render as inline SVG with `role="img"`, a
|
|
244
|
-
`<title>` and a `<desc>`
|
|
349
|
+
`<title>` and a `<desc>` summarizing the series (latest, high and low), a
|
|
245
350
|
legend when there are two or more series, a hover and keyboard (arrow keys)
|
|
246
|
-
tooltip, and a collapsible "View as table" with every value.
|
|
351
|
+
tooltip, and a collapsible "View as table" with every value. Colors are CSS
|
|
247
352
|
custom properties (`--dwt-series-1` … `--dwt-series-8`) with built-in
|
|
248
|
-
defaults from a palette checked for
|
|
353
|
+
defaults from a palette checked for color-vision deficiency in light and
|
|
249
354
|
dark modes; a graph may have at most eight series.
|
|
250
355
|
|
|
251
356
|
## Maker Toolkit compatibility
|
|
@@ -271,7 +376,7 @@ the definition mirrors its `widget` table:
|
|
|
271
376
|
`fromLegacyDefinition()` maps a served definition.
|
|
272
377
|
- `KPI`, `BAR_LIST` and `ALERT_LIST` are new kinds. Add them to the
|
|
273
378
|
`WidgetViewType` enum before seeding widgets that use them.
|
|
274
|
-
- The desktop app's `dashboard-layout.ts` (order, hidden,
|
|
379
|
+
- The desktop app's `dashboard-layout.ts` (order, hidden, minimized) is
|
|
275
380
|
`layout.ts` here, with the same JSON shape, so saved layouts carry over.
|
|
276
381
|
It now appends new widgets by `sortOrder` and tolerates corrupt values per
|
|
277
382
|
field.
|