@cfasim-ui/charts 0.7.3 → 0.7.5

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.
@@ -6,4 +6,10 @@ export declare function downloadBlob(blob: Blob, name: string): void;
6
6
  export declare function prepareSvgForExport(svg: SVGSVGElement): SVGSVGElement;
7
7
  export declare function saveSvg(svg: SVGSVGElement, filename: string): void;
8
8
  export declare function savePng(svg: SVGSVGElement, filename: string): void;
9
+ /**
10
+ * Downloads a rendering canvas's current contents as a PNG — no SVG
11
+ * round-trip. The canvas backing store is already sized at
12
+ * devicePixelRatio, so the export is naturally high-resolution.
13
+ */
14
+ export declare function saveCanvasPng(canvas: HTMLCanvasElement, filename: string): void;
9
15
  export declare function downloadCsv(csv: string, filename: string): void;
@@ -206,6 +206,16 @@ type __VLS_Props = {
206
206
  * built-in reset button is unaffected.
207
207
  */
208
208
  focusZoom?: boolean;
209
+ /**
210
+ * Rendering backend, fixed at mount. `"svg"` (default) keeps one DOM
211
+ * path per feature — full assistive-tech fallback (per-feature
212
+ * `<title>`) and SVG export. `"canvas"` paints every feature into a
213
+ * single canvas: much faster for dense maps (counties, HSAs) and on
214
+ * mobile WebKit, with identical interactions. In canvas mode the menu
215
+ * offers PNG export only, and there is no per-feature fallback for
216
+ * assistive tech — configure an interactive tooltip.
217
+ */
218
+ renderer?: "svg" | "canvas";
209
219
  /**
210
220
  * Where to teleport the map while expanded (the Expand menu item). A
211
221
  * CSS selector or element; defaults to `body`. Moving it to the
@@ -235,6 +245,7 @@ declare function __VLS_template(): {
235
245
  };
236
246
  refs: {
237
247
  containerRef: HTMLDivElement;
248
+ canvasRef: HTMLCanvasElement;
238
249
  svgRef: SVGSVGElement;
239
250
  mapGroupRef: SVGGElement;
240
251
  baseGroupRef: SVGGElement;
@@ -242,7 +253,9 @@ declare function __VLS_template(): {
242
253
  tooltipChildRef: ({
243
254
  $: import('vue').ComponentInternalInstance;
244
255
  $data: {};
245
- $props: Partial<{}> & Omit<{} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, never>;
256
+ $props: {
257
+ readonly mode?: "float" | "sheet" | undefined;
258
+ } & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
246
259
  $attrs: import('vue').Attrs;
247
260
  $refs: {
248
261
  [x: string]: unknown;
@@ -257,10 +270,15 @@ declare function __VLS_template(): {
257
270
  $host: Element | null;
258
271
  $emit: (event: string, ...args: any[]) => void;
259
272
  $el: any;
260
- $options: import('vue').ComponentOptionsBase<Readonly<{}> & Readonly<{}>, {
273
+ $options: import('vue').ComponentOptionsBase<Readonly<{
274
+ mode?: "float" | "sheet";
275
+ }> & Readonly<{}>, {
261
276
  setData(next: import('./ChoroplethTooltip').ChoroplethTooltipData | null): void;
277
+ setOpen(next: boolean): void;
262
278
  getEl(): HTMLDivElement | null;
263
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
279
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {
280
+ mode: "float" | "sheet";
281
+ }, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
264
282
  beforeCreate?: (() => void) | (() => void)[];
265
283
  created?: (() => void) | (() => void)[];
266
284
  beforeMount?: (() => void) | (() => void)[];
@@ -280,14 +298,28 @@ declare function __VLS_template(): {
280
298
  $forceUpdate: () => void;
281
299
  $nextTick: typeof nextTick;
282
300
  $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
283
- } & Readonly<{}> & Omit<Readonly<{}> & Readonly<{}>, "setData" | "getEl"> & {
301
+ } & Readonly<{
302
+ mode: "float" | "sheet";
303
+ }> & Omit<Readonly<{
304
+ mode?: "float" | "sheet";
305
+ }> & Readonly<{}>, "mode" | "setData" | "setOpen" | "getEl"> & {
284
306
  setData: (next: import('./ChoroplethTooltip').ChoroplethTooltipData | null) => void;
307
+ setOpen: (next: boolean) => void;
285
308
  getEl: () => HTMLDivElement | null;
286
309
  } & {} & import('vue').ComponentCustomProperties & {} & {
287
- $slots: Readonly<{
288
- default?(props: import('./ChoroplethTooltip').ChoroplethTooltipData): unknown;
289
- }> & {
290
- default?(props: import('./ChoroplethTooltip').ChoroplethTooltipData): unknown;
310
+ $slots: {
311
+ default?(_: {
312
+ id: string;
313
+ name: string;
314
+ value?: number | string | undefined;
315
+ feature: unknown;
316
+ }): any;
317
+ default?(_: {
318
+ id: string;
319
+ name: string;
320
+ value?: number | string | undefined;
321
+ feature: unknown;
322
+ }): any;
291
323
  };
292
324
  }) | null;
293
325
  };
@@ -332,8 +364,10 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
332
364
  zoomHint: boolean;
333
365
  focusZoomLevel: number;
334
366
  focusZoom: boolean;
367
+ renderer: "svg" | "canvas";
335
368
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
336
369
  containerRef: HTMLDivElement;
370
+ canvasRef: HTMLCanvasElement;
337
371
  svgRef: SVGSVGElement;
338
372
  mapGroupRef: SVGGElement;
339
373
  baseGroupRef: SVGGElement;
@@ -341,7 +375,9 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
341
375
  tooltipChildRef: ({
342
376
  $: import('vue').ComponentInternalInstance;
343
377
  $data: {};
344
- $props: Partial<{}> & Omit<{} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, never>;
378
+ $props: {
379
+ readonly mode?: "float" | "sheet" | undefined;
380
+ } & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
345
381
  $attrs: import('vue').Attrs;
346
382
  $refs: {
347
383
  [x: string]: unknown;
@@ -356,10 +392,15 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
356
392
  $host: Element | null;
357
393
  $emit: (event: string, ...args: any[]) => void;
358
394
  $el: any;
359
- $options: import('vue').ComponentOptionsBase<Readonly<{}> & Readonly<{}>, {
395
+ $options: import('vue').ComponentOptionsBase<Readonly<{
396
+ mode?: "float" | "sheet";
397
+ }> & Readonly<{}>, {
360
398
  setData(next: import('./ChoroplethTooltip').ChoroplethTooltipData | null): void;
399
+ setOpen(next: boolean): void;
361
400
  getEl(): HTMLDivElement | null;
362
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
401
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {
402
+ mode: "float" | "sheet";
403
+ }, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
363
404
  beforeCreate?: (() => void) | (() => void)[];
364
405
  created?: (() => void) | (() => void)[];
365
406
  beforeMount?: (() => void) | (() => void)[];
@@ -379,14 +420,28 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
379
420
  $forceUpdate: () => void;
380
421
  $nextTick: typeof nextTick;
381
422
  $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
382
- } & Readonly<{}> & Omit<Readonly<{}> & Readonly<{}>, "setData" | "getEl"> & {
423
+ } & Readonly<{
424
+ mode: "float" | "sheet";
425
+ }> & Omit<Readonly<{
426
+ mode?: "float" | "sheet";
427
+ }> & Readonly<{}>, "mode" | "setData" | "setOpen" | "getEl"> & {
383
428
  setData: (next: import('./ChoroplethTooltip').ChoroplethTooltipData | null) => void;
429
+ setOpen: (next: boolean) => void;
384
430
  getEl: () => HTMLDivElement | null;
385
431
  } & {} & import('vue').ComponentCustomProperties & {} & {
386
- $slots: Readonly<{
387
- default?(props: import('./ChoroplethTooltip').ChoroplethTooltipData): unknown;
388
- }> & {
389
- default?(props: import('./ChoroplethTooltip').ChoroplethTooltipData): unknown;
432
+ $slots: {
433
+ default?(_: {
434
+ id: string;
435
+ name: string;
436
+ value?: number | string | undefined;
437
+ feature: unknown;
438
+ }): any;
439
+ default?(_: {
440
+ id: string;
441
+ name: string;
442
+ value?: number | string | undefined;
443
+ feature: unknown;
444
+ }): any;
390
445
  };
391
446
  }) | null;
392
447
  }, any>;
@@ -4,12 +4,32 @@ export interface ChoroplethTooltipData {
4
4
  value?: number | string;
5
5
  feature: unknown;
6
6
  }
7
+ type __VLS_Props = {
8
+ /**
9
+ * `"float"` (default) renders the classic pointer-anchored tooltip.
10
+ * `"sheet"` renders a bottom sheet that slides up inside the map
11
+ * wrapper instead — used in the expanded touch view, where it stays
12
+ * correctly positioned regardless of the page's pinch-zoom state
13
+ * (the wrapper is pinned to the visual viewport; floating fixed
14
+ * positioning is not).
15
+ */
16
+ mode?: "float" | "sheet";
17
+ };
7
18
  declare function __VLS_template(): {
8
19
  attrs: Partial<{}>;
9
- slots: Readonly<{
10
- default?(props: ChoroplethTooltipData): unknown;
11
- }> & {
12
- default?(props: ChoroplethTooltipData): unknown;
20
+ slots: {
21
+ default?(_: {
22
+ id: string;
23
+ name: string;
24
+ value?: number | string | undefined;
25
+ feature: unknown;
26
+ }): any;
27
+ default?(_: {
28
+ id: string;
29
+ name: string;
30
+ value?: number | string | undefined;
31
+ feature: unknown;
32
+ }): any;
13
33
  };
14
34
  refs: {
15
35
  root: HTMLDivElement;
@@ -17,10 +37,14 @@ declare function __VLS_template(): {
17
37
  rootEl: any;
18
38
  };
19
39
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
20
- declare const __VLS_component: import('vue').DefineComponent<{}, {
40
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
21
41
  setData(next: ChoroplethTooltipData | null): void;
42
+ /** Sheet-mode visibility (float mode is driven imperatively via getEl). */
43
+ setOpen(next: boolean): void;
22
44
  getEl(): HTMLDivElement | null;
23
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
45
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
46
+ mode: "float" | "sheet";
47
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
24
48
  root: HTMLDivElement;
25
49
  }, any>;
26
50
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
@@ -0,0 +1,79 @@
1
+ /** Matches ChoroplethMap's FocusStyle without importing from the SFC. */
2
+ export type CanvasDashStyle = "solid" | "dashed" | "dotted";
3
+ export interface SceneItem {
4
+ id: string;
5
+ path: Path2D;
6
+ fill: string;
7
+ }
8
+ export interface CanvasScene {
9
+ items: SceneItem[];
10
+ indexById: Map<string, number>;
11
+ /**
12
+ * Every feature outline concatenated into one path — features share a
13
+ * stroke color, and one native stroke call beats thousands (WebKit's
14
+ * canvas2D especially).
15
+ */
16
+ outlines: Path2D | null;
17
+ /** State-borders mesh (counties / hsas mode). */
18
+ borders: Path2D | null;
19
+ }
20
+ export interface CanvasView {
21
+ dpr: number;
22
+ /** Uniform viewBox→CSS scale (xMidYMid meet). */
23
+ meetScale: number;
24
+ /** CSS-px letterbox offsets inside the canvas box. */
25
+ offsetX: number;
26
+ offsetY: number;
27
+ zoom: {
28
+ k: number;
29
+ x: number;
30
+ y: number;
31
+ };
32
+ }
33
+ export interface CanvasOverlayItem {
34
+ path: Path2D;
35
+ stroke: string;
36
+ strokeWidth?: number;
37
+ style?: CanvasDashStyle;
38
+ }
39
+ export interface CanvasHighlightItem {
40
+ stroke?: string;
41
+ strokeWidth?: number;
42
+ style?: CanvasDashStyle;
43
+ }
44
+ export interface CanvasBaseState {
45
+ strokeColor: string;
46
+ /** Base feature stroke width in CSS px (effectiveStrokeWidth). */
47
+ strokeWidth: number;
48
+ /** Resolved highlight color (light-dark() can't paint on canvas). */
49
+ highlightStroke: string;
50
+ focused: Map<string, CanvasHighlightItem>;
51
+ overlays: CanvasOverlayItem[];
52
+ }
53
+ export interface CanvasDrawState extends CanvasBaseState {
54
+ hoveredId: string | null;
55
+ }
56
+ export declare function buildScene(features: Array<{
57
+ id?: string | number | null;
58
+ }>, pathFor: (feature: never) => string | null, colorFor: (id: string) => string, bordersD?: string | null): CanvasScene;
59
+ /** Live hover highlight, drawn by the display frame on top of the blitted
60
+ * base (focused features are already highlighted in the base itself). */
61
+ export declare function drawHoverHighlight(ctx: CanvasRenderingContext2D, scene: CanvasScene, view: CanvasView, state: CanvasBaseState, hoveredId: string | null): void;
62
+ /** One-shot full repaint (composition of the passes above). */
63
+ export declare function drawScene(ctx: CanvasRenderingContext2D, scene: CanvasScene, view: CanvasView, state: CanvasDrawState): void;
64
+ /** Unique fill color for feature index `i` on the picking canvas. */
65
+ export declare function indexToColor(i: number): string;
66
+ /**
67
+ * Paints every feature in a unique index color onto `canvas` at canonical
68
+ * viewBox resolution. Rebuilt only when the geometry changes; hit-testing
69
+ * then reads one pixel per query regardless of feature count.
70
+ */
71
+ export declare function buildPicking(scene: CanvasScene, width: number, height: number, canvas: HTMLCanvasElement): CanvasRenderingContext2D | null;
72
+ /**
73
+ * Feature index at canonical viewBox coordinates (the caller has already
74
+ * inverted the zoom transform), or null over the background. Fill edges
75
+ * antialias into blended colors, so a candidate whose decoded index is
76
+ * implausible — or that fails a point-in-path check — falls back to a
77
+ * linear `isPointInPath` scan (rare, borders only).
78
+ */
79
+ export declare function pickIndexAt(ctx: CanvasRenderingContext2D, scene: CanvasScene, x: number, y: number): number | null;
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- .chart-menu-trigger-area[data-v-f5743494]{z-index:1;position:absolute;top:.5em;right:.5em}.chart-menu-trigger-area--expanded[data-v-f5743494]{top:1.25em;right:1.25em}.chart-menu-button[data-v-f5743494]{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary);cursor:pointer;opacity:0;border-radius:.25em;justify-content:center;align-items:center;transition:opacity .15s;display:flex}.chart-menu-button[data-state=open][data-v-f5743494],.chart-close-button[data-v-f5743494]{opacity:1}.chart-menu-button[data-v-f5743494]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.line-chart-wrapper:hover .chart-menu-button,.bar-chart-wrapper:hover .chart-menu-button,.choropleth-wrapper:hover .chart-menu-button,.line-chart-wrapper:focus-within .chart-menu-button,.bar-chart-wrapper:focus-within .chart-menu-button,.choropleth-wrapper:focus-within .chart-menu-button{opacity:1}.chart-sr-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.chart-menu-content{z-index:100;background:var(--color-bg-0);border:1px solid var(--color-border);border-radius:.25em;min-width:140px;padding:.25em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.chart-menu-item{font-size:var(--font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;border-radius:.25em;outline:none;align-items:center;padding:.375em .5em;display:flex}.chart-menu-item[data-highlighted]{background:var(--color-primary);color:#fff}.chart-zoom-controls[data-v-87ceeada]{z-index:1;flex-direction:column;gap:4px;display:flex;position:absolute;top:.5em;left:.5em}.chart-zoom-controls--expanded[data-v-87ceeada]{top:1.25em;left:1.25em}.chart-zoom-button[data-v-87ceeada]{border:1px solid var(--color-border,#e5e7eb);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary,#555);cursor:pointer;border-radius:.25em;justify-content:center;align-items:center;padding:0;display:flex}.chart-zoom-button[data-v-87ceeada]:hover:not(:disabled){background:var(--color-bg-1,#0000000d);color:var(--color-text)}.chart-zoom-button[data-v-87ceeada]:disabled{opacity:.4;cursor:default}.line-chart-wrapper[data-v-a3132bed]{width:100%;position:relative}.line-chart-tooltip-label[data-v-a3132bed]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-a3132bed]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-a3132bed]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-a3132bed]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.line-chart-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.5em;padding:.5em 1em;display:inline-flex}.line-chart-download-button:hover{background:var(--color-bg-1,#0000000d)}.line-chart-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.bar-chart-wrapper[data-v-251f7945]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-251f7945]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-251f7945]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-251f7945]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-251f7945]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.bar-chart-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.5em;padding:.5em 1em;display:inline-flex}.bar-chart-download-button:hover{background:var(--color-bg-1,#0000000d)}.bar-chart-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.choropleth-wrapper[data-v-75643edc]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative;container-type:inline-size}.choropleth-wrapper svg[data-v-75643edc]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-75643edc]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-75643edc]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-75643edc]:active{cursor:grabbing}.state-path[data-v-75643edc]{cursor:pointer}.choropleth-zoom-hint[data-v-75643edc]{z-index:1;text-align:center;color:var(--color-text-secondary,#777);opacity:.6;pointer-events:none;text-shadow:1px 0 0 var(--color-bg-0,#fff), -1px 0 0 var(--color-bg-0,#fff), 0 1px 0 var(--color-bg-0,#fff), 0 -1px 0 var(--color-bg-0,#fff), 0 0 3px var(--color-bg-0,#fff);padding-top:6px;font-size:12px;line-height:1.4;position:absolute;left:0;right:0}@container (width<=480px){.choropleth-zoom-hint[data-v-75643edc]{padding:0;position:static}}.choropleth-header[data-v-75643edc]{background:var(--choropleth-legend-bg);color:currentColor;border-radius:4px;flex-direction:column;align-items:center;gap:10px;width:fit-content;margin:0 auto;padding:8px 14px;display:flex}.choropleth-title[data-v-75643edc]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-75643edc]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-75643edc]{font-weight:600}.choropleth-legend[data-v-75643edc]:has(.choropleth-legend-continuous){align-items:flex-start}.choropleth-legend:has(.choropleth-legend-continuous) .choropleth-legend-title[data-v-75643edc]{line-height:12px}.choropleth-legend-item[data-v-75643edc]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-75643edc]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-75643edc]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-75643edc]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-75643edc]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-75643edc]{position:absolute;transform:translate(-50%)}.chart-tooltip-anchor[data-v-44377f70]{pointer-events:none;width:1px;height:1px;position:absolute}.chart-tooltip-content{z-index:100;background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);font-size:var(--font-size-sm,.875rem);pointer-events:none;border-radius:.375em;padding:.5em .75em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.TableOuter[data-v-9b1b6a76]{display:inline-block;position:relative}.TableOuter.full-width[data-v-9b1b6a76]{display:block}.TableWrapper[data-v-9b1b6a76]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-9b1b6a76]{border-collapse:collapse;font-variant-numeric:tabular-nums;border:1px solid var(--color-border);table-layout:fixed;margin:0;display:table}.Table.full-width[data-v-9b1b6a76]{width:100%}.Table tr[data-v-9b1b6a76],.Table th[data-v-9b1b6a76],.Table td[data-v-9b1b6a76]{background:0 0;border:none}.Table th[data-v-9b1b6a76],.Table td[data-v-9b1b6a76]{white-space:nowrap;text-overflow:ellipsis;text-align:left;padding:.75em 1.25em;overflow:hidden}.Table th.cell-wrap[data-v-9b1b6a76],.Table td.cell-wrap[data-v-9b1b6a76]{white-space:normal;text-overflow:clip;overflow:visible}.Table th[data-v-9b1b6a76]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-9b1b6a76]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-9b1b6a76]{border-bottom:none}.TableOuter[data-v-9b1b6a76] .chart-menu-trigger-area{top:4px;right:4px}.TableOuter[data-v-9b1b6a76] .chart-menu-button{opacity:1}.TableOuter.has-menu .Table thead th[data-v-9b1b6a76]:last-child{padding-right:2.5em}.data-table-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.75em;padding:.5em 1em;display:inline-flex}.data-table-download-button:hover{background:var(--color-bg-1,#0000000d)}.data-table-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.data-table-download-link{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}
1
+ .chart-menu-trigger-area[data-v-f5743494]{z-index:1;position:absolute;top:.5em;right:.5em}.chart-menu-trigger-area--expanded[data-v-f5743494]{top:1.25em;right:1.25em}.chart-menu-button[data-v-f5743494]{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary);cursor:pointer;opacity:0;border-radius:.25em;justify-content:center;align-items:center;transition:opacity .15s;display:flex}.chart-menu-button[data-state=open][data-v-f5743494],.chart-close-button[data-v-f5743494]{opacity:1}.chart-menu-button[data-v-f5743494]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.line-chart-wrapper:hover .chart-menu-button,.bar-chart-wrapper:hover .chart-menu-button,.choropleth-wrapper:hover .chart-menu-button,.line-chart-wrapper:focus-within .chart-menu-button,.bar-chart-wrapper:focus-within .chart-menu-button,.choropleth-wrapper:focus-within .chart-menu-button{opacity:1}.chart-sr-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.chart-menu-content{z-index:100;background:var(--color-bg-0);border:1px solid var(--color-border);border-radius:.25em;min-width:140px;padding:.25em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.chart-menu-item{font-size:var(--font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;border-radius:.25em;outline:none;align-items:center;padding:.375em .5em;display:flex}.chart-menu-item[data-highlighted]{background:var(--color-primary);color:#fff}.chart-zoom-controls[data-v-87ceeada]{z-index:1;flex-direction:column;gap:4px;display:flex;position:absolute;top:.5em;left:.5em}.chart-zoom-controls--expanded[data-v-87ceeada]{top:1.25em;left:1.25em}.chart-zoom-button[data-v-87ceeada]{border:1px solid var(--color-border,#e5e7eb);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary,#555);cursor:pointer;border-radius:.25em;justify-content:center;align-items:center;padding:0;display:flex}.chart-zoom-button[data-v-87ceeada]:hover:not(:disabled){background:var(--color-bg-1,#0000000d);color:var(--color-text)}.chart-zoom-button[data-v-87ceeada]:disabled{opacity:.4;cursor:default}.line-chart-wrapper[data-v-a3132bed]{width:100%;position:relative}.line-chart-tooltip-label[data-v-a3132bed]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-a3132bed]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-a3132bed]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-a3132bed]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.line-chart-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.5em;padding:.5em 1em;display:inline-flex}.line-chart-download-button:hover{background:var(--color-bg-1,#0000000d)}.line-chart-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.bar-chart-wrapper[data-v-251f7945]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-251f7945]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-251f7945]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-251f7945]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-251f7945]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.bar-chart-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.5em;padding:.5em 1em;display:inline-flex}.bar-chart-download-button:hover{background:var(--color-bg-1,#0000000d)}.bar-chart-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.chart-tooltip-sheet[data-v-90392830]{z-index:2;background:var(--color-bg-0,#fff);color:var(--color-text,inherit);border-top:1px solid var(--color-border,#e5e7eb);padding:14px 16px calc(14px + env(safe-area-inset-bottom,0px));pointer-events:none;font-size:14px;line-height:1.4;transition:transform .25s;position:absolute;bottom:0;left:0;right:0;transform:translateY(100%);box-shadow:0 -4px 12px #0000001f}.chart-tooltip-sheet.is-open[data-v-90392830]{transform:translateY(0)}.choropleth-wrapper[data-v-8366c5c6]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative;container-type:inline-size}.choropleth-wrapper svg[data-v-8366c5c6]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-8366c5c6]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-8366c5c6]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-8366c5c6]:active{cursor:grabbing}.state-path[data-v-8366c5c6]{cursor:pointer}.choropleth-canvas[data-v-8366c5c6]{pointer-events:none;will-change:transform;position:absolute;top:0;left:0}.choropleth-zoom-hint[data-v-8366c5c6]{z-index:1;text-align:center;color:var(--color-text-secondary,#777);opacity:.6;pointer-events:none;text-shadow:1px 0 0 var(--color-bg-0,#fff), -1px 0 0 var(--color-bg-0,#fff), 0 1px 0 var(--color-bg-0,#fff), 0 -1px 0 var(--color-bg-0,#fff), 0 0 3px var(--color-bg-0,#fff);padding-top:6px;font-size:12px;line-height:1.4;position:absolute;left:0;right:0}@container (width<=480px){.choropleth-zoom-hint[data-v-8366c5c6]{padding:0;position:static}}.choropleth-header[data-v-8366c5c6]{background:var(--choropleth-legend-bg);color:currentColor;border-radius:4px;flex-direction:column;align-items:center;gap:10px;width:fit-content;margin:0 auto;padding:8px 14px;display:flex}.choropleth-title[data-v-8366c5c6]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-8366c5c6]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-8366c5c6]{font-weight:600}.choropleth-legend[data-v-8366c5c6]:has(.choropleth-legend-continuous){align-items:flex-start}.choropleth-legend:has(.choropleth-legend-continuous) .choropleth-legend-title[data-v-8366c5c6]{line-height:12px}.choropleth-legend-item[data-v-8366c5c6]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-8366c5c6]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-8366c5c6]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-8366c5c6]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-8366c5c6]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-8366c5c6]{position:absolute;transform:translate(-50%)}.chart-tooltip-anchor[data-v-44377f70]{pointer-events:none;width:1px;height:1px;position:absolute}.chart-tooltip-content{z-index:100;background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);font-size:var(--font-size-sm,.875rem);pointer-events:none;border-radius:.375em;padding:.5em .75em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.TableOuter[data-v-9b1b6a76]{display:inline-block;position:relative}.TableOuter.full-width[data-v-9b1b6a76]{display:block}.TableWrapper[data-v-9b1b6a76]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-9b1b6a76]{border-collapse:collapse;font-variant-numeric:tabular-nums;border:1px solid var(--color-border);table-layout:fixed;margin:0;display:table}.Table.full-width[data-v-9b1b6a76]{width:100%}.Table tr[data-v-9b1b6a76],.Table th[data-v-9b1b6a76],.Table td[data-v-9b1b6a76]{background:0 0;border:none}.Table th[data-v-9b1b6a76],.Table td[data-v-9b1b6a76]{white-space:nowrap;text-overflow:ellipsis;text-align:left;padding:.75em 1.25em;overflow:hidden}.Table th.cell-wrap[data-v-9b1b6a76],.Table td.cell-wrap[data-v-9b1b6a76]{white-space:normal;text-overflow:clip;overflow:visible}.Table th[data-v-9b1b6a76]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-9b1b6a76]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-9b1b6a76]{border-bottom:none}.TableOuter[data-v-9b1b6a76] .chart-menu-trigger-area{top:4px;right:4px}.TableOuter[data-v-9b1b6a76] .chart-menu-button{opacity:1}.TableOuter.has-menu .Table thead th[data-v-9b1b6a76]:last-child{padding-right:2.5em}.data-table-download-button{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;border-radius:.25em;align-items:center;margin-top:.75em;padding:.5em 1em;display:inline-flex}.data-table-download-button:hover{background:var(--color-bg-1,#0000000d)}.data-table-download-button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.data-table-download-link{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}
2
2
  /*$vite$:1*/