lintje 0.1.1 → 0.2.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.
Files changed (177) hide show
  1. package/dist-elements/actions.js +1 -1
  2. package/dist-elements/charts.js +1 -1
  3. package/dist-elements/chunks/{base-rBLTcEIv.js → base-Bg-IFOPG.js} +134 -105
  4. package/dist-elements/chunks/{date-format-B5DPGjAw.js → date-format-mHtZyBys.js} +28 -2
  5. package/dist-elements/chunks/disclosure-BXTX04gM.js +4 -0
  6. package/dist-elements/chunks/{disclosure-CHasOudX.js → disclosure-CMXhX-Vb.js} +7 -7
  7. package/dist-elements/chunks/download-y528pIHP.js +230 -0
  8. package/dist-elements/chunks/{focus-trap-w3vCamJ6.js → focus-trap-9BnE-xWv.js} +1 -1
  9. package/dist-elements/chunks/{input-jQVTln7H.js → input-BtuNFSWk.js} +13 -13
  10. package/dist-elements/chunks/{player-Bq9YGnpt.js → player-DXOZEyEy.js} +24 -24
  11. package/dist-elements/chunks/{sentence-CLNJOeXz.js → sentence-BI3lwEuT.js} +3 -3
  12. package/dist-elements/chunks/{stagger-9hYzxhMG.js → stagger-qGD3wmhg.js} +145 -123
  13. package/dist-elements/core.js +1 -1
  14. package/dist-elements/custom-elements.json +436 -26
  15. package/dist-elements/feedback.js +1 -1
  16. package/dist-elements/guides/dashboard.md +1 -1
  17. package/dist-elements/guides/events.md +3 -2
  18. package/dist-elements/guides/loading.md +3 -3
  19. package/dist-elements/guides/start.md +1 -1
  20. package/dist-elements/inputs.js +1 -0
  21. package/dist-elements/layout.js +1 -1
  22. package/dist-elements/lintje.js +22659 -22216
  23. package/dist-elements/map.js +1 -1
  24. package/dist-elements/overlays.js +1 -1
  25. package/dist-elements/tag/activity-log.js +11 -11
  26. package/dist-elements/tag/ai-label.js +7 -7
  27. package/dist-elements/tag/announcement.js +19 -19
  28. package/dist-elements/tag/app-search.js +21 -21
  29. package/dist-elements/tag/audio-player.js +34 -34
  30. package/dist-elements/tag/badge.js +1 -1
  31. package/dist-elements/tag/breadcrumbs.js +11 -11
  32. package/dist-elements/tag/button.js +1 -1
  33. package/dist-elements/tag/card-list.js +1 -1
  34. package/dist-elements/tag/card.js +25 -25
  35. package/dist-elements/tag/chart.d.ts +1 -0
  36. package/dist-elements/tag/chart.js +1868 -0
  37. package/dist-elements/tag/chat-answer.js +28 -28
  38. package/dist-elements/tag/chat-composer.js +20 -20
  39. package/dist-elements/tag/chat-message.js +9 -9
  40. package/dist-elements/tag/chat-strip.js +16 -16
  41. package/dist-elements/tag/chat-suggestions.js +1 -1
  42. package/dist-elements/tag/chat.js +27 -27
  43. package/dist-elements/tag/checkbox.js +6 -6
  44. package/dist-elements/tag/code.js +8 -8
  45. package/dist-elements/tag/combobox.js +13 -13
  46. package/dist-elements/tag/confirm-dialog.js +6 -6
  47. package/dist-elements/tag/conflict-alert.js +5 -5
  48. package/dist-elements/tag/copy-button.js +7 -7
  49. package/dist-elements/tag/data-table.js +179 -179
  50. package/dist-elements/tag/date-input.js +34 -42
  51. package/dist-elements/tag/date-range.js +33 -33
  52. package/dist-elements/tag/description-list.js +20 -20
  53. package/dist-elements/tag/document-viewer.js +19 -19
  54. package/dist-elements/tag/drawer.js +7 -7
  55. package/dist-elements/tag/empty-state.js +11 -11
  56. package/dist-elements/tag/error-summary.js +8 -8
  57. package/dist-elements/tag/expander.js +7 -7
  58. package/dist-elements/tag/explainer.js +9 -9
  59. package/dist-elements/tag/field.js +4 -4
  60. package/dist-elements/tag/file-upload.js +20 -20
  61. package/dist-elements/tag/filter-bar.js +35 -35
  62. package/dist-elements/tag/filter-sheet.js +6 -6
  63. package/dist-elements/tag/filter-zone.js +21 -21
  64. package/dist-elements/tag/footer.js +1 -1
  65. package/dist-elements/tag/form-actions.js +7 -7
  66. package/dist-elements/tag/form-section.js +3 -3
  67. package/dist-elements/tag/form.js +4 -4
  68. package/dist-elements/tag/gallery.js +6 -6
  69. package/dist-elements/tag/grid-item.js +1 -1
  70. package/dist-elements/tag/grid.js +1 -1
  71. package/dist-elements/tag/hero.js +6 -6
  72. package/dist-elements/tag/highlight.js +6 -6
  73. package/dist-elements/tag/icon-button.js +1 -1
  74. package/dist-elements/tag/icon.js +1 -1
  75. package/dist-elements/tag/job-list.js +6 -6
  76. package/dist-elements/tag/kpi-row.js +7 -5
  77. package/dist-elements/tag/kpi.js +259 -69
  78. package/dist-elements/tag/level-meter.js +5 -5
  79. package/dist-elements/tag/list.js +28 -28
  80. package/dist-elements/tag/logo.js +9 -9
  81. package/dist-elements/tag/map.d.ts +1 -0
  82. package/dist-elements/tag/map.js +21910 -0
  83. package/dist-elements/tag/menu-button.js +48 -47
  84. package/dist-elements/tag/modal.js +9 -9
  85. package/dist-elements/tag/multiselect.js +18 -18
  86. package/dist-elements/tag/note.js +4 -4
  87. package/dist-elements/tag/notifications.js +24 -24
  88. package/dist-elements/tag/number-input.js +8 -8
  89. package/dist-elements/tag/page-header.js +13 -13
  90. package/dist-elements/tag/pagination.js +27 -27
  91. package/dist-elements/tag/popover.js +1 -1
  92. package/dist-elements/tag/progress-bar.js +1 -1
  93. package/dist-elements/tag/prose.js +4 -4
  94. package/dist-elements/tag/qr-code.js +6 -6
  95. package/dist-elements/tag/radio-group.js +7 -7
  96. package/dist-elements/tag/range.js +13 -13
  97. package/dist-elements/tag/recording-status.js +8 -8
  98. package/dist-elements/tag/repeater.js +1 -1
  99. package/dist-elements/tag/segmented.js +7 -7
  100. package/dist-elements/tag/select.js +6 -6
  101. package/dist-elements/tag/session-expiry.js +13 -13
  102. package/dist-elements/tag/shell.js +168 -168
  103. package/dist-elements/tag/shortcuts.js +8 -8
  104. package/dist-elements/tag/skeleton.js +1 -1
  105. package/dist-elements/tag/slot-picker.d.ts +1 -0
  106. package/dist-elements/tag/slot-picker.js +74 -0
  107. package/dist-elements/tag/sortable-list.js +11 -11
  108. package/dist-elements/tag/spinner.js +1 -1
  109. package/dist-elements/tag/split-pane.js +4 -4
  110. package/dist-elements/tag/status-dot.js +1 -1
  111. package/dist-elements/tag/stepper.js +13 -13
  112. package/dist-elements/tag/streaming-text.js +15 -15
  113. package/dist-elements/tag/sub-nav.js +26 -26
  114. package/dist-elements/tag/tabs.js +13 -13
  115. package/dist-elements/tag/tag-input.js +14 -14
  116. package/dist-elements/tag/text-editor.js +7 -7
  117. package/dist-elements/tag/text-input.js +10 -10
  118. package/dist-elements/tag/textarea.js +6 -6
  119. package/dist-elements/tag/tile.js +1 -1
  120. package/dist-elements/tag/time-input.js +136 -42
  121. package/dist-elements/tag/toast.js +10 -10
  122. package/dist-elements/tag/toggle.js +6 -6
  123. package/dist-elements/tag/toggletip.js +11 -11
  124. package/dist-elements/tag/tooltip.js +1 -1
  125. package/dist-elements/tag/transcript.js +31 -31
  126. package/dist-elements/tag/translator.js +7 -7
  127. package/dist-elements/tag/tree-view.js +12 -12
  128. package/dist-elements/tag/user-menu.js +31 -30
  129. package/dist-elements/tag/video-player.js +13 -13
  130. package/dist-elements/tokens.css +2 -0
  131. package/dist-elements/types/bundle/charts.d.ts +1 -1
  132. package/dist-elements/types/bundle/index.d.ts +1 -1
  133. package/dist-elements/types/bundle/inputs.d.ts +1 -0
  134. package/dist-elements/types/bundle/map.d.ts +1 -1
  135. package/dist-elements/types/components/charts/{chart-tile/chart-tile.d.ts → chart/chart.d.ts} +7 -7
  136. package/dist-elements/types/components/charts/kpi/gauge.d.ts +18 -0
  137. package/dist-elements/types/components/charts/kpi/kpi.d.ts +28 -3
  138. package/dist-elements/types/components/chat/chat-answer/chat-answer.d.ts +1 -1
  139. package/dist-elements/types/components/index.d.ts +8 -5
  140. package/dist-elements/types/components/inputs/date-input/date-format.d.ts +4 -0
  141. package/dist-elements/types/components/inputs/slot-picker/slot-picker.d.ts +41 -0
  142. package/dist-elements/types/components/inputs/time-input/time-format.d.ts +4 -0
  143. package/dist-elements/types/components/inputs/time-input/time-input.d.ts +25 -6
  144. package/dist-elements/types/components/map/{map-tile/map-tile.d.ts → map/map.d.ts} +10 -6
  145. package/dist-elements/types/components/shared/charts/histogram-chart/histogram-chart.d.ts +33 -0
  146. package/dist-elements/types/components/shared/charts/index.d.ts +3 -1
  147. package/dist-elements/types/components/shared/charts/map-chart/area.d.ts +16 -0
  148. package/dist-elements/types/components/shared/charts/map-chart/drawings.d.ts +6 -2
  149. package/dist-elements/types/components/shared/charts/map-chart/geo.d.ts +6 -0
  150. package/dist-elements/types/components/shared/charts/map-chart/leaflet.d.ts +40 -2
  151. package/dist-elements/types/components/shared/charts/map-chart/map-chart.d.ts +17 -3
  152. package/dist-elements/types/components/shared/charts/map-chart/map-legend.d.ts +26 -0
  153. package/dist-elements/types/components/shared/charts/map-chart/marks.d.ts +47 -0
  154. package/dist-elements/types/components/shared/charts/map-chart/reveal.d.ts +1 -1
  155. package/dist-elements/types/components/shared/charts/scatter-chart/scatter-chart.d.ts +29 -0
  156. package/dist-elements/types/components/shared/charts/shared/axes.d.ts +21 -4
  157. package/dist-elements/types/components/shared/charts/shared/chart-icons.d.ts +4 -3
  158. package/dist-elements/types/components/shared/charts/shared/controller.d.ts +27 -15
  159. package/dist-elements/types/components/shared/charts/shared/types.d.ts +112 -6
  160. package/dist-elements/types/core/format.d.ts +5 -2
  161. package/dist-elements/types/icons/register.d.ts +1 -1
  162. package/dist-elements/types/primitives/shared/place.d.ts +1 -1
  163. package/dist-elements/types/primitives/tooltip/tooltip.d.ts +2 -0
  164. package/dist-elements/types/types.d.ts +37 -7
  165. package/dist-icons/functioneel-cirkelselectie.svg +1 -0
  166. package/dist-icons/functioneel-lasso.svg +1 -0
  167. package/dist-icons/functioneel-punaise-outline.svg +1 -0
  168. package/dist-icons/functioneel-punaise.svg +1 -0
  169. package/dist-icons/functioneel-rechthoekselectie.svg +1 -0
  170. package/dist-icons/functioneel-selectie.svg +1 -0
  171. package/package.json +1 -1
  172. package/dist-elements/chunks/disclosure-Z7Ny17sS.js +0 -4
  173. package/dist-elements/chunks/download-lFooAfD1.js +0 -226
  174. package/dist-elements/tag/chart-tile.d.ts +0 -1
  175. package/dist-elements/tag/chart-tile.js +0 -1474
  176. package/dist-elements/tag/map-tile.d.ts +0 -1
  177. package/dist-elements/tag/map-tile.js +0 -22292
@@ -28,6 +28,25 @@ export interface BarSeriesData {
28
28
  /** One entry per value: the drilldown of that bar or segment, or null. */
29
29
  links?: (ChartLink | null)[];
30
30
  }
31
+ /** One point of a scatter plot: a named record, clickable with a `href` like a table row. */
32
+ export interface ScatterPoint {
33
+ label: string;
34
+ /** null = no data, never 0 (rule 15): the point is not drawn and stays in the table. */
35
+ x: number | null;
36
+ y: number | null;
37
+ /** The identity a click carries; without it the series' label and its own: `Loket · Utrecht`. */
38
+ id?: string;
39
+ href?: string;
40
+ }
41
+ /**
42
+ * A series of a scatter plot: a colour and the shape that colour has on a map (rule 13).
43
+ * Without a colour the series take the data colours in their order.
44
+ */
45
+ export interface ScatterSeriesData {
46
+ label: string;
47
+ color?: ChartColor;
48
+ points: ScatterPoint[];
49
+ }
31
50
  export type ChartSpec = {
32
51
  kind: 'line';
33
52
  labels: string[];
@@ -124,6 +143,21 @@ export type ChartSpec = {
124
143
  thresholdLabel?: string;
125
144
  pendingHours?: number;
126
145
  small?: boolean;
146
+ } | {
147
+ kind: 'scatter';
148
+ series: ScatterSeriesData[];
149
+ /** The vertical axis: its title above the chart, in the tooltip and as a table column. */
150
+ axisTitle: string;
151
+ unit?: string;
152
+ /** The horizontal axis: its title under its labels, right-aligned. */
153
+ xTitle: string;
154
+ xUnit?: string;
155
+ /** A horizontal norm on the vertical axis, dashed in the emphasis colour. */
156
+ threshold?: number;
157
+ thresholdLabel?: string;
158
+ /** The labels of the points that show their name; all of them, or none when one does not fit. */
159
+ dataLabels?: string[];
160
+ small?: boolean;
127
161
  } | {
128
162
  kind: 'heatmap';
129
163
  columnLabels: string[];
@@ -146,11 +180,40 @@ export type ChartSpec = {
146
180
  values: (number | null)[][];
147
181
  links?: (ChartLink | null)[][];
148
182
  };
183
+ } | {
184
+ kind: 'histogram';
185
+ /**
186
+ * The classes in ascending order, each starting where the one before ends. `to: null` is
187
+ * an open last class ("30+"); `count: null` is no data, never 0 (rule 15).
188
+ */
189
+ bins: {
190
+ from: number;
191
+ to: number | null;
192
+ count: number | null;
193
+ }[];
194
+ /** What the classes count, in the legend and the tooltip. Default "Aantal". */
195
+ label?: string;
196
+ color?: ChartColor;
197
+ /** Above the y-axis, e.g. "aanvragen per twee dagen". */
198
+ axisTitle?: string;
199
+ /** Under the x labels, right-aligned, e.g. "doorlooptijd in dagen". */
200
+ xTitle?: string;
201
+ /** The unit of the x-axis, e.g. "dagen": in the tooltip and beside the lines. */
202
+ unit?: string;
203
+ /** A solid emphasis line at this x value. */
204
+ median?: number;
205
+ /** The text beside the median line; default "mediaan" with its value and unit. */
206
+ medianLabel?: string;
207
+ /** A dashed emphasis line at this x value. */
208
+ threshold?: number;
209
+ /** The text beside the threshold line; default "norm" with its value and unit. */
210
+ thresholdLabel?: string;
211
+ small?: boolean;
149
212
  };
150
213
  export type ChartKind = ChartSpec['kind'];
151
214
  /**
152
215
  * What a map draws. `polygons` are areas that carry their own outline (`MapValue.polygon`);
153
- * `plots` stacks several drawings, from `MapTileData.plots`.
216
+ * `plots` stacks several drawings, from `MapSpec.plots`.
154
217
  */
155
218
  export type MapVariant = 'flows' | 'points' | 'choropleth' | 'polygons' | 'plots' | 'scope-picker';
156
219
  /** A map point's data colour, by name: one of the data colours, each with its own shape. */
@@ -176,6 +239,45 @@ export interface MapValue {
176
239
  /** A URL the host minted, carried into `lintje-mark-select`. */
177
240
  href?: string;
178
241
  }
242
+ /**
243
+ * An area drawn on the map to choose what lies in it: a lasso, a ring of `[lon, lat]` pairs with
244
+ * the first point not repeated, or a circle around a `[lon, lat]` centre.
245
+ */
246
+ export type MapArea = {
247
+ kind: 'lasso';
248
+ ring: [number, number][];
249
+ } | {
250
+ kind: 'circle';
251
+ centre: [number, number];
252
+ radiusKm: number;
253
+ };
254
+ /** A tool that draws an area on the map. */
255
+ export type MapTool = 'lasso' | 'circle' | 'rect';
256
+ /**
257
+ * The parts of a map a host switches on or off. Without a value each keeps its default: every
258
+ * part on, except the drawing tools, which choose for a host that filters on an area. With two
259
+ * or more tools on, one button opens a menu of them.
260
+ */
261
+ export interface MapControls {
262
+ /** The + and − buttons, a double click and a pinch. Default on. */
263
+ zoom?: boolean;
264
+ /** Zooming on the wheel with Ctrl or ⌘ held. Default on. */
265
+ wheel?: boolean;
266
+ /** Panning with the mouse. Default on; on a phone a finger always scrolls the page. */
267
+ drag?: boolean;
268
+ /** The reset: the whole area in view and nothing chosen. Default on. */
269
+ reset?: boolean;
270
+ /** Choosing with a drawn lasso; sends `lintje-area-select`. Default off. */
271
+ lasso?: boolean;
272
+ /** Choosing with a drawn circle; sends `lintje-area-select`. Default off. */
273
+ circle?: boolean;
274
+ /** Choosing with a drawn rectangle, sent as a lasso of four corners. Default off. */
275
+ rect?: boolean;
276
+ /** A scale bar in km bottom right. Default on. */
277
+ scale?: boolean;
278
+ /** The legend above the map: a line per layer with its key and its series. Default on. */
279
+ legend?: boolean;
280
+ }
179
281
  /** The basemap the map draws on, a WMS service the host configures. */
180
282
  export interface WmsBasemap {
181
283
  kind: 'wms';
@@ -213,12 +315,12 @@ export interface MapPlotData {
213
315
  };
214
316
  /**
215
317
  * What each series in this layer means, over the map's own `seriesLabels`. A colour may serve
216
- * several layers; the legend above the map keeps one line per colour, named by the first.
318
+ * several layers; each layer's line in the legend names and switches its own.
217
319
  */
218
320
  seriesLabels?: Partial<Record<MapSeriesKey, string>>;
219
321
  }
220
- /** The map's data, as `MapTileData` in `src/types.ts` carries it, without the tile fields. */
221
- export interface MapTileData {
322
+ /** The map's data, as `MapData` in `src/types.ts` carries it, without the tile fields. */
323
+ export interface MapSpec {
222
324
  variant: MapVariant;
223
325
  geo?: 'world' | 'netherlands';
224
326
  /** The marks of a one-variant map; empty with `variant: 'plots'`. */
@@ -232,7 +334,7 @@ export interface MapTileData {
232
334
  };
233
335
  unit?: string;
234
336
  description: string;
235
- /** Map height in px; default 400, 220 below 768 px. */
337
+ /** Map height in px; default 400, 280 below 768 px. */
236
338
  height?: number;
237
339
  selectedId?: string | null;
238
340
  layers?: {
@@ -247,6 +349,10 @@ export interface MapTileData {
247
349
  selectLabel?: string;
248
350
  /** The URL that undoes the selection, for a page that keeps it in the URL. */
249
351
  clearHref?: string;
250
- /** With a basemap the map draws with Leaflet; without one it stays the SVG map. */
352
+ /** Tiles under the map: Leaflet draws the basemap, the map draws its data over it. */
251
353
  basemap?: WmsBasemap;
354
+ /** Which parts of the map show and answer; each left out keeps its default. */
355
+ controls?: MapControls;
356
+ /** The area the host keeps, from its URL: adopted when it changes, as `selectedId` is. */
357
+ selectedArea?: MapArea | null;
252
358
  }
@@ -8,6 +8,9 @@ export declare function formatDataLabel(n: number, available: number): string;
8
8
  export declare function dataLabelFits(text: string, available: number): boolean;
9
9
  /** `text` shortened with an ellipsis until it fits `maxWidth` px in the axis label font. */
10
10
  export declare function truncateToWidth(text: string, maxWidth: number, fontFamily?: string): string;
11
- /** Width in px of `text` in the 12 px axis label font; ~6.5 px per character without a canvas. */
12
- export declare function textWidth(text: string, fontFamily?: string): number;
11
+ /**
12
+ * Width in px of `text` in the 12 px chart font, at `weight` (400 for an axis label, 700 for a
13
+ * data label); ~6.5 px per character without a canvas.
14
+ */
15
+ export declare function textWidth(text: string, fontFamily?: string, weight?: number): number;
13
16
  export declare function formatPercent(n: number, decimals?: number): string;
@@ -5,7 +5,7 @@
5
5
  * Every other icon is fetched by name when a name needs it
6
6
  * (`src/icons/loader.ts`); the name is always the file name.
7
7
  *
8
- * 59 icons, of 1192 in `dist-icons/`.
8
+ * 62 icons, of 1198 in `dist-icons/`.
9
9
  */
10
10
  export interface IconGlyph {
11
11
  /** The file's own viewBox: 64 or 48 in RVO's set, 24 for an own icon, 346x75 for an emblem. */
@@ -3,7 +3,7 @@
3
3
  * gap, flipped when the room is too small and the other side has more, never past the viewport.
4
4
  * Shared by the popover and the tooltip.
5
5
  */
6
- export type Placement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'top-center';
6
+ export type Placement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'top-center' | 'left-center' | 'left-start';
7
7
  /** `bottom` is set instead of `top` when the box stands above the anchor. */
8
8
  export interface Place {
9
9
  top: number | null;
@@ -18,6 +18,8 @@ export declare class LintjeTooltip extends LintjeElement {
18
18
  text: string;
19
19
  /** The text is already the element's accessible name. */
20
20
  noDescribe: boolean;
21
+ /** Above the element, or `left` of it, level with it: for a column of buttons along an edge. */
22
+ placement: 'top' | 'left';
21
23
  open: boolean;
22
24
  protected spot: Place | null;
23
25
  private timer;
@@ -5,10 +5,10 @@
5
5
  * names come from their one list, `tokens/colors.ts`.
6
6
  */
7
7
  import type { DataColor } from './tokens/colors.js';
8
- import type { ChartSpec, MapTileData } from './components/shared/charts/shared/types.js';
8
+ import type { ChartSpec, MapSpec } from './components/shared/charts/shared/types.js';
9
9
  import type { MenuEntry } from './components/actions/menu-button/menu-button.js';
10
10
  import type { NotificationItem } from './components/frame/notifications/notifications.js';
11
- export type { BarSeriesData, ChartColor, ChartKind, ChartSpec, LineSeriesData, MapTileData, MapValue, MapPlotData, MapPlotVariant, MapVariant, WmsBasemap, } from './components/shared/charts/shared/types.js';
11
+ export type { BarSeriesData, ChartColor, ChartKind, ChartSpec, LineSeriesData, MapSpec, MapValue, MapPlotData, MapPlotVariant, MapVariant, ScatterPoint, ScatterSeriesData, WmsBasemap, MapArea, MapControls, } from './components/shared/charts/shared/types.js';
12
12
  export type { DataColor } from './tokens/colors.js';
13
13
  /** Settings every view receives, taken from the URL by the host. */
14
14
  export interface FrameSettings {
@@ -43,6 +43,30 @@ export interface KpiTrend {
43
43
  /** For variables where rising is bad (wait time, refusals). */
44
44
  inverted?: boolean;
45
45
  }
46
+ /**
47
+ * The figure's own recent values as a small line with the area under it: no axes, scaled from
48
+ * the lowest to the highest value, in the variable's colour. A `null` breaks the line (rule 15).
49
+ */
50
+ export interface KpiSparkline {
51
+ /** The values in order, the current one last; at least two numbers draw a line. */
52
+ values: (number | null)[];
53
+ /** A readable summary with the unit, the line's `<desc>`: the accessible alternative. */
54
+ description: string;
55
+ }
56
+ /** Where the figure stands on a scale, drawn under or around the value. */
57
+ export interface KpiGauge {
58
+ /** `arc`: a half circle with the value in its mouth. `linear`: a bar under the value. */
59
+ shape?: 'arc' | 'linear';
60
+ /** Where the scale starts; default 0. */
61
+ min?: number;
62
+ max: number;
63
+ /** The figure on the scale; default the number in the KPI's `value`. `null` draws no fill. */
64
+ value?: number | null;
65
+ /** A dashed mark on the scale, in the emphasis colour. */
66
+ target?: number;
67
+ /** The word before the target's number: "doel" (default) or "norm". */
68
+ targetLabel?: string;
69
+ }
46
70
  export interface KpiData {
47
71
  label: string;
48
72
  /** An icon file name (`dist-icons/`, without `.svg`). Decorative. */
@@ -54,8 +78,11 @@ export interface KpiData {
54
78
  emphasis?: 'equal' | 'primary';
55
79
  dividers?: boolean;
56
80
  trend?: KpiTrend;
81
+ sparkline?: KpiSparkline;
57
82
  note?: string;
58
83
  detail?: string;
84
+ /** A single figure on its scale; ignored with `items`. */
85
+ gauge?: KpiGauge;
59
86
  variable?: KpiVariable;
60
87
  state?: KpiState;
61
88
  }
@@ -92,7 +119,7 @@ export interface TileData {
92
119
  * Events: `lintje-mark-select` `{id, label, href}` when a mark with a `href` is clicked,
93
120
  * `{id: null, href: clearHref}` when the selection is undone.
94
121
  */
95
- export interface ChartTileData extends FrameSettings, TileData, ContentState {
122
+ export interface ChartData extends FrameSettings, TileData, ContentState {
96
123
  chart: ChartSpec;
97
124
  /** The chart's `<desc>`: a readable summary, the accessible alternative. Required. */
98
125
  description: string;
@@ -105,9 +132,11 @@ export interface ChartTileData extends FrameSettings, TileData, ContentState {
105
132
  }
106
133
  /**
107
134
  * Events: `lintje-mark-select` `{id, label, href?}` on a click on an area or point,
108
- * `{id: null, href: clearHref}` when undone; `lintje-layer-change` with the chosen layer.
135
+ * `{id: null, href: clearHref}` when undone; `lintje-layer-change` with the chosen layer;
136
+ * with `controls.lasso` or `controls.circle`, `lintje-area-select` `{area, ids}` for a drawn area and
137
+ * `{area: null, ids: []}` when it is undone.
109
138
  */
110
- export interface MapTileViewData extends FrameSettings, TileData, ContentState, MapTileData {
139
+ export interface MapData extends FrameSettings, TileData, ContentState, MapSpec {
111
140
  }
112
141
  export type CellValue = string | number | null;
113
142
  export interface TableColumnData {
@@ -518,8 +547,8 @@ export type ChatBlock = {
518
547
  kind: 'kpi-row';
519
548
  data: KpiRowData;
520
549
  } | {
521
- kind: 'chart-tile';
522
- data: ChartTileData;
550
+ kind: 'chart';
551
+ data: ChartData;
523
552
  } | {
524
553
  kind: 'data-table';
525
554
  data: DataTableData;
@@ -601,6 +630,7 @@ export type { FormValues, FormErrors, StoredDraft } from './components/forms/for
601
630
  export type { ErrorSummaryItem } from './components/forms/error-summary/error-summary.js';
602
631
  export type { UploadFile } from './components/inputs/file-upload/file-upload.js';
603
632
  export type { DateRange } from './components/inputs/date-range/date-range.js';
633
+ export type { SlotDay, TimeSlot } from './components/inputs/slot-picker/slot-picker.js';
604
634
  export type { TabItem } from './components/layout/tabs/tabs.js';
605
635
  export type { Step, StepState, StepperOrientation } from './components/forms/stepper/stepper.js';
606
636
  export type { MenuEntry, MenuHeading, MenuItem } from './components/actions/menu-button/menu-button.js';
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2.5a9.5 9.5 0 1 0 0 19 9.5 9.5 0 0 0 0-19Zm0 2a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15Z" fill-rule="evenodd"/><path d="M12 9.75a2.25 2.25 0 1 0 2.1 3.25h3.4v-2h-3.4A2.25 2.25 0 0 0 12 9.75Z"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13 2.5c-5.2 0-9.5 2.9-9.5 6.5 0 1.8 1.1 3.5 2.9 4.7l-.3.8a2.2 2.2 0 0 0 .3 3.3c-.3 1.6.4 3.3 2.2 4.5l1.1-1.6c-1.2-.8-1.6-1.8-1.5-2.7a2.2 2.2 0 0 0 1.4-2.6l.3-.7c1 .3 2 .4 3.1.4 5.2 0 9.5-2.9 9.5-6.5S18.2 2.5 13 2.5Zm0 2c4.3 0 7.5 2.3 7.5 4.5S17.3 13.5 13 13.5c-1 0-2-.1-2.8-.4a2.2 2.2 0 0 0-2.7-.6C6.3 11.7 5.5 10.4 5.5 9c0-2.2 3.2-4.5 7.5-4.5Z" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8 2h8a1 1 0 0 1 0 2h-.8v5.6l3.2 3.2c.4.4.6.9.6 1.4v.8c0 .5-.4 1-1 1H13v5.2l-1 1.8-1-1.8V16H6c-.6 0-1-.5-1-1v-.8c0-.5.2-1 .6-1.4l3.2-3.2V4H8a1 1 0 0 1 0-2Zm2.8 2v6.4l-3.6 3.6h9.6l-3.6-3.6V4h-2.4Z" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8 2h8a1 1 0 0 1 0 2h-.8v5.6l3.2 3.2c.4.4.6.9.6 1.4v.8c0 .5-.4 1-1 1H13v5.2l-1 1.8-1-1.8V16H6c-.6 0-1-.5-1-1v-.8c0-.5.2-1 .6-1.4l3.2-3.2V4H8a1 1 0 0 1 0-2Z"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 4h18v12h-2V6H5v12h9v2H3V4Z"/><path d="M16 15.5a1 1 0 0 1 1.4-.9l4 1.9a.8.8 0 0 1-.1 1.5l-1.5.4-.4 1.5a.8.8 0 0 1-1.5.1l-1.9-4a1 1 0 0 1 0-.5Z"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 3h4v2H5v2H3V3Zm6 0h4v2H9V3Zm6 0h4v4h-2V5h-2V3ZM3 9h2v4H3V9Zm14 0h2v3h-2V9ZM3 15h2v2h2v2H3v-4Zm6 4h3v2H9v-2Z"/><path d="M13 12.5a1 1 0 0 1 1.4-.9l6.8 3.2a.8.8 0 0 1-.1 1.5l-2.7.7-.7 2.7a.8.8 0 0 1-1.5.1L13 13a1 1 0 0 1 0-.5Z"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lintje",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Lintje: the Rijkshuisstijl design system as Lit web components",
6
6
  "license": "EUPL-1.2",
@@ -1,4 +0,0 @@
1
- //#region src/components/shared/disclosure.css?inline
2
- var e = "/*\n * The disclosure shared by `lintje-expander` and `lintje-explainer`: the surface stays with each\n * element. The body unfolds with `grid-template-rows: 0fr -> 1fr`, as the filter zone does;\n * `--dur-collapse` is 0 ms under reduced motion (`tokens/base.css`).\n */\n:host(lintje-expander) {\n display: block;\n min-width: 0;\n}\n:host([hidden]) { display: none; }\n\n/* --- */\n\n.lintje-disclosure__heading { margin: 0; font: inherit; }\n.lintje-disclosure__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n min-height: var(--h-target);\n gap: var(--space-3);\n text-align: left;\n}\n/* Spans, because a button holds phrasing content only. */\n.lintje-disclosure__title { display: block; font: var(--text-tile-title); color: var(--color-text-primary); }\n/* A grid only with an icon or subtitle: the subtitle then sits under the title text. */\n.lintje-disclosure__label {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n min-width: 0;\n}\n.lintje-disclosure__label--plain { display: block; }\n.lintje-disclosure__icon { grid-row: 1; }\n.lintje-disclosure__label .lintje-disclosure__title,\n.lintje-disclosure__label .lintje-disclosure__sub { grid-column: 2; }\n.lintje-disclosure__label--plain .lintje-disclosure__title,\n.lintje-disclosure__label--plain .lintje-disclosure__sub { grid-column: auto; }\n.lintje-disclosure__sub { display: block; font: var(--text-tile-sub); color: var(--color-text-muted); margin-top: 2px; }\n\n/* --- Opening and closing -------------------------------------------------- */\n.lintje-disclosure__body {\n display: grid;\n grid-template-rows: 0fr;\n /* Named column: an implicit `auto` track takes the max-content width, so a code block with\n `wrap: false` would run out of the box instead of scrolling. */\n grid-template-columns: minmax(0, 1fr);\n transition: grid-template-rows var(--dur-collapse) var(--ease-in-motion);\n}\n.lintje-disclosure.is-open .lintje-disclosure__body { grid-template-rows: 1fr; }\n\n.lintje-disclosure__body-inner {\n min-height: 0;\n overflow: hidden;\n opacity: 0;\n /* Closed: out of the tab order and the accessibility tree; hiding waits for the collapse. */\n visibility: hidden;\n transition:\n opacity var(--dur-collapse) var(--ease-in-motion),\n visibility 0s linear var(--dur-collapse);\n}\n.lintje-disclosure.is-open .lintje-disclosure__body-inner {\n opacity: 1;\n visibility: visible;\n transition: opacity var(--dur-collapse) var(--ease-in-motion), visibility 0s;\n}\n/* Standing open, nothing clips: slotted content may hang a popover out of the box. */\n.lintje-disclosure.is-open.is-settled .lintje-disclosure__body-inner { overflow: visible; }\n\n/* Inside the clipped box: on the body it would show under a closed disclosure. */\n.lintje-disclosure__content { margin-top: var(--space-3); }\n\n.lintje-disclosure__chevron {\n flex: none;\n transform-origin: 50% 50%;\n transition: transform var(--dur-collapse) var(--ease-in-motion);\n}\n.lintje-disclosure.is-open .lintje-disclosure__chevron { transform: rotate(180deg); }\n/* Leading: the chevron first, the title after it, and the content in line with the title. */\n.lintje-disclosure--leading .lintje-disclosure__header { justify-content: flex-start; align-items: flex-start; padding-top: var(--space-3); }\n/* The chevron stands in line with the title's first line, not between title and subtitle. */\n.lintje-disclosure--leading .lintje-disclosure__chevron { margin-top: calc((1lh - 16px) / 2); }\n.lintje-disclosure--leading .lintje-disclosure__label { flex: 1 1 auto; }\n.lintje-disclosure--leading .lintje-disclosure__content { margin-left: calc(16px + var(--space-3)); }\n\n/* Columns: the title in its own column, the content beside it in the text's column, the actions\n at the end; the host's width decides, so a narrow one stacks again. */\n:host([columns]) { container-type: inline-size; }\n.lintje-expander--columns {\n display: grid;\n grid-template-columns: var(--lintje-expander-label, calc(4 * var(--space-10))) minmax(0, 1fr) auto;\n grid-template-areas: 'head body actions';\n column-gap: var(--space-5);\n align-items: start;\n}\n.lintje-expander--columns .lintje-expander__top { display: contents; }\n.lintje-expander--columns .lintje-disclosure__heading { grid-area: head; }\n.lintje-expander--columns .lintje-expander__actions { grid-area: actions; }\n.lintje-expander--columns .lintje-disclosure__body { grid-area: body; }\n.lintje-expander--columns .lintje-disclosure__content { margin: 0; padding-top: var(--space-3); }\n@container (max-width: 40rem) {\n .lintje-expander--columns {\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-areas: 'head actions' 'body body';\n }\n .lintje-expander--columns .lintje-disclosure__content { margin-left: calc(16px + var(--space-3)); padding-top: 0; }\n}\n\n.lintje-expander {\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border-default);\n padding: var(--tile-pad-y) var(--tile-pad-x);\n}\n/* `flat`: an expander inside a tile is not a second card. */\n.lintje-expander--flat { background: none; border: none; padding: 0; }\n.lintje-expander__content { font: var(--text-body); color: var(--color-text-secondary); }\n/* The actions stand beside the title's button, never inside it. */\n.lintje-expander__top { display: flex; align-items: flex-start; gap: var(--space-2); }\n.lintje-expander__top .lintje-disclosure__heading { flex: 1 1 auto; min-width: 0; }\n.lintje-expander__actions { display: flex; flex: none; align-items: center; gap: var(--space-1); }\n";
3
- //#endregion
4
- export { e as t };
@@ -1,226 +0,0 @@
1
- import { $ as e, Gt as t, Jt as n, Kt as r, O as i, et as a, ut as o } from "./base-rBLTcEIv.js";
2
- import "../tag/modal.js";
3
- //#region src/components/shared/content-tile.ts
4
- var s = class extends i {
5
- constructor(...e) {
6
- super(...e), this.expanded = !1;
7
- }
8
- static {
9
- this.properties = { expanded: { state: !0 } };
10
- }
11
- expand(e) {
12
- this.expanded !== e && (this.expanded = e, this.expandChanged(e));
13
- }
14
- expandChanged(e) {}
15
- renderExpandModal(e, n) {
16
- let { heading: i, subtitle: a, footnote: o, csv: s, png: c } = n;
17
- return r`<lintje-modal
18
- .open=${this.expanded}
19
- heading=${i ?? "Vergroot"}
20
- subtitle=${a ?? t}
21
- .csv=${s !== void 0}
22
- .png=${c !== void 0}
23
- @lintje-close=${(e) => {
24
- e.stopPropagation(), this.expand(!1);
25
- }}
26
- @lintje-download-csv=${(e) => {
27
- e.stopPropagation(), s?.();
28
- }}
29
- @lintje-download-png=${(e) => {
30
- e.stopPropagation(), c?.();
31
- }}
32
- >
33
- ${e}${o ? r`<span slot="footer">${o}</span>` : t}
34
- </lintje-modal>`;
35
- }
36
- };
37
- //#endregion
38
- //#region src/components/shared/charts/shared/chart-icons.ts
39
- function c(e, n, r = 16) {
40
- let i = a(e, { size: r });
41
- return i === t ? n : i;
42
- }
43
- var l = [
44
- {
45
- action: "in",
46
- name: "functioneel-plus",
47
- text: "+",
48
- label: "Inzoomen"
49
- },
50
- {
51
- action: "out",
52
- name: "functioneel-minus",
53
- text: "−",
54
- label: "Uitzoomen"
55
- },
56
- {
57
- action: "home",
58
- name: "functioneel-home",
59
- text: "Terug",
60
- label: "Terug naar het hele gebied"
61
- }
62
- ];
63
- //#endregion
64
- //#region src/components/shared/charts/shared/chart-states.ts
65
- function u(e = "100%", t = 12, n = "") {
66
- let i = (e) => typeof e == "number" ? `${e}px` : e;
67
- return r`<span class="lintje-skeleton ${n}"
68
- ${o({
69
- width: i(e),
70
- height: i(t)
71
- })} aria-hidden="true"></span>`;
72
- }
73
- function d({ kind: e = "line", height: n } = {}) {
74
- return r`
75
- <div class="lintje-chart-skeleton lintje-chart-skeleton--${e}"
76
- ${o({ height: n ?? (e === "table" ? void 0 : "var(--chart-h-main)") })}
77
- role="status">
78
- <!-- In words, not only in a label: a status region is spoken from its content. -->
79
- <span class="visually-hidden">Gegevens laden…</span>
80
- ${e === "line" || e === "bar" ? r`
81
- <div class="lintje-chart-skeleton__y-labels">
82
- ${[
83
- 0,
84
- 1,
85
- 2,
86
- 3
87
- ].map(() => u(24, 10))}
88
- </div>
89
- <div class="lintje-chart-skeleton__x-labels">
90
- ${[
91
- 0,
92
- 1,
93
- 2
94
- ].map(() => u(32, 10))}
95
- </div>
96
- <div class="lintje-chart-skeleton__plot">
97
- ${u("100%", "100%", "lintje-chart-skeleton__fill")}
98
- </div>
99
- ` : t}
100
- ${e === "pie" || e === "donut" ? r`
101
- <!-- Sized by the skeleton's own box, so it always fits beside its lines. -->
102
- ${u("min(100cqh, 60cqw, 200px)", "auto", "lintje-chart-skeleton__disc")}
103
- <div class="lintje-chart-skeleton__lines">
104
- ${[
105
- "80%",
106
- "64%",
107
- "48%"
108
- ].map((e) => u(e, 13))}
109
- </div>
110
- ` : t}
111
- ${e === "heatmap" ? Array.from({ length: 35 }, () => u("100%", "100%")) : t}
112
- ${e === "map" ? r`
113
- ${u("100%", "100%", "lintje-chart-skeleton__fill")}
114
- <div class="lintje-chart-skeleton__zoom" aria-hidden="true">
115
- ${l.map((e) => r`
116
- <span class="lintje-chart-skeleton__zoom-button">${c(e.name, e.text)}</span>
117
- `)}
118
- </div>
119
- ` : t}
120
- ${e === "table" ? Array.from({ length: 5 }, () => r`
121
- <div class="lintje-chart-skeleton__row">
122
- ${u("32%")}
123
- ${u("12%", 12, "lintje-chart-skeleton__measure")}
124
- ${u("12%")}
125
- </div>
126
- `) : t}
127
- </div>
128
- `;
129
- }
130
- function f(e, t = "var(--chart-h-main)") {
131
- return r`
132
- <div class="lintje-chart-state lintje-chart-state--empty" ${o({ height: t })}>
133
- <p>${e}</p>
134
- </div>
135
- `;
136
- }
137
- function p(e) {
138
- return r`<lintje-announcement
139
- compact
140
- .data=${{
141
- kind: "warning",
142
- text: String(e ?? ""),
143
- live: !0
144
- }}
145
- ></lintje-announcement>`;
146
- }
147
- function m({ message: e, lastKnown: n, height: i = "var(--chart-h-main)", announcement: a = p }) {
148
- return r`
149
- <div class="lintje-chart-state lintje-chart-state--error" ${o({ "min-height": i })}>
150
- ${a(e)}
151
- ${n ? r`<div class="lintje-chart-state__last-known">${n}</div>` : t}
152
- </div>
153
- `;
154
- }
155
- //#endregion
156
- //#region src/components/shared/charts/shared/chart.css?inline
157
- var h = ".lintje-chart { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0; }\n/* Charts that are as high as their rows (horizontal bars, target progress) center in a taller\n tile instead of leaving the space below them empty. */\n.lintje-chart--rows { margin-block: auto; }\n.lintje-chart__axis-title { font: var(--text-axis); color: var(--color-text-muted); }\n.lintje-chart__svg {\n width: 100%;\n display: block;\n overflow: visible;\n}\n\n.lintje-chart__axis-label {\n font-family: var(--font-ui);\n font-size: 0.75rem;\n font-weight: 400;\n fill: var(--color-chart-axis);\n}\n/* Data labels are bold so they read as values rather than axis labels. */\n.lintje-chart__data-label {\n font-family: var(--font-ui);\n font-size: 0.75rem;\n font-weight: 700;\n fill: var(--color-text-primary);\n}\n/* On a mark the label takes the text of the fill it stands on: white on a dark rung, ink on a\n light one. The fills are the same in both modes, so the label is too. */\n.lintje-chart__data-label--inside { fill: var(--color-text-on-fill); }\n.lintje-chart__data-label--inside-light { fill: var(--color-text-on-light-fill); }\n/* On a threshold line (horizontal bars): a halo in the surface color. Invisible on the tile, it cuts the\n dotted line where a value just under the norm puts its label across it. */\n.lintje-chart__data-label--halo {\n stroke: var(--color-bg-surface);\n stroke-width: 4px;\n stroke-linejoin: round;\n paint-order: stroke fill;\n}\n.lintje-chart__as-of-label {\n font-family: var(--font-ui);\n font-size: 0.75rem;\n font-weight: 700;\n fill: var(--color-text-primary);\n}\n.lintje-chart__as-of-note {\n font-family: var(--font-ui);\n font-size: 0.75rem;\n fill: var(--color-text-muted);\n}\n\n.lintje-chart__line { stroke-width: 2.5; fill: none; stroke-linejoin: round; }\n/* 1 px either side of the line, under it (`lineCasing`). */\n.lintje-chart__line--casing { stroke-width: 4.5; }\n\n/* Bars. transform-box: fill-box puts the origin in the bar's own box instead of the svg's:\n a bar widens around its own middle. A horizontal bar is anchored at the category axis. */\n.lintje-chart__bar {\n transform-box: fill-box;\n transform-origin: 50% 100%;\n transition: transform var(--dur-hover) var(--ease-in-motion), filter var(--dur-hover) var(--ease-in-motion);\n}\n.lintje-chart__bar--horizontal { transform-origin: 0 50%; }\n\n/* The bar under the pointer widens a little and lifts with a light\n shadow, so it is clear what the tooltip describes — the same lift as a pie segment. Only the\n width grows: the length carries the value. A stacked column lifts as a whole. */\n.lintje-chart__bar-group:hover .lintje-chart__bar,\n.lintje-chart__bar-group.is-hovered .lintje-chart__bar {\n transform: scaleX(1.06);\n filter: drop-shadow(var(--shadow-chart-hover));\n}\n.lintje-chart__bar-row:hover .lintje-chart__bar--horizontal,\n.lintje-chart__bar-row.is-hovered .lintje-chart__bar--horizontal {\n transform: scaleY(1.12);\n filter: drop-shadow(var(--shadow-chart-hover));\n}\n\n/* A mark that drills. The same three states wherever a mark can carry a\n href — bars, stacked segments, pie slices — and the same ones the map draws: the chosen\n mark takes the text colour as a 2 px outline (the outline is the carrier, not the colour,\n rule 13) and every other mark steps back so it reads against them; .45 is the legend's own\n dimming. The focus ring is the orange 3 px of every other control, around the shape with\n a 1 px gap in the surface (`renderFocusRing`, axes.ts), so an orange mark keeps it too: the\n box an outline draws around a slice or a stacked segment is not the shape the reader is on. */\n.lintje-chart__mark.is-clickable { cursor: pointer; }\n.lintje-chart__mark.is-selected { stroke: var(--color-text-primary); stroke-width: 2; }\n.lintje-chart__mark.is-muted { fill-opacity: .45; }\n/* A focused SVG element with a tabindex gets the browser's own box even where `:focus-visible`\n does not match, after a click: the ring below is the only one. */\n.lintje-chart__mark:focus { outline: none; }\n/* Weighs as much as the hover's lift and stands after it, so the ring is what a focused bar\n under the pointer shows. Only a clickable mark takes the focus. */\n.lintje-chart__mark.is-clickable:focus-visible {\n outline: none;\n filter: var(--lintje-focus-ring);\n}\n.lintje-chart__focus-ring { flood-color: var(--color-focus); }\n.lintje-chart__focus-gap { flood-color: var(--color-bg-surface); }\n/* Stacked segments and slices of neighbouring tints part with a 1 px line in the surface:\n two rungs of the ladder differ by 1.2–1.5:1. */\n.lintje-chart__segment { stroke: var(--color-bg-surface); stroke-width: 1px; }\n\n/* Draw-in takes 900 ms for data marks only. Axes, grid and titles appear immediately. */\n@media (prefers-reduced-motion: no-preference) {\n /* A line and the area below it are uncovered together from left to right. The clip opens over the box\n of the series; the negative insets leave room for the stroke outside that box. */\n .lintje-chart__reveal { animation: lintje-reveal var(--dur-draw) var(--ease-in-motion) backwards; }\n /* Bars grow from the axis one after another: left to right, or top to bottom when horizontal\n --lintje-stagger (0 to 1, set per bar) spreads the starts over the first\n 40 % of the draw and each bar grows in the other 60 %, so all are done at --dur-draw. A\n column grows as a whole, so stacked segments stay together. Fill mode `backwards`, not\n `both`: a transform held after the end would override the hover transform. */\n .lintje-chart__bar-group,\n .lintje-chart__bar--horizontal {\n animation-duration: calc(var(--dur-draw) * 0.6);\n animation-timing-function: var(--ease-in-motion);\n animation-delay: calc(var(--dur-draw) * 0.4 * var(--lintje-stagger, 0));\n animation-fill-mode: backwards;\n }\n .lintje-chart__bar-group {\n transform-box: fill-box;\n transform-origin: 50% 100%;\n animation-name: lintje-grow;\n }\n .lintje-chart__bar--horizontal { animation-name: lintje-grow-x; }\n /* Data labels fade in once the marks are drawn, eased at both ends. */\n .lintje-chart__data-label { animation: lintje-fade-in var(--dur-data-label) ease-in-out var(--dur-draw) both; }\n\n /* Draw in only once the chart comes into view. By default the marks are\n paused on their first frame (series covered, bar flat, label gone); as soon\n as usePlotArea sets data-in-view on the outermost chart element, they run.\n These rules come after the `animation` shorthands above: those set\n animation-play-state back to running and would otherwise win at equal\n specificity. They sit inside this media block because with reduced motion\n there is no animation — and a paused fill-mode would keep the marks\n invisible there. */\n .lintje-chart__reveal,\n .lintje-chart__bar-group,\n .lintje-chart__bar--horizontal,\n .lintje-chart__data-label { animation-play-state: paused; }\n [data-in-view] .lintje-chart__reveal,\n [data-in-view] .lintje-chart__bar-group,\n [data-in-view] .lintje-chart__bar--horizontal,\n [data-in-view] .lintje-chart__data-label { animation-play-state: running; }\n}\n@keyframes lintje-reveal {\n from { clip-path: inset(-8px calc(100% + 8px) -8px -8px); }\n to { clip-path: inset(-8px); }\n}\n@keyframes lintje-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }\n@keyframes lintje-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }\n\n/* --- Legend -------------------------------------------------------------- */\n.lintje-legend {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2) var(--space-4);\n font: var(--text-small);\n color: var(--color-text-primary);\n}\n/* A legend above the chart keeps 12 px to the axis title below it. */\n.lintje-chart-wrap > .lintje-legend { margin-bottom: var(--space-3); }\n.lintje-legend--right { flex-direction: column; flex-wrap: nowrap; }\n.lintje-legend__item { display: flex; align-items: center; gap: 6px; }\n.lintje-legend__button { display: flex; align-items: center; gap: 6px; font: inherit; color: inherit; }\n/* A series switched off: the marker steps back and the name is struck through, at full\n contrast — the strike and `aria-pressed` carry the state, not a faded word. */\n.lintje-legend__item.is-hidden .lintje-legend__marker { opacity: 0.45; }\n.lintje-legend__item.is-hidden .lintje-legend__label { text-decoration: line-through; }\n\n.lintje-legend__marker { flex: none; display: block; }\n.lintje-legend__marker--symbol { width: 14px; height: 14px; }\n.lintje-legend__marker--square { width: 12px; height: 12px; background: currentColor; }\n.lintje-legend__marker--line { width: 14px; height: 3px; background: currentColor; }\n.lintje-legend__marker--dashed {\n width: 14px; height: 0;\n border-top: 2px dashed currentColor;\n}\n\n/* --- Tooltip ------------------------------------------------------------- */\n.lintje-chart-tooltip {\n position: absolute;\n z-index: 55;\n pointer-events: none;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border-popover);\n box-shadow: var(--shadow-popover);\n padding: var(--space-2) 10px;\n font: var(--text-small);\n min-width: 160px;\n /* Its own width, whatever its position: shrink-to-fit narrowed it near the right edge. */\n width: max-content;\n max-width: 320px;\n}\n.lintje-chart-tooltip__title { font-weight: 700; margin-bottom: 4px; }\n.lintje-chart-tooltip__row { display: flex; align-items: center; gap: 6px; justify-content: space-between; }\n.lintje-chart-tooltip__label { display: flex; align-items: center; gap: 6px; }\n.lintje-chart-tooltip__marker { width: 10px; height: 10px; flex: none; }\n.lintje-chart-tooltip__value { font-weight: 700; margin-left: var(--space-3); }\n\n.lintje-chart-wrap { position: relative; min-width: 0; }\n\n/* Chart tooltip anchor: coordinates and positioning both share this element. */\n[data-tooltip-anchor] { position: relative; }\n\n/* Hover point on a line: 4 px in the series color — the size of the as-of point —\n with a ring in the surface color, so it stays legible on the line and on the\n filled area below it. No animation: hover does not redraw. */\n.lintje-chart__hover-point { stroke: var(--color-bg-surface); stroke-width: 2; pointer-events: none; }\n\n\n/* --- States -------------------------------------------------------------- */\n.lintje-chart-state {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n justify-content: center;\n align-items: center;\n min-width: 0;\n}\n.lintje-chart-state--empty { text-align: center; font: var(--text-small); color: var(--color-text-muted); gap: var(--space-3); }\n/* An announcement measures as a container, so it has no width of its own to centre by. */\n.lintje-chart-state--error { justify-content: flex-start; align-items: stretch; gap: var(--space-4); }\n.lintje-chart-state__last-known { font: var(--text-small); color: var(--color-text-muted); text-align: center; }\n\n/* Loading uses a skeleton per chart type, exactly as tall as the chart it stands in for. */\n/* The stand-in grows into a tile that is taller than it: a tile that holds its height\n while it fetches again or stretches to its row. `height` stays\n the basis, so where there is no room to take nothing changes; in a held box that is\n shorter than the stand-in it shrinks to fit. */\n.lintje-chart-skeleton { position: relative; min-width: 0; overflow: hidden; flex: 1 1 auto; min-height: 0; }\n/* Line, area and bars: \"assen echt, datavlak één glanzend blok\". Real axis lines around one\n shimmering block, in the charts' plot area (left 52, right 8, top 16, bottom 28). The axis\n labels load with the data: four bars in the gutter, from the top line to the zero line where\n the labels sit, and three below the axis, so the gutter doesn't read as empty. */\n.lintje-chart-skeleton__plot {\n position: absolute;\n top: 16px; right: 8px; bottom: 28px; left: 52px;\n border-left: 1px solid var(--color-chart-grid);\n border-bottom: 1px solid var(--color-chart-zero);\n}\n.lintje-chart-skeleton__fill { position: absolute; inset: 0; }\n.lintje-chart-skeleton__y-labels {\n position: absolute;\n top: 11px; bottom: 23px; left: 0; width: 44px;\n display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end;\n}\n.lintje-chart-skeleton__x-labels {\n position: absolute;\n right: 8px; bottom: 7px; left: 52px;\n display: flex; justify-content: space-between;\n}\n/* Pie and donut: \"ring + drie legendaregels\", a disc for the pie and a ring\n with a 62 % hole for the donut, beside three lines. The skeleton is a size container: the disc\n is never taller than the skeleton, never wider than 60 % of it and at most 200 px, so the lines\n keep their room in a narrow tile. */\n.lintje-chart-skeleton--pie,\n.lintje-chart-skeleton--donut { container-type: size; display: flex; align-items: center; gap: var(--space-5); }\n.lintje-chart-skeleton__disc {\n position: relative;\n flex: none;\n aspect-ratio: 1;\n border-radius: var(--radius-round);\n}\n.lintje-chart-skeleton--donut .lintje-chart-skeleton__disc::after {\n content: '';\n position: absolute;\n inset: 19%;\n border-radius: var(--radius-round);\n background: var(--color-bg-surface);\n}\n.lintje-chart-skeleton__lines {\n flex: 1;\n min-width: 0;\n max-width: 240px;\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n}\n/* Heatmap: \"cellen glanzen individueel\" — cells with the heatmap's 3 px gutter, each with its\n own sweep. */\n.lintje-chart-skeleton--heatmap {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n grid-template-rows: repeat(5, minmax(0, 1fr));\n gap: 3px;\n}\n/* Map: \"kaartvlak glanst, overlays echt\" — the map area shimmers; the zoom buttons are drawn\n as on the map (48 px, top right). */\n.lintje-chart-skeleton__zoom {\n position: absolute;\n top: var(--space-2); right: var(--space-2);\n display: flex;\n flex-direction: column;\n}\n.lintje-chart-skeleton__zoom-button {\n width: var(--h-target); height: var(--h-target);\n display: flex; align-items: center; justify-content: center;\n background: var(--color-bg-surface);\n color: var(--color-text-primary);\n border: 1px solid var(--color-border-strong);\n margin-top: -1px;\n}\n.lintje-chart-skeleton__zoom-button:first-child { margin-top: 0; }\n/* Table: \"5 rijen\" — five rows at the table's row height. */\n.lintje-chart-skeleton--table { display: flex; flex-direction: column; }\n.lintje-chart-skeleton__row {\n flex: none;\n height: var(--h-table-row);\n display: flex;\n align-items: center;\n gap: var(--space-6);\n padding: 0 var(--space-3);\n border-bottom: 1px solid var(--color-border-default);\n}\n.lintje-chart-skeleton__measure { margin-left: auto; }\n\n/* --- Forced colours ------------------------------------------------------- */\n/* One colour per variable is what tells the series apart, and the legend's\n marker is what ties a colour to a name: with the reader's palette they would\n all come out one colour. So the data marks and the markers keep their drawing\n (`forced-color-adjust: none`) — the bars, segments and slices, the lines and\n their areas, the hover point, the legend's and the tooltip's markers — and\n nothing else does: the axes, the grid, the labels and the titles take the\n reader's palette. A data label is forced again even where it stands in a\n group that is not (the stacked column), except one drawn ON a mark, which keeps\n its own colour against that mark. The halo behind a label is the surface, so\n Canvas, and so are the gap between segments and the one inside the focus\n ring. The chosen mark is outlined in CanvasText and the focused one ringed in\n Highlight. */\n@media (forced-colors: active) {\n .lintje-chart__bar,\n .lintje-chart__mark,\n .lintje-chart__line,\n .lintje-chart__reveal,\n .lintje-chart__hover-point,\n .lintje-legend__marker,\n .lintje-chart-tooltip__marker { forced-color-adjust: none; }\n .lintje-chart__data-label { forced-color-adjust: auto; }\n /* Text in the reader's palette by name, not left to the engine: not every\n engine repaints an SVG `fill`, and near-black on a black Canvas is nothing. */\n .lintje-chart__axis-label,\n .lintje-chart__data-label,\n .lintje-chart__as-of-label,\n .lintje-chart__as-of-note { fill: CanvasText; }\n .lintje-chart__data-label--inside { forced-color-adjust: none; fill: var(--color-text-on-fill); }\n .lintje-chart__data-label--inside-light { forced-color-adjust: none; fill: var(--color-text-on-light-fill); }\n .lintje-chart__data-label--halo { stroke: Canvas; }\n .lintje-chart__segment { stroke: Canvas; }\n .lintje-chart__mark.is-selected { stroke: CanvasText; }\n .lintje-chart__focus-ring { flood-color: Highlight; }\n .lintje-chart__focus-gap { flood-color: Canvas; }\n}\n", g = ".lintje-pie-chart {\n display: flex; gap: var(--space-8); align-items: center; justify-content: center; flex-wrap: wrap;\n padding-top: var(--space-3);\n}\n.lintje-pie-chart--expanded { gap: var(--space-10); height: 100%; padding-top: 0; }\n.lintje-pie-chart--expanded .lintje-pie-chart__table { flex: 0 1 440px; min-width: 260px; }\n.lintje-pie-chart__center { font-family: var(--font-ui); font-size: 1.5rem; font-weight: 700; fill: var(--color-text-primary); }\n.lintje-pie-chart__table { flex: 1; min-width: 200px; border-collapse: collapse; font: var(--text-small); }\n.lintje-pie-chart__column-label,\n.lintje-pie-chart__label,\n.lintje-pie-chart__value,\n.lintje-pie-chart__total-label,\n.lintje-pie-chart__total { padding: 5px 0; text-align: left; font-weight: 400; }\n.lintje-pie-chart__column-label {\n font-size: var(--label-size); font-weight: var(--label-weight);\n letter-spacing: var(--label-tracking); text-transform: uppercase;\n color: var(--color-text-muted);\n border-bottom: 1px solid var(--color-border-default);\n}\n/* The numeric columns sit right-aligned under their heading, a fixed step from their neighbour. */\n.lintje-pie-chart__column-label--numeric,\n.lintje-pie-chart__value,\n.lintje-pie-chart__total { padding-left: var(--space-4); text-align: right; }\n.lintje-pie-chart__value,\n.lintje-pie-chart__total { font-variant-numeric: tabular-nums; }\n.lintje-pie-chart__label { display: flex; align-items: center; gap: 6px; }\n.lintje-pie-chart__total-label,\n.lintje-pie-chart__total {\n font-weight: 700; border-top: 1px solid var(--color-border-default); padding-top: 6px;\n}\n.lintje-pie-chart__marker { width: 10px; height: 10px; flex: none; display: block; }\n\n/* Hover scales the segment around the center, so its side edges keep their angle. The shadow\n sits on a copy on top (`__lift`); the segment itself only scales and eases back. */\n.lintje-pie-chart__svg { overflow: visible; flex: none; }\n.lintje-pie-chart__segment { transition: transform var(--dur-hover) var(--ease-in-motion); }\n.lintje-pie-chart__segment.is-hovered { transform: scale(1.03); }\n.lintje-pie-chart__lift {\n pointer-events: none;\n transform: scale(1.03);\n filter: drop-shadow(var(--shadow-chart-hover));\n animation: lintje-pie-lift var(--dur-hover) var(--ease-in-motion) backwards;\n}\n@keyframes lintje-pie-lift { from { transform: none; filter: none; } }\n.lintje-pie-chart__row.is-hovered { background: var(--color-bg-subtle); }\n/* The chosen row carries the outline the chosen slice has (rule 13). */\n.lintje-pie-chart__row.is-muted .lintje-pie-chart__marker { opacity: .45; }\n.lintje-pie-chart__row.is-selected .lintje-pie-chart__marker { outline: 2px solid var(--color-text-primary); }\n.lintje-pie-chart__row.is-selected .lintje-pie-chart__label { font-weight: 700; }\n\n/* Forced colours: the slices, the lifted copy and the table's swatches keep their colours (as\n `chart.css`); the chosen row's swatch is outlined in CanvasText. */\n@media (forced-colors: active) {\n .lintje-pie-chart__lift,\n .lintje-pie-chart__marker { forced-color-adjust: none; }\n .lintje-pie-chart__center { fill: CanvasText; }\n .lintje-pie-chart__row.is-selected .lintje-pie-chart__marker { outline-color: CanvasText; }\n}\n", _ = ".lintje-heatmap { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }\n.lintje-heatmap__grid { border-collapse: separate; border-spacing: 3px; width: 100%; }\n.lintje-heatmap__column-label,\n.lintje-heatmap__row-label {\n font: var(--text-axis);\n font-weight: 400;\n color: var(--color-text-muted);\n text-align: center;\n padding: 2px;\n}\n/* `width: 1%` keeps the auto table layout from handing the label column surplus width; a longer\n label ends in an ellipsis. */\n.lintje-heatmap__row-label { text-align: right; padding-right: var(--space-2); white-space: nowrap; width: 1%; }\n.lintje-heatmap__row-label-text { display: block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; }\n.lintje-heatmap__slot { padding: 0; }\n\n.lintje-heatmap__cell {\n width: 100%;\n height: 34px;\n display: flex; align-items: center; justify-content: center;\n font-size: 0.75rem;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n /* The class range is the same in both modes, so the text on it is too: ink up to the fourth\n rung (5.9:1), white on the darkest (4.5:1). */\n background: var(--lintje-cell);\n color: var(--color-text-on-light-fill);\n transition: background-color var(--dur-hover) var(--ease-in-motion);\n}\n.lintje-heatmap__cell--class-4 { color: var(--color-text-on-fill); }\n.lintje-heatmap__cell--class-0 { box-shadow: inset 0 0 0 1px var(--color-border-default); }\n.lintje-heatmap__cell.is-selected { outline: 2px solid currentColor; outline-offset: -2px; }\n/* A cell steps back by its fill alone, mixed into the surface; the figure stays in the text\n colour, which reaches 4.5:1 on every rung so mixed, in both modes. */\n.lintje-heatmap__cell.is-dimmed {\n background: color-mix(in srgb, var(--lintje-cell) 25%, var(--color-bg-surface));\n color: var(--color-text-primary);\n}\n/* A drilling cell that is not chosen steps back while a cell is chosen; less than the legend's\n dimming, which answers \"show me this class\". */\n.lintje-heatmap__cell.is-muted {\n background: color-mix(in srgb, var(--lintje-cell) 40%, var(--color-bg-surface));\n color: var(--color-text-primary);\n}\n.lintje-heatmap__cell.is-empty { background: var(--color-bg-subtle); }\n\n/* Cells fade in left to right, then top to bottom. Fill mode `backwards`: a held opacity would\n override a dimmed class. The paused declaration follows the shorthand, see chart.css. */\n@media (prefers-reduced-motion: no-preference) {\n .lintje-heatmap__cell:not(.is-empty) {\n animation: lintje-fade-in calc(var(--dur-draw) * 0.6) ease-in-out calc(var(--dur-draw) * 0.4 * var(--lintje-stagger, 0)) backwards;\n animation-play-state: paused;\n }\n [data-in-view] .lintje-heatmap__cell:not(.is-empty) { animation-play-state: running; }\n}\n\n.lintje-heatmap__selection {\n min-height: var(--h-touch);\n display: flex; align-items: center; gap: 6px;\n padding: 0 var(--space-3);\n background: var(--color-bg-subtle);\n font: var(--text-small);\n}\n\n.lintje-heatmap__legend { display: flex; gap: var(--space-2) var(--space-4); flex-wrap: wrap; font: var(--text-small); }\n.lintje-heatmap__legend-item {\n display: flex; align-items: center; gap: 6px;\n font: inherit; color: var(--color-text-primary);\n}\n.lintje-heatmap__legend-item[aria-pressed='true'] { font-weight: 700; }\n/* Only the swatch steps back: the word keeps its contrast. */\n.lintje-heatmap__legend-item.is-dimmed .lintje-heatmap__swatch { opacity: 0.45; }\n.lintje-heatmap__swatch {\n width: 12px; height: 12px; display: block; flex: none;\n transition: opacity var(--dur-hover) var(--ease-in-motion);\n}\n.lintje-heatmap__swatch--class-0 { box-shadow: inset 0 0 0 1px var(--color-border-default); }\n\n/* Forced colours: the class colours are the heatmap, so cells and swatches keep them\n (`forced-color-adjust: none`). */\n@media (forced-colors: active) {\n .lintje-heatmap__cell,\n .lintje-heatmap__swatch { forced-color-adjust: none; }\n}\n", v = n(h), y = [
158
- v,
159
- n(g),
160
- n(_),
161
- e
162
- ];
163
- //#endregion
164
- //#region src/components/shared/download.ts
165
- function b(e) {
166
- if (e == null) return "";
167
- let t = typeof e == "number" ? String(e).replace(".", ",") : e;
168
- return /[";\n\r]/.test(t) ? `"${t.replace(/"/g, "\"\"")}"` : t;
169
- }
170
- function x(e) {
171
- return e.map((e) => e.map(b).join(";")).join("\r\n");
172
- }
173
- function S(e, t) {
174
- let n = URL.createObjectURL(e), r = document.createElement("a");
175
- r.href = n, r.download = t, r.click(), setTimeout(() => URL.revokeObjectURL(n), 0);
176
- }
177
- function C(e, t) {
178
- let n = e.toLowerCase().endsWith(".csv") ? e : `${e}.csv`;
179
- S(new Blob(["", x(t)], { type: "text/csv;charset=utf-8" }), n);
180
- }
181
- var w = [
182
- "fill",
183
- "fill-opacity",
184
- "stroke",
185
- "stroke-width",
186
- "stroke-dasharray",
187
- "stroke-linecap",
188
- "stroke-linejoin",
189
- "opacity",
190
- "font-family",
191
- "font-size",
192
- "font-weight",
193
- "text-anchor",
194
- "dominant-baseline",
195
- "letter-spacing"
196
- ];
197
- function T(e, t) {
198
- let n = getComputedStyle(e), r = t.style;
199
- for (let e of w) r.setProperty(e, n.getPropertyValue(e));
200
- let i = e.children, a = t.children;
201
- for (let e = 0; e < i.length; e += 1) {
202
- let t = a[e];
203
- t && T(i[e], t);
204
- }
205
- }
206
- function E(e) {
207
- let t = (e) => getComputedStyle(e).getPropertyValue("--color-bg-surface").trim();
208
- return t(e) || t(document.documentElement);
209
- }
210
- async function D(e, t) {
211
- let n = e.toLowerCase().endsWith(".png") ? e : `${e}.png`, r = t.getBoundingClientRect(), i = Math.max(1, Math.round(r.width)), a = Math.max(1, Math.round(r.height)), o = t.cloneNode(!0);
212
- o.setAttribute("xmlns", "http://www.w3.org/2000/svg"), o.setAttribute("width", String(i)), o.setAttribute("height", String(a)), T(t, o);
213
- let s = E(t), c = new XMLSerializer().serializeToString(o), l = new Image();
214
- l.decoding = "sync", await new Promise((e, t) => {
215
- l.onload = () => e(), l.onerror = () => t(/* @__PURE__ */ Error("svg")), l.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(c)}`;
216
- });
217
- let u = document.createElement("canvas");
218
- u.width = i * 2, u.height = a * 2;
219
- let d = u.getContext("2d");
220
- if (!d) return;
221
- s && (d.fillStyle = s, d.fillRect(0, 0, u.width, u.height)), d.drawImage(l, 0, 0, u.width, u.height);
222
- let f = await new Promise((e) => u.toBlob(e, "image/png"));
223
- f && S(f, n);
224
- }
225
- //#endregion
226
- export { p as a, d as c, s as d, y as i, l, D as n, f as o, v as r, m as s, C as t, c as u };
@@ -1 +0,0 @@
1
- export * from '../types/components/charts/chart-tile/chart-tile.js'