@cfasim-ui/charts 0.7.6 → 0.7.8

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.
@@ -2,6 +2,7 @@ import { nextTick } from 'vue';
2
2
  import { Topology } from 'topojson-specification';
3
3
  import { NumberFormat } from '@cfasim-ui/shared';
4
4
  import { TitleStyle, LabelStyle } from '../_shared/index.js';
5
+ import { CityMarker } from './cityLayout.js';
5
6
  export type GeoType = "states" | "counties" | "hsas";
6
7
  export interface StateData {
7
8
  /** FIPS code (e.g. "06" for California, "04015" for a county) or name */
@@ -87,9 +88,9 @@ type __VLS_Props = {
87
88
  * overhang so the contiguous US fills more of the frame. `false`/`0`
88
89
  * (default) fits every region into view; `true`/`1` fits the lower-48 to
89
90
  * the frame and lets Alaska's western tail (and Hawaii) clip into the
90
- * lower-left corner. A number in between (e.g. `0.5`) crops partway. No
91
- * effect in single-state mode or on a national HSA map (HSA ids aren't
92
- * FIPS, so AK/HI can't be split out).
91
+ * lower-left corner. A number in between (e.g. `0.5`) crops partway.
92
+ * Applies to national states, counties, and HSA maps; no effect in
93
+ * single-state mode.
93
94
  */
94
95
  tightFit?: boolean | number;
95
96
  colorScale?: ChoroplethColorScale | ThresholdStop[] | CategoricalStop[];
@@ -187,8 +188,8 @@ type __VLS_Props = {
187
188
  tooltipValueFormat?: NumberFormat;
188
189
  /**
189
190
  * Boundary for tooltip flip/clamp. `"none"` always places to the right of
190
- * the pointer with no clamping. `"chart"` (default) uses the map
191
- * container's bounding box. `"window"` uses the viewport.
191
+ * the pointer with no clamping. `"chart"` uses the map container's
192
+ * bounding box. `"window"` (default) uses the viewport.
192
193
  */
193
194
  tooltipClamp?: "none" | "chart" | "window";
194
195
  /**
@@ -235,6 +236,28 @@ type __VLS_Props = {
235
236
  * doesn't mount at the document root.
236
237
  */
237
238
  fullscreenTarget?: string | HTMLElement;
239
+ /**
240
+ * Optional decorative overlay of city markers, each `{ name,
241
+ * coordinates: [lng, lat], capital? }`. Every city is a dot; `capital`
242
+ * cities take first pick when labels would collide and are never dropped
243
+ * (their label is lightly emphasized). Any non-capital label that can't be
244
+ * placed without overlapping is dropped (its dot stays). Purely visual:
245
+ * the markers don't capture pointer events, so the choropleth's own
246
+ * hover/click is unaffected. The `@cfasim-ui/charts/us-cities` subpath
247
+ * ships a ready-made US dataset with `nationalCityMarkers()` /
248
+ * `stateCityMarkers()` helpers.
249
+ */
250
+ cities?: CityMarker[];
251
+ /**
252
+ * Default minimum zoom scale for `cities` that don't set their own
253
+ * `minZoom`, so they act as a zoom-in detail layer. Default `2` (one zoom
254
+ * level = 2×): such markers stay hidden until the user zooms in one level.
255
+ * Set to `1` to show them from the start. Per-city `minZoom` overrides this
256
+ * (level-of-detail: reveal more cities as you zoom in). Only applies when
257
+ * `zoom` is enabled — a static map has no way to zoom, so its `cities`
258
+ * always show.
259
+ */
260
+ citiesMinZoom?: number;
238
261
  };
239
262
  type ChoroplethFeature = GeoJSON.Feature<GeoJSON.Geometry | null, {
240
263
  name?: string;
@@ -260,6 +283,8 @@ declare function __VLS_template(): {
260
283
  mapGroupRef: SVGGElement;
261
284
  baseGroupRef: SVGGElement;
262
285
  overlayGroupRef: SVGGElement;
286
+ cityOverlayRef: SVGSVGElement;
287
+ cityLayerRef: SVGGElement;
263
288
  tooltipChildRef: ({
264
289
  $: import('vue').ComponentInternalInstance;
265
290
  $data: {};
@@ -376,6 +401,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
376
401
  focusZoomLevel: number;
377
402
  focusZoom: boolean;
378
403
  renderer: "svg" | "canvas";
404
+ citiesMinZoom: number;
379
405
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
380
406
  containerRef: HTMLDivElement;
381
407
  canvasRef: HTMLCanvasElement;
@@ -383,6 +409,8 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
383
409
  mapGroupRef: SVGGElement;
384
410
  baseGroupRef: SVGGElement;
385
411
  overlayGroupRef: SVGGElement;
412
+ cityOverlayRef: SVGSVGElement;
413
+ cityLayerRef: SVGGElement;
386
414
  tooltipChildRef: ({
387
415
  $: import('vue').ComponentInternalInstance;
388
416
  $data: {};
@@ -59,7 +59,14 @@ export declare function buildScene(features: Array<{
59
59
  /** Live hover highlight, drawn by the display frame on top of the blitted
60
60
  * base (focused features are already highlighted in the base itself). */
61
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). */
62
+ /**
63
+ * Everything but the transient hover: clear, fills, outlines, borders, focus
64
+ * highlights, overlays. Split out so the component can cache this to an
65
+ * offscreen canvas and, on a hover-only change, blit it back + redraw the one
66
+ * highlight instead of re-filling every feature.
67
+ */
68
+ export declare function drawBase(ctx: CanvasRenderingContext2D, scene: CanvasScene, view: CanvasView, state: CanvasDrawState): void;
69
+ /** One-shot full repaint: the base pass plus the hover highlight on top. */
63
70
  export declare function drawScene(ctx: CanvasRenderingContext2D, scene: CanvasScene, view: CanvasView, state: CanvasDrawState): void;
64
71
  /** Unique fill color for feature index `i` on the picking canvas. */
65
72
  export declare function indexToColor(i: number): string;
@@ -0,0 +1,89 @@
1
+ /** A city to render. `coordinates` is `[longitude, latitude]`. */
2
+ export interface CityMarker {
3
+ name: string;
4
+ coordinates: [number, number];
5
+ /**
6
+ * Mark as a capital: the label gets first pick during placement and is never
7
+ * dropped for collisions (rendered slightly emphasized). The marker itself is
8
+ * a plain dot, same as any other city.
9
+ */
10
+ capital?: boolean;
11
+ /**
12
+ * Minimum zoom scale at which this city appears (level-of-detail): it shows
13
+ * only once the map is zoomed to `scaleK >= minZoom`. Lets you reveal the
14
+ * biggest cities first and progressively add more as the user zooms in.
15
+ * Falls back to the map's `citiesMinZoom` prop when unset. Only applies on a
16
+ * zoomable map. See `nationalCityMarkers` / `stateCityMarkers`, which assign
17
+ * tiers by population.
18
+ */
19
+ minZoom?: number;
20
+ }
21
+ /** A resolved label anchor in canonical coordinates. */
22
+ export interface PlacedLabel {
23
+ /** Anchor x (interpretation depends on `anchor`). */
24
+ x: number;
25
+ /** Vertical center of the text (render with `dominant-baseline: central`). */
26
+ y: number;
27
+ anchor: "start" | "middle" | "end";
28
+ }
29
+ /** A city resolved to canonical coordinates, with an optional placed label. */
30
+ export interface PlacedCity {
31
+ name: string;
32
+ capital: boolean;
33
+ /** Dot/star center. */
34
+ x: number;
35
+ y: number;
36
+ /** Marker radius in canonical units. */
37
+ radius: number;
38
+ /** Null when no non-overlapping label position was found. */
39
+ label: PlacedLabel | null;
40
+ }
41
+ /** d3-zoom-style transform: `screen = k * point + [x, y]`. */
42
+ export interface ZoomTransformLike {
43
+ k: number;
44
+ x: number;
45
+ y: number;
46
+ }
47
+ export interface LayoutOptions {
48
+ /** Canonical viewport width (e.g. 1000). */
49
+ width: number;
50
+ /** Canonical viewport height. */
51
+ height: number;
52
+ /** Rendered px per canonical unit; converts px sizes into canonical units. */
53
+ viewScale: number;
54
+ /** Label font size in px. */
55
+ labelPx?: number;
56
+ /** Dot radius in px (capitals render larger, see CAPITAL_SCALE). */
57
+ dotPx?: number;
58
+ /** Gap between marker edge and label in px. */
59
+ gapPx?: number;
60
+ /** How far outside the viewport (canonical units) a dot may sit and still
61
+ * render. Cities beyond this are culled. */
62
+ margin?: number;
63
+ }
64
+ /** An axis-aligned bounding box in canonical coordinates. */
65
+ export interface LabelRect {
66
+ x0: number;
67
+ y0: number;
68
+ x1: number;
69
+ y1: number;
70
+ }
71
+ /** Rough label width in px (no DOM measurement). */
72
+ export declare function estimateTextWidth(text: string, fontPx: number): number;
73
+ /** True when two axis-aligned boxes overlap (shared edges don't count). */
74
+ export declare function rectsOverlap(a: LabelRect, b: LabelRect): boolean;
75
+ /**
76
+ * The canonical bounding box of a placed label, or null if it has none. Uses
77
+ * the same width/height model as the layout, so callers can reason about label
78
+ * extents (e.g. tests asserting non-overlap).
79
+ */
80
+ export declare function placedLabelBox(placed: PlacedCity, opts: {
81
+ labelPx?: number;
82
+ viewScale: number;
83
+ }): LabelRect | null;
84
+ /**
85
+ * Project + place cities. Returns one `PlacedCity` per city that projects
86
+ * inside the (margin-expanded) viewport, in draw order. `label` is null when no
87
+ * candidate anchor avoided every already-placed label and every dot.
88
+ */
89
+ export declare function layoutCities(cities: readonly CityMarker[], project: (lngLat: [number, number]) => [number, number] | null, transform: ZoomTransformLike | undefined, options: LayoutOptions): PlacedCity[];
@@ -0,0 +1 @@
1
+ export {};
@@ -72,6 +72,13 @@ export interface Area {
72
72
  x?: LineChartXInput;
73
73
  color?: string;
74
74
  opacity?: number;
75
+ /** Label shown in the inline legend. */
76
+ legend?: string;
77
+ /**
78
+ * Whether this area appears in the inline legend. Defaults to true.
79
+ * Has no effect when `legend` is unset.
80
+ */
81
+ showInLegend?: boolean;
75
82
  /**
76
83
  * CSS `mix-blend-mode` applied to the area fill. Lets overlapping
77
84
  * areas (e.g. confidence bands) combine their colors instead of one
@@ -108,7 +108,7 @@ export interface ChartCommonProps {
108
108
  tooltipData?: ArrayLike<unknown>;
109
109
  /** Tooltip activation mode. */
110
110
  tooltipTrigger?: "hover" | "click";
111
- /** Boundary for tooltip flip/clamp. Default: `"chart"`. */
111
+ /** Boundary for tooltip flip/clamp. Default: `"window"`. */
112
112
  tooltipClamp?: "none" | "chart" | "window";
113
113
  /**
114
114
  * Formatter for numeric values shown in the default tooltip. Accepts a
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}.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-4954204d]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative;container-type:inline-size}.choropleth-wrapper svg[data-v-4954204d]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-4954204d]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-4954204d]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-4954204d]:active{cursor:grabbing}.state-path[data-v-4954204d]{cursor:pointer}.choropleth-canvas[data-v-4954204d]{pointer-events:none;will-change:transform;position:absolute;top:0;left:0}.choropleth-zoom-hint[data-v-4954204d]{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-4954204d]{padding:0;position:static}}.choropleth-header[data-v-4954204d]{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-4954204d]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-4954204d]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-4954204d]{font-weight:600}.choropleth-legend[data-v-4954204d]:has(.choropleth-legend-continuous){align-items:flex-start}.choropleth-legend:has(.choropleth-legend-continuous) .choropleth-legend-title[data-v-4954204d]{line-height:12px}.choropleth-legend-item[data-v-4954204d]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-4954204d]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-4954204d]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-4954204d]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-4954204d]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-4954204d]{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-a11696bb]{width:100%;position:relative}.line-chart-tooltip-label[data-v-a11696bb]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-a11696bb]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-a11696bb]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-a11696bb]{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-32872fa4]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-32872fa4]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-32872fa4]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-32872fa4]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-32872fa4]{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-529f8dad]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative;container-type:inline-size}.choropleth-wrapper svg[data-v-529f8dad]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-529f8dad]{cursor:grab}.choropleth-wrapper.is-fullscreen svg[data-v-529f8dad]{flex:auto;width:100%;height:100%;min-height:0}.choropleth-wrapper.pannable svg[data-v-529f8dad]:active{cursor:grabbing}.state-path[data-v-529f8dad]{cursor:pointer}.choropleth-city-overlay[data-v-529f8dad]{pointer-events:none;position:absolute;top:0;left:0}.choropleth-cities[data-v-529f8dad]{--choropleth-city-marker:var(--lightningcss-light,#1a1a1a)var(--lightningcss-dark,#f2f2f2);--choropleth-city-halo:var(--lightningcss-light,#fff)var(--lightningcss-dark,#0a0a0a);--choropleth-city-label-color:var(--lightningcss-light,#1a1a1a)var(--lightningcss-dark,#f2f2f2);font-family:var(--font-family,system-ui, sans-serif)}.choropleth-city-dot[data-v-529f8dad]{fill:var(--choropleth-city-marker);stroke:var(--choropleth-city-halo)}.choropleth-city-label[data-v-529f8dad]{fill:var(--choropleth-city-label-color);stroke:var(--choropleth-city-halo);paint-order:stroke fill;stroke-linejoin:round;font-weight:500}.choropleth-city-label-capital[data-v-529f8dad]{font-weight:700}.choropleth-canvas[data-v-529f8dad]{pointer-events:none;will-change:transform;position:absolute;top:0;left:0}.choropleth-zoom-hint[data-v-529f8dad]{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-529f8dad]{padding:0;position:static}}.choropleth-header[data-v-529f8dad]{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-529f8dad]{white-space:pre-line;font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-529f8dad]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-529f8dad]{font-weight:600}.choropleth-legend[data-v-529f8dad]:has(.choropleth-legend-continuous){align-items:flex-start}.choropleth-legend:has(.choropleth-legend-continuous) .choropleth-legend-title[data-v-529f8dad]{line-height:12px}.choropleth-legend-item[data-v-529f8dad]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-529f8dad]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-529f8dad]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-529f8dad]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-529f8dad]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-529f8dad]{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*/
package/dist/index.d.ts CHANGED
@@ -3,5 +3,6 @@ export { default as BarChart, type BarChartData, type BarSeries, type BarSummary
3
3
  export { default as ChoroplethMap, type GeoType, type StateData, type ChoroplethColorScale, type ThresholdStop, type CategoricalStop, type FocusItem, type FocusValue, type FocusStyle, } from './ChoroplethMap/ChoroplethMap';
4
4
  export { default as ChartTooltip } from './ChartTooltip/ChartTooltip';
5
5
  export { default as DataTable, type TableData, type TableRecord, type ColumnAlign, type ColumnConfig, type ColumnWidth, } from './DataTable/DataTable';
6
+ export type { CityMarker, PlacedCity } from './ChoroplethMap/cityLayout.js';
6
7
  export type { ChartAnnotation } from './_shared/annotations.js';
7
8
  export type { BlendMode, LineMarkStyle } from './_shared/chartProps.js';