@cfasim-ui/charts 0.5.1 → 0.6.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.
@@ -244,7 +244,7 @@ declare function __VLS_template(): {
244
244
  svgRef: SVGSVGElement;
245
245
  tooltipRef: HTMLDivElement;
246
246
  };
247
- rootEl: HTMLDivElement;
247
+ rootEl: any;
248
248
  };
249
249
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
250
250
  declare const __VLS_component: import('vue').DefineComponent<BarChartProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
@@ -266,7 +266,7 @@ declare const __VLS_component: import('vue').DefineComponent<BarChartProps, {},
266
266
  containerRef: HTMLDivElement;
267
267
  svgRef: SVGSVGElement;
268
268
  tooltipRef: HTMLDivElement;
269
- }, HTMLDivElement>;
269
+ }, any>;
270
270
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
271
271
  export default _default;
272
272
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -8,8 +8,18 @@ type __VLS_Props = {
8
8
  items: ChartMenuItem[];
9
9
  /** Force the dropdown style even when only one item is provided. */
10
10
  forceDropdown?: boolean;
11
+ /**
12
+ * When the chart is expanded, the menu trigger is replaced by a
13
+ * persistent close (✕) button that emits `close`.
14
+ */
15
+ isFullscreen?: boolean;
11
16
  };
12
- declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
18
+ close: () => any;
19
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
20
+ onClose?: (() => any) | undefined;
21
+ }>, {
13
22
  forceDropdown: boolean;
23
+ isFullscreen: boolean;
14
24
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
15
25
  export default _default;
@@ -133,6 +133,15 @@ type __VLS_Props = {
133
133
  focus?: FocusValue;
134
134
  /** Scale factor applied when `focus` is set. Default: 4 */
135
135
  focusZoomLevel?: number;
136
+ /**
137
+ * Where to teleport the map while expanded (the Expand menu item). A
138
+ * CSS selector or element; defaults to `body`. Moving it to the
139
+ * document root keeps `position: fixed` resolving against the viewport
140
+ * instead of being trapped by an ancestor's `transform`/`filter`/
141
+ * `contain`/`perspective` or stacking context. Set this when your app
142
+ * doesn't mount at the document root.
143
+ */
144
+ fullscreenTarget?: string | HTMLElement;
136
145
  };
137
146
  type ChoroplethFeature = GeoJSON.Feature<GeoJSON.Geometry | null, {
138
147
  name?: string;
@@ -209,7 +218,7 @@ declare function __VLS_template(): {
209
218
  };
210
219
  }) | null;
211
220
  };
212
- rootEl: HTMLDivElement;
221
+ rootEl: any;
213
222
  };
214
223
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
215
224
  declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
@@ -304,7 +313,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
304
313
  default?(props: import('./ChoroplethTooltip').ChoroplethTooltipData): unknown;
305
314
  };
306
315
  }) | null;
307
- }, HTMLDivElement>;
316
+ }, any>;
308
317
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
309
318
  export default _default;
310
319
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -46,6 +46,17 @@ export interface Series extends LineMarkStyle {
46
46
  * effect when `line` is `false`.
47
47
  */
48
48
  outline?: boolean;
49
+ /**
50
+ * Outline stroke color. Defaults to the page background
51
+ * (`var(--color-bg-0, #fff)`). Only applies when `outline` is true.
52
+ */
53
+ outlineColor?: string;
54
+ /**
55
+ * Total extra width added to the line's `strokeWidth` for the outline
56
+ * (split evenly on each side). Defaults to `4`. Only applies when
57
+ * `outline` is true.
58
+ */
59
+ outlineWidth?: number;
49
60
  dotFill?: string;
50
61
  dotStroke?: string;
51
62
  /**
@@ -184,7 +195,7 @@ declare function __VLS_template(): {
184
195
  svgRef: SVGSVGElement;
185
196
  tooltipRef: HTMLDivElement;
186
197
  };
187
- rootEl: HTMLDivElement;
198
+ rootEl: any;
188
199
  };
189
200
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
190
201
  declare const __VLS_component: import('vue').DefineComponent<LineChartProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
@@ -200,7 +211,7 @@ declare const __VLS_component: import('vue').DefineComponent<LineChartProps, {},
200
211
  containerRef: HTMLDivElement;
201
212
  svgRef: SVGSVGElement;
202
213
  tooltipRef: HTMLDivElement;
203
- }, HTMLDivElement>;
214
+ }, any>;
204
215
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
205
216
  export default _default;
206
217
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -121,6 +121,16 @@ export interface ChartCommonProps {
121
121
  * are set, `downloadButton` wins.
122
122
  */
123
123
  downloadButton?: boolean | string;
124
+ /**
125
+ * Where to teleport the chart while expanded (the Expand menu item). A
126
+ * CSS selector or element; defaults to `body`. The expanded chart is
127
+ * moved here so its `position: fixed` resolves against the viewport
128
+ * instead of being trapped by an ancestor's `transform`/`filter`/
129
+ * `contain`/`perspective` (which would otherwise become its containing
130
+ * block) or stacking context. Set this when your app doesn't mount at
131
+ * the document root (e.g. inside a shadow root or a dedicated overlay).
132
+ */
133
+ fullscreenTarget?: string | HTMLElement;
124
134
  /** Annotations rendered as the top layer of the chart. */
125
135
  annotations?: readonly ChartAnnotation[];
126
136
  /**
@@ -16,6 +16,7 @@ export interface ChartFoundationOptions {
16
16
  filename: () => string | undefined;
17
17
  downloadLink: () => boolean | string | undefined;
18
18
  downloadButton: () => boolean | string | undefined;
19
+ fullscreenTarget: () => string | HTMLElement | undefined;
19
20
  chartPadding: () => ChartPadding | undefined;
20
21
  /**
21
22
  * Labels for the inline legend in render order. Empty array = no
@@ -29,6 +30,12 @@ export interface ChartFoundationOptions {
29
30
  onHover: (payload: {
30
31
  index: number;
31
32
  } | null) => void;
33
+ /**
34
+ * Axis a finger drags along to scrub the tooltip on touch; the
35
+ * orthogonal direction is left to the browser for page scrolling.
36
+ * Defaults to `"x"`.
37
+ */
38
+ scrubAxis?: () => "x" | "y";
32
39
  /**
33
40
  * Extra height (in px) the chart adds *below* the SVG plot area
34
41
  * (e.g. LineChart's area-section labels). Used to keep the SVG total
@@ -95,6 +102,9 @@ export declare function useChartFoundation(opts: ChartFoundationOptions): {
95
102
  triggerCsvDownload: () => void;
96
103
  menuFilename: () => string;
97
104
  isFullscreen: import('vue').Ref<boolean, boolean>;
105
+ fullscreenStyle: import('vue').ComputedRef<Record<string, string> | undefined>;
106
+ teleportTarget: import('vue').ComputedRef<string | HTMLElement>;
107
+ exitFullscreen: () => void;
98
108
  measuredHeight: import('vue').Ref<number, number>;
99
109
  };
100
110
  /**
@@ -1,16 +1,40 @@
1
1
  import { ChartMenuItem } from '../ChartMenu/ChartMenu';
2
+ export interface ChartFullscreenOptions {
3
+ /**
4
+ * Reactive getter for where to teleport the expanded chart. A CSS
5
+ * selector or element; resolves to `"body"` when unset. Teleporting
6
+ * out to the document root is what makes `position: fixed` reliable:
7
+ * a `transform`/`filter`/`contain`/`perspective` on any ancestor would
8
+ * otherwise become the containing block and trap the "fullscreen" box
9
+ * inside it.
10
+ */
11
+ target?: () => string | HTMLElement | undefined;
12
+ }
2
13
  /**
3
- * Tracks whether the chart is in "expanded" mode (fills the window via
4
- * CSS). The browser Fullscreen API isn't used — the consumer wires a
5
- * `.is-fullscreen` class to its wrapper and the CSS handles positioning,
6
- * which avoids Fullscreen API restrictions (user-gesture requirement,
7
- * permission policy, iframe sandboxing) and keeps the chart inside the
8
- * document so the rest of the page remains keyboard-navigable.
14
+ * Tracks whether the chart is in "expanded" mode (fills the window). The
15
+ * browser Fullscreen API isn't used — avoiding its restrictions
16
+ * (user-gesture requirement, permission policy, iframe sandboxing) and
17
+ * keeping the chart inside the document so the rest of the page stays
18
+ * keyboard-navigable.
19
+ *
20
+ * Resilience is the whole point here, so the layout is driven two ways
21
+ * that don't depend on the CSS cascade:
22
+ * - `fullscreenStyle` returns the critical layout as an *inline* style
23
+ * object. Inline styles outrank any class rule regardless of stylesheet
24
+ * source order, so they beat each chart's scoped `position: relative`
25
+ * base rule (equal specificity, and the scoped rule often loads last)
26
+ * and still work even if the consumer never imported the package CSS.
27
+ * - `teleportTarget` moves the node to the document root so the fixed
28
+ * positioning resolves against the viewport, not a transformed ancestor.
29
+ * The `.is-fullscreen` class remains on the wrapper only as a hook for the
30
+ * one rule inline styles can't express (ChoroplethMap's SVG stretch).
9
31
  */
10
- export declare function useChartFullscreen(): {
32
+ export declare function useChartFullscreen(opts?: ChartFullscreenOptions): {
11
33
  isFullscreen: import('vue').Ref<boolean, boolean>;
12
34
  toggle: () => void;
13
35
  enter: () => void;
14
36
  exit: () => void;
15
37
  menuItem: import('vue').ComputedRef<ChartMenuItem>;
38
+ fullscreenStyle: import('vue').ComputedRef<Record<string, string> | undefined>;
39
+ teleportTarget: import('vue').ComputedRef<string | HTMLElement>;
16
40
  };
@@ -11,15 +11,17 @@ export interface ChartMenuOptions {
11
11
  /** Whether a separate download button is rendered (and the CSV menu item should be hidden). */
12
12
  downloadButton?: () => boolean | string | undefined;
13
13
  /**
14
- * When true, prepends an Expand/Collapse menu item that toggles the
15
- * chart into a full-window view. The consumer is responsible for
16
- * binding the returned `isFullscreen` ref to a CSS class on its
17
- * wrapper.
14
+ * When true, prepends a Fullscreen menu item that toggles the chart
15
+ * into a full-window view. The consumer binds the returned
16
+ * `isFullscreen` class plus `fullscreenStyle` to its wrapper and wraps
17
+ * it in a `<Teleport :to="teleportTarget" :disabled="!isFullscreen">`.
18
18
  */
19
19
  fullscreen?: boolean;
20
+ /** Forwarded to `useChartFullscreen` — see its `target` option. */
21
+ fullscreenTarget?: () => string | HTMLElement | undefined;
20
22
  }
21
23
  /**
22
- * Computes the standard chart menu items (Expand / SVG / PNG / CSV) plus
24
+ * Computes the standard chart menu items (Fullscreen / SVG / PNG / CSV) plus
23
25
  * the CSV-download-link state shared by every chart.
24
26
  */
25
27
  export declare function useChartMenu(opts: ChartMenuOptions): {
@@ -31,4 +33,7 @@ export declare function useChartMenu(opts: ChartMenuOptions): {
31
33
  triggerCsvDownload: () => void;
32
34
  resolvedFilename: () => string;
33
35
  isFullscreen: Ref<boolean, boolean>;
36
+ fullscreenStyle: import('vue').ComputedRef<Record<string, string> | undefined>;
37
+ teleportTarget: import('vue').ComputedRef<string | HTMLElement>;
38
+ exitFullscreen: () => void;
34
39
  };
@@ -18,6 +18,13 @@ export interface ChartTooltipOptions {
18
18
  containerRef: Ref<HTMLElement | null>;
19
19
  /** Pointer-vertical offset applied for touch interactions. */
20
20
  touchYOffset?: number;
21
+ /**
22
+ * Axis a finger drags *along* to scrub the tooltip. On touch, a drag in
23
+ * the orthogonal direction is left to the browser so the page can still
24
+ * scroll. Defaults to `"x"` (horizontal scrub, vertical page scroll) —
25
+ * correct for time-series line charts and vertical bar charts.
26
+ */
27
+ scrubAxis?: () => "x" | "y";
21
28
  /**
22
29
  * Emit hover events. The first arg is `{ index }` while hovering and
23
30
  * `null` when leaving.
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- .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,.line-chart-wrapper.is-fullscreen .chart-menu-button,.bar-chart-wrapper.is-fullscreen .chart-menu-button,.choropleth-wrapper.is-fullscreen .chart-menu-button{opacity:1}.line-chart-wrapper.is-fullscreen,.bar-chart-wrapper.is-fullscreen,.choropleth-wrapper.is-fullscreen{z-index:var(--cfasim-z-fullscreen,1000);background:var(--color-bg-0,#fff);color:var(--color-text,inherit);box-sizing:border-box;flex-direction:column;justify-content:center;padding:2em;display:flex;position:fixed;inset:0}.choropleth-wrapper.is-fullscreen svg{flex:auto;width:100%;height:100%;min-height:0}.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-trigger-area[data-v-c74e2889]{z-index:1;position:absolute;top:0;right:0}.chart-menu-button[data-v-c74e2889]{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-c74e2889]{opacity:1}.chart-menu-button[data-v-c74e2889]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.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-0d24242d]{width:100%;position:relative}.line-chart-tooltip-label[data-v-0d24242d]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-0d24242d]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-0d24242d]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-0d24242d]{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-59c746d2]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-59c746d2]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-59c746d2]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-59c746d2]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-59c746d2]{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-b11a80ed]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative}.choropleth-wrapper svg[data-v-b11a80ed]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-b11a80ed]{cursor:grab}.choropleth-wrapper.pannable svg[data-v-b11a80ed]:active{cursor:grabbing}.state-path[data-v-b11a80ed]{cursor:pointer}.choropleth-reset[data-v-b11a80ed]{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-b11a80ed]:hover{background:var(--color-bg-1,#f8f9fa);color:var(--color-text,#212529)}.choropleth-header[data-v-b11a80ed]{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-b11a80ed]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-b11a80ed]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-b11a80ed]{font-weight:600}.choropleth-legend-item[data-v-b11a80ed]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-b11a80ed]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-b11a80ed]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-b11a80ed]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-b11a80ed]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-b11a80ed]{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}.line-chart-wrapper[data-v-70eeecc9]{width:100%;position:relative}.line-chart-tooltip-label[data-v-70eeecc9]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-70eeecc9]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-70eeecc9]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-70eeecc9]{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-67594e38]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-67594e38]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-67594e38]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-67594e38]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-67594e38]{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-96a5f36e]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative}.choropleth-wrapper svg[data-v-96a5f36e]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-96a5f36e]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-96a5f36e]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-96a5f36e]:active{cursor:grabbing}.state-path[data-v-96a5f36e]{cursor:pointer}.choropleth-reset[data-v-96a5f36e]{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-96a5f36e]:hover{background:var(--color-bg-1,#f8f9fa);color:var(--color-text,#212529)}.choropleth-header[data-v-96a5f36e]{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-96a5f36e]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-96a5f36e]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-96a5f36e]{font-weight:600}.choropleth-legend-item[data-v-96a5f36e]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-96a5f36e]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-96a5f36e]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-96a5f36e]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-96a5f36e]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-96a5f36e]{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}
2
2
  /*$vite$:1*/