@cfasim-ui/charts 0.6.4 → 0.7.1

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.
@@ -1,3 +1,4 @@
1
+ import { nextTick } from 'vue';
1
2
  import { Topology } from 'topojson-specification';
2
3
  import { NumberFormat } from '@cfasim-ui/shared';
3
4
  import { TitleStyle, LabelStyle } from '../_shared/index.js';
@@ -43,10 +44,14 @@ export interface FocusItem {
43
44
  * `"dashed"` uses long dashes; `"dotted"` uses small round dots —
44
45
  * useful when stacking multiple outlines of different geoTypes. */
45
46
  style?: FocusStyle;
46
- /** Stroke color for the outline. Applies to cross-geoType overlay
47
- * paths only (base-geoType highlights stay at the default focus
48
- * color). Default: `"#fff"`. */
47
+ /** Stroke color for the outline. In-place highlights (items in the
48
+ * base geoType) default to pure black/white following the theme
49
+ * (`light-dark(#000, #fff)`); cross-geoType overlay paths default to
50
+ * `"#fff"`. */
49
51
  stroke?: string;
52
+ /** Outline width in CSS px. Defaults to the map's stroke width + 1
53
+ * for in-place highlights and + 1.5 for cross-geoType overlays. */
54
+ strokeWidth?: number;
50
55
  }
51
56
  export type FocusValue = string | FocusItem | Array<string | FocusItem> | null;
52
57
  type __VLS_Props = {
@@ -110,18 +115,45 @@ type __VLS_Props = {
110
115
  legend?: boolean;
111
116
  /** Title displayed next to the legend */
112
117
  legendTitle?: string;
113
- /** Enable mouse-wheel zooming. Default: false */
118
+ /**
119
+ * Enable the activate-to-zoom interaction. Default `false` — the map
120
+ * is fully static (tooltips and click-select still work, and
121
+ * programmatic `focus` zoom still applies). When enabled, the map
122
+ * stays static until the user double-clicks (desktop) or taps (touch):
123
+ * desktop double-click zooms in place alongside always-visible
124
+ * +/−/reset controls, with drag-pan once zoomed; on touch a tap
125
+ * expands the map to fill the window, where one finger pans, pinch
126
+ * zooms, and a tap selects. The scroll wheel never zooms inline, so
127
+ * the map can't hijack page scrolling.
128
+ */
114
129
  zoom?: boolean;
115
- /** Enable click-and-drag panning. Default: false */
116
- pan?: boolean;
117
130
  /**
118
- * Require two fingers to pan/zoom on touch devices. Default `false`.
119
- * When `true`, a single finger scrolls the page (the map sets
120
- * `touch-action: pan-y` and ignores one-finger drags) while two fingers
121
- * pan and pinch-zoom the map. Single-finger tap-to-select still works.
122
- * Has no effect with a mouse.
131
+ * Interaction style when `zoom` is enabled. `"activate"` (default)
132
+ * keeps the map static until a double-click / tap / feature click, so
133
+ * the page scrolls freely past it. `"scroll"` makes the map immediately
134
+ * interactive the wheel zooms, dragging pans, and touch gestures work
135
+ * inline with no tap-to-expand step. Use it for full-page experiences
136
+ * where the map is the main surface and there's no page scroll to
137
+ * hijack.
138
+ */
139
+ zoomMode?: "activate" | "scroll";
140
+ /**
141
+ * On touch devices, expand the map to fill the window when tapped.
142
+ * Default `true`. Set `false` to zoom in place instead: the first tap
143
+ * zooms the inline map in on the tapped point (like a desktop
144
+ * double-click), after which one-finger pan / pinch work and taps
145
+ * select features; the +/−/reset controls render inline. Note the
146
+ * activated map captures touch scrolling over it. No effect on desktop
147
+ * or when `zoom` is off; `zoom-mode="scroll"` already implies inline
148
+ * interaction.
149
+ */
150
+ touchExpand?: boolean;
151
+ /**
152
+ * Show the grey "Double click to zoom" / "Tap to zoom" affordance over
153
+ * the top of the map while the zoom gesture hasn't been used yet.
154
+ * Default `true`; set `false` to hide it. No effect when `zoom` is off.
123
155
  */
124
- twoFingerPan?: boolean;
156
+ zoomHint?: boolean;
125
157
  /** Tooltip activation mode */
126
158
  tooltipTrigger?: "hover" | "click";
127
159
  /**
@@ -158,7 +190,7 @@ type __VLS_Props = {
158
190
  * current pan/zoom transform is preserved; only the highlight is
159
191
  * removed. Works with `v-model:focus`: clicking an unfocused feature
160
192
  * (in the base geoType) emits its id; clicking the focused feature
161
- * emits `null`. The built-in Reset button clears focus *and* resets
193
+ * emits `null`. The built-in reset button clears focus *and* resets
162
194
  * the zoom. If a tooltip is configured, focusing a feature in the
163
195
  * base geoType shows its tooltip.
164
196
  */
@@ -170,7 +202,7 @@ type __VLS_Props = {
170
202
  * Default `true`. Set `false` to highlight (and draw cross-geoType
171
203
  * overlays) without changing the current pan/zoom — useful for a
172
204
  * click-to-select interaction where the map should stay put. The
173
- * built-in Reset button is unaffected.
205
+ * built-in reset button is unaffected.
174
206
  */
175
207
  focusZoom?: boolean;
176
208
  /**
@@ -245,7 +277,7 @@ declare function __VLS_template(): {
245
277
  errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
246
278
  };
247
279
  $forceUpdate: () => void;
248
- $nextTick: typeof import('vue').nextTick;
280
+ $nextTick: typeof nextTick;
249
281
  $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;
250
282
  } & Readonly<{}> & Omit<Readonly<{}> & Readonly<{}>, "setData" | "getEl"> & {
251
283
  setData: (next: import('./ChoroplethTooltip').ChoroplethTooltipData | null) => void;
@@ -294,8 +326,9 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
294
326
  noDataColor: string;
295
327
  strokeColor: string;
296
328
  zoom: boolean;
297
- pan: boolean;
298
- twoFingerPan: boolean;
329
+ zoomMode: "activate" | "scroll";
330
+ touchExpand: boolean;
331
+ zoomHint: boolean;
299
332
  focusZoomLevel: number;
300
333
  focusZoom: boolean;
301
334
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
@@ -343,7 +376,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
343
376
  errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
344
377
  };
345
378
  $forceUpdate: () => void;
346
- $nextTick: typeof import('vue').nextTick;
379
+ $nextTick: typeof nextTick;
347
380
  $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;
348
381
  } & Readonly<{}> & Omit<Readonly<{}> & Readonly<{}>, "setData" | "getEl"> & {
349
382
  setData: (next: import('./ChoroplethTooltip').ChoroplethTooltipData | null) => void;
@@ -0,0 +1,24 @@
1
+ type __VLS_Props = {
2
+ canZoomIn?: boolean;
3
+ canZoomOut?: boolean;
4
+ /** Reset is a no-op at the identity transform — disable it there. */
5
+ canReset?: boolean;
6
+ /** Insets the stack further from the corner while the chart fills the
7
+ * window, matching the ChartMenu trigger area. */
8
+ isFullscreen?: boolean;
9
+ };
10
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
11
+ reset: () => any;
12
+ zoomIn: () => any;
13
+ zoomOut: () => any;
14
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onReset?: (() => any) | undefined;
16
+ onZoomIn?: (() => any) | undefined;
17
+ onZoomOut?: (() => any) | undefined;
18
+ }>, {
19
+ isFullscreen: boolean;
20
+ canZoomIn: boolean;
21
+ canZoomOut: boolean;
22
+ canReset: boolean;
23
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
24
+ export default _default;
@@ -1,15 +1,17 @@
1
- export { snap, niceStep, intervalValues, formatTick, type ChartData, } from './axes.js';
1
+ export { snap, formatTick, type ChartData } from './axes.js';
2
2
  export { computeTickValues, type TickValueOptions } from './computeTicks.js';
3
- export { scaleFraction, clampExtentForScale, computeLogTickValues, LOG_FLOOR, type ScaleType, } from './scale.js';
3
+ export { scaleFraction, clampExtentForScale, computeLogTickValues, type ScaleType, } from './scale.js';
4
4
  export { useChartSize, type ChartSizeOptions } from './useChartSize.js';
5
5
  export { useChartPadding, resolveLabelStyle, INLINE_LEGEND_ROW_HEIGHT, TITLE_LINE_HEIGHT, TITLE_FONT_SIZE, TITLE_FONT_WEIGHT, AXIS_LABEL_FONT_SIZE, TICK_LABEL_FONT_SIZE, TICK_LABEL_OPACITY, LEGEND_FONT_SIZE, type ChartPaddingOptions, type ChartPadding, type ChartBounds, type PositionedLegendItem, } from './useChartPadding.js';
6
6
  export { useChartTooltip, type ChartTooltipOptions, } from './useChartTooltip.js';
7
7
  export { useChartMenu, type ChartMenuOptions } from './useChartMenu.js';
8
8
  export { useChartFullscreen } from './useChartFullscreen.js';
9
+ export { isTouchDevice } from './touch.js';
10
+ export { default as ChartZoomControls } from './ChartZoomControls';
9
11
  export { seriesToCsv, categoricalToCsv, type CsvSeries } from './seriesCsv.js';
10
12
  export { default as ChartAnnotations } from './ChartAnnotations';
11
13
  export type { ChartAnnotation } from './annotations.js';
12
14
  export { useChartFoundation, makeTooltipValueFormatter, type ChartFoundationOptions, } from './useChartFoundation.js';
13
15
  export type { ChartCommonProps, ChartHoverPayload, ChartTooltipValue, ChartTooltipBaseProps, TitleStyle, LabelStyle, BlendMode, LineMarkStyle, } from './chartProps.js';
14
- export { parseRgb, relativeLuminance, resolveColorToRgb, pickContrastColor, type Rgb, } from './contrast.js';
16
+ export { resolveColorToRgb, pickContrastColor, type Rgb } from './contrast.js';
15
17
  export { parseDate, isDateLike, isAllDates, pickDateTicks, formatDate, DATE_FORMAT_PRESETS, type DateFormat, type DateFormatPreset, type DateTickUnit, type DateTimezone, } from './dateAxis.js';
@@ -18,3 +18,4 @@ export declare function categoricalToCsv(categories: readonly string[], series:
18
18
  label?: string;
19
19
  data: ChartData;
20
20
  }[], categoryHeader?: string): string;
21
+ export declare function escapeCsvField(value: string): string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Whether the current device has a touch screen. A function (not a
3
+ * module-level constant) so unit tests can mock it per-case and so SSR
4
+ * evaluation is deferred until an event actually needs the answer.
5
+ */
6
+ export declare function isTouchDevice(): boolean;
@@ -105,7 +105,6 @@ export declare function useChartFoundation(opts: ChartFoundationOptions): {
105
105
  fullscreenStyle: import('vue').ComputedRef<Record<string, string> | undefined>;
106
106
  teleportTarget: import('vue').ComputedRef<string | HTMLElement>;
107
107
  exitFullscreen: () => void;
108
- measuredHeight: import('vue').Ref<number, number>;
109
108
  };
110
109
  /**
111
110
  * Build a tooltip value formatter that prefers `tooltipValueFormat`,
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}.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-7bd9e073]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative}.choropleth-wrapper svg[data-v-7bd9e073]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-7bd9e073]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-7bd9e073]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-7bd9e073]:active{cursor:grabbing}.state-path[data-v-7bd9e073]{cursor:pointer}.choropleth-reset[data-v-7bd9e073]{font:inherit;color:var(--color-text-secondary,#555);background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);cursor:pointer;border-radius:4px;padding:4px 10px;font-size:12px;position:absolute;bottom:8px;left:8px;box-shadow:0 1px 2px #0000000d}.choropleth-reset[data-v-7bd9e073]:hover{background:var(--color-bg-1,#f8f9fa);color:var(--color-text,#212529)}.choropleth-header[data-v-7bd9e073]{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-7bd9e073]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-7bd9e073]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-7bd9e073]{font-weight:600}.choropleth-legend-item[data-v-7bd9e073]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-7bd9e073]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-7bd9e073]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-7bd9e073]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-7bd9e073]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-7bd9e073]{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-21721f41]{display:inline-block;position:relative}.TableOuter.full-width[data-v-21721f41]{display:block}.TableWrapper[data-v-21721f41]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-21721f41]{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-21721f41]{width:100%}.Table tr[data-v-21721f41],.Table th[data-v-21721f41],.Table td[data-v-21721f41]{background:0 0;border:none}.Table th[data-v-21721f41],.Table td[data-v-21721f41]{white-space:nowrap;text-overflow:ellipsis;text-align:left;padding:.75em 1.25em;overflow:hidden}.Table th.cell-wrap[data-v-21721f41],.Table td.cell-wrap[data-v-21721f41]{white-space:normal;text-overflow:clip;overflow:visible}.Table th[data-v-21721f41]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-21721f41]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-21721f41]{border-bottom:none}.TableOuter[data-v-21721f41] .chart-menu-trigger-area{top:4px;right:4px}.TableOuter[data-v-21721f41] .chart-menu-button{opacity:1}.TableOuter.has-menu .Table thead th[data-v-21721f41]: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}.choropleth-wrapper[data-v-c62cdd12]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative}.choropleth-wrapper svg[data-v-c62cdd12]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-c62cdd12]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-c62cdd12]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-c62cdd12]:active{cursor:grabbing}.state-path[data-v-c62cdd12]{cursor:pointer}.choropleth-zoom-hint[data-v-c62cdd12]{text-align:center;color:var(--color-text-secondary,#777);opacity:.6;pointer-events:none;padding-top:6px;font-size:12px;line-height:1.4;position:absolute;left:0;right:0}.choropleth-header[data-v-c62cdd12]{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-c62cdd12]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-c62cdd12]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-c62cdd12]{font-weight:600}.choropleth-legend[data-v-c62cdd12]:has(.choropleth-legend-continuous){align-items:flex-start}.choropleth-legend:has(.choropleth-legend-continuous) .choropleth-legend-title[data-v-c62cdd12]{line-height:12px}.choropleth-legend-item[data-v-c62cdd12]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-c62cdd12]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-c62cdd12]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-c62cdd12]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-c62cdd12]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-c62cdd12]{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*/