queria 0.0.0 → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +57 -1
- package/dist/boot.d.ts +24 -0
- package/dist/boot.js +137 -0
- package/dist/boot.js.map +1 -0
- package/dist/client.d.ts +56 -0
- package/dist/client.js +194 -0
- package/dist/client.js.map +1 -0
- package/dist/elements/define.d.ts +1 -0
- package/dist/elements/define.js +4 -0
- package/dist/elements/define.js.map +1 -0
- package/dist/elements/index.d.ts +40 -0
- package/dist/elements/index.js +144 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/react/Chart.d.ts +12 -0
- package/dist/react/Chart.js +42 -0
- package/dist/react/Chart.js.map +1 -0
- package/dist/react/DataMap.d.ts +12 -0
- package/dist/react/DataMap.js +44 -0
- package/dist/react/DataMap.js.map +1 -0
- package/dist/react/MapView.d.ts +13 -0
- package/dist/react/MapView.js +31 -0
- package/dist/react/MapView.js.map +1 -0
- package/dist/react/PoweredBy.d.ts +2 -0
- package/dist/react/PoweredBy.js +5 -0
- package/dist/react/PoweredBy.js.map +1 -0
- package/dist/react/index.d.ts +5 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/query.d.ts +20 -0
- package/dist/react/query.js +50 -0
- package/dist/react/query.js.map +1 -0
- package/dist/render/attribution.d.ts +6 -0
- package/dist/render/attribution.js +17 -0
- package/dist/render/attribution.js.map +1 -0
- package/dist/render/chart.d.ts +27 -0
- package/dist/render/chart.js +50 -0
- package/dist/render/chart.js.map +1 -0
- package/dist/render/data-map.d.ts +61 -0
- package/dist/render/data-map.js +200 -0
- package/dist/render/data-map.js.map +1 -0
- package/dist/render/escape.d.ts +2 -0
- package/dist/render/escape.js +4 -0
- package/dist/render/escape.js.map +1 -0
- package/dist/render/index.d.ts +5 -0
- package/dist/render/index.js +6 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/map.d.ts +7 -0
- package/dist/render/map.js +9 -0
- package/dist/render/map.js.map +1 -0
- package/dist/render/poweredBy.d.ts +2 -0
- package/dist/render/poweredBy.js +5 -0
- package/dist/render/poweredBy.js.map +1 -0
- package/dist/sql.d.ts +10 -0
- package/dist/sql.js +13 -0
- package/dist/sql.js.map +1 -0
- package/package.json +93 -1
- package/src/boot.test.ts +65 -0
- package/src/boot.ts +141 -0
- package/src/client.test.ts +77 -0
- package/src/client.ts +247 -0
- package/src/elements/define.ts +4 -0
- package/src/elements/index.ts +151 -0
- package/src/index.ts +12 -0
- package/src/react/Chart.tsx +49 -0
- package/src/react/DataMap.tsx +52 -0
- package/src/react/MapView.tsx +45 -0
- package/src/react/PoweredBy.tsx +4 -0
- package/src/react/index.ts +5 -0
- package/src/react/query.tsx +64 -0
- package/src/render/attribution.test.ts +22 -0
- package/src/render/attribution.ts +21 -0
- package/src/render/chart.test.ts +23 -0
- package/src/render/chart.ts +80 -0
- package/src/render/data-map.test.ts +40 -0
- package/src/render/data-map.ts +230 -0
- package/src/render/escape.ts +4 -0
- package/src/render/index.ts +12 -0
- package/src/render/map.ts +18 -0
- package/src/render/poweredBy.ts +6 -0
- package/src/sql.test.ts +21 -0
- package/src/sql.ts +19 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { GeoJSONSourceSpecification, Map as MapLibreMap, StyleSpecification } from "maplibre-gl";
|
|
2
|
+
import type { Rows } from "./chart.js";
|
|
3
|
+
export type AreaLevel = "prefecture" | "city" | "small_area";
|
|
4
|
+
/**
|
|
5
|
+
* How rows are put on the map: by area code (the shapes come from Queria's boundary tiles) or by longitude and latitude.
|
|
6
|
+
* The values are column names. `color` colors by a column, `label` names a row on hover.
|
|
7
|
+
*/
|
|
8
|
+
export type MapLayer = ({
|
|
9
|
+
area: AreaLevel;
|
|
10
|
+
code: string;
|
|
11
|
+
} | {
|
|
12
|
+
lng: string;
|
|
13
|
+
lat: string;
|
|
14
|
+
}) & {
|
|
15
|
+
color?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
opacity?: number;
|
|
18
|
+
};
|
|
19
|
+
/** Queria's map styles. They keep their URL when the tiles are rebuilt, and hold the boundary sources. */
|
|
20
|
+
export declare const MAP_STYLES: {
|
|
21
|
+
readonly light: "https://assets.queria.io/maps/v1/light.json";
|
|
22
|
+
readonly dark: "https://assets.queria.io/maps/v1/dark.json";
|
|
23
|
+
};
|
|
24
|
+
/** The style's source for each area level. */
|
|
25
|
+
export declare const boundarySource: (area: AreaLevel) => string;
|
|
26
|
+
/**
|
|
27
|
+
* Put a code into the form of the boundary tiles: restore leading zeros lost in numeric columns, and drop
|
|
28
|
+
* the check digit of a 6-digit local government code.
|
|
29
|
+
*/
|
|
30
|
+
export declare const areaCode: (area: AreaLevel, value: unknown) => string | null;
|
|
31
|
+
/**
|
|
32
|
+
* A color for each row. Numbers run from light to dark between the smallest and largest value;
|
|
33
|
+
* other values get one color each, in order of first appearance.
|
|
34
|
+
*/
|
|
35
|
+
export declare const colorsOf: (rows: Rows, column: string | undefined) => string[];
|
|
36
|
+
/** Points as GeoJSON. Rows without a valid position are left out. */
|
|
37
|
+
export declare const pointFeatures: (rows: Rows, layer: MapLayer & {
|
|
38
|
+
lng: string;
|
|
39
|
+
lat: string;
|
|
40
|
+
}) => GeoJSONSourceSpecification["data"];
|
|
41
|
+
/** Color and hover lines by area code. The first row of a code wins. */
|
|
42
|
+
export declare const areaRows: (rows: Rows, layer: MapLayer & {
|
|
43
|
+
area: AreaLevel;
|
|
44
|
+
code: string;
|
|
45
|
+
}) => Map<string, {
|
|
46
|
+
color: string;
|
|
47
|
+
hover: string;
|
|
48
|
+
}>;
|
|
49
|
+
export type MapRenderOptions = {
|
|
50
|
+
/** A MapLibre style or its URL. By default Queria's style, which has the boundary tiles. */
|
|
51
|
+
style?: StyleSpecification | string;
|
|
52
|
+
theme?: keyof typeof MAP_STYLES;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Draw rows on a MapLibre map. maplibre-gl is loaded on first use; include its CSS in your page.
|
|
56
|
+
* The map is fitted to the rows. Sources and licenses are not drawn here; the elements and React components add them.
|
|
57
|
+
*/
|
|
58
|
+
export declare const renderMap: (el: HTMLElement, layer: MapLayer, rows: Rows, { style, theme }?: MapRenderOptions) => Promise<{
|
|
59
|
+
map: MapLibreMap;
|
|
60
|
+
finalize: () => void;
|
|
61
|
+
}>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/** Queria's map styles. They keep their URL when the tiles are rebuilt, and hold the boundary sources. */
|
|
2
|
+
export const MAP_STYLES = {
|
|
3
|
+
light: "https://assets.queria.io/maps/v1/light.json",
|
|
4
|
+
dark: "https://assets.queria.io/maps/v1/dark.json",
|
|
5
|
+
};
|
|
6
|
+
/** The style's source for each area level. */
|
|
7
|
+
export const boundarySource = (area) => `queria-${area}`;
|
|
8
|
+
/**
|
|
9
|
+
* Put a code into the form of the boundary tiles: restore leading zeros lost in numeric columns, and drop
|
|
10
|
+
* the check digit of a 6-digit local government code.
|
|
11
|
+
*/
|
|
12
|
+
export const areaCode = (area, value) => {
|
|
13
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "bigint")
|
|
14
|
+
return null;
|
|
15
|
+
const text = String(value).trim();
|
|
16
|
+
if (text === "")
|
|
17
|
+
return null;
|
|
18
|
+
if (area === "small_area")
|
|
19
|
+
return text.length === 8 || text.length === 10 ? `0${text}` : text;
|
|
20
|
+
const digits = area === "prefecture" ? 2 : 5;
|
|
21
|
+
return text.length >= digits ? text.slice(0, digits) : text.padStart(digits, "0");
|
|
22
|
+
};
|
|
23
|
+
const BASE = "#2563eb";
|
|
24
|
+
const LOW = [219, 234, 254];
|
|
25
|
+
const HIGH = [29, 78, 216];
|
|
26
|
+
const CATEGORIES = ["#2563eb", "#ea580c", "#16a34a", "#dc2626", "#9333ea", "#0891b2", "#ca8a04", "#db2777", "#4b5563", "#65a30d"];
|
|
27
|
+
const hex = (rgb) => `#${rgb.map((c) => Math.round(c).toString(16).padStart(2, "0")).join("")}`;
|
|
28
|
+
/**
|
|
29
|
+
* A color for each row. Numbers run from light to dark between the smallest and largest value;
|
|
30
|
+
* other values get one color each, in order of first appearance.
|
|
31
|
+
*/
|
|
32
|
+
export const colorsOf = (rows, column) => {
|
|
33
|
+
if (column === undefined)
|
|
34
|
+
return rows.map(() => BASE);
|
|
35
|
+
const values = rows.map((r) => r[column]);
|
|
36
|
+
const nums = values.filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
37
|
+
if (nums.length > 0 && nums.length === values.filter((v) => v !== null && v !== undefined).length) {
|
|
38
|
+
// Spreading a large array into Math.min overflows the stack.
|
|
39
|
+
const min = nums.reduce((a, b) => Math.min(a, b));
|
|
40
|
+
const max = nums.reduce((a, b) => Math.max(a, b));
|
|
41
|
+
return values.map((v) => {
|
|
42
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
43
|
+
return "#d4d4d4";
|
|
44
|
+
const t = max === min ? 1 : (v - min) / (max - min);
|
|
45
|
+
return hex(LOW.map((l, i) => l + (HIGH[i] - l) * t));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const order = [...new Set(values.map(String))];
|
|
49
|
+
return values.map((v) => CATEGORIES[order.indexOf(String(v)) % CATEGORIES.length]);
|
|
50
|
+
};
|
|
51
|
+
/** Lines shown on hover: the label, then the colored value. */
|
|
52
|
+
const hoverLines = (row, layer) => [
|
|
53
|
+
layer.label === undefined ? null : String(row[layer.label] ?? ""),
|
|
54
|
+
layer.color === undefined ? null : `${layer.color}: ${typeof row[layer.color] === "number" ? row[layer.color].toLocaleString() : String(row[layer.color])}`,
|
|
55
|
+
].filter((l) => !!l);
|
|
56
|
+
const coordinate = (v) => typeof v === "number" ? v : typeof v === "string" && v.trim() !== "" ? Number(v) : Number.NaN;
|
|
57
|
+
/** The row's [lng, lat], or null when either is missing or not a number. */
|
|
58
|
+
const positionOf = (row, layer) => {
|
|
59
|
+
const [lng, lat] = [coordinate(row[layer.lng]), coordinate(row[layer.lat])];
|
|
60
|
+
return Number.isFinite(lng) && Number.isFinite(lat) ? [lng, lat] : null;
|
|
61
|
+
};
|
|
62
|
+
/** Points as GeoJSON. Rows without a valid position are left out. */
|
|
63
|
+
export const pointFeatures = (rows, layer) => {
|
|
64
|
+
const colors = colorsOf(rows, layer.color);
|
|
65
|
+
return {
|
|
66
|
+
type: "FeatureCollection",
|
|
67
|
+
features: rows.flatMap((r, i) => {
|
|
68
|
+
const position = positionOf(r, layer);
|
|
69
|
+
if (position === null)
|
|
70
|
+
return [];
|
|
71
|
+
return [{ type: "Feature", geometry: { type: "Point", coordinates: position }, properties: { color: colors[i], hover: hoverLines(r, layer).join("\n") } }];
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/** Color and hover lines by area code. The first row of a code wins. */
|
|
76
|
+
export const areaRows = (rows, layer) => {
|
|
77
|
+
const colors = colorsOf(rows, layer.color);
|
|
78
|
+
const out = new Map();
|
|
79
|
+
rows.forEach((r, i) => {
|
|
80
|
+
const code = areaCode(layer.area, r[layer.code]);
|
|
81
|
+
if (code !== null && !out.has(code))
|
|
82
|
+
out.set(code, { color: colors[i], hover: hoverLines(r, layer).join("\n") });
|
|
83
|
+
});
|
|
84
|
+
return out;
|
|
85
|
+
};
|
|
86
|
+
const union = (boxes) => boxes.length === 0
|
|
87
|
+
? null
|
|
88
|
+
: boxes.reduce((a, b) => [Math.min(a[0], b[0]), Math.min(a[1], b[1]), Math.max(a[2], b[2]), Math.max(a[3], b[3])]);
|
|
89
|
+
const bboxIndexes = new Map();
|
|
90
|
+
/** The bbox index at the URL, fetched once per page. */
|
|
91
|
+
const bboxIndex = (url) => {
|
|
92
|
+
const found = bboxIndexes.get(url);
|
|
93
|
+
if (found)
|
|
94
|
+
return found;
|
|
95
|
+
const p = fetch(url)
|
|
96
|
+
.then((res) => {
|
|
97
|
+
if (!res.ok)
|
|
98
|
+
throw new Error(`${url}: ${res.status}`);
|
|
99
|
+
return res.json();
|
|
100
|
+
})
|
|
101
|
+
.catch((e) => {
|
|
102
|
+
bboxIndexes.delete(url);
|
|
103
|
+
throw e;
|
|
104
|
+
});
|
|
105
|
+
bboxIndexes.set(url, p);
|
|
106
|
+
return p;
|
|
107
|
+
};
|
|
108
|
+
/** The bounds of the points, or of the areas from the style's bbox index (small areas use their city). */
|
|
109
|
+
const boundsOf = async (map, layer, rows, codes) => {
|
|
110
|
+
if ("lng" in layer) {
|
|
111
|
+
return union(rows.flatMap((r) => {
|
|
112
|
+
const p = positionOf(r, layer);
|
|
113
|
+
return p ? [[p[0], p[1], p[0], p[1]]] : [];
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
const url = map.getStyle().metadata?.["queria:bbox"];
|
|
117
|
+
if (typeof url !== "string")
|
|
118
|
+
return null;
|
|
119
|
+
const index = await bboxIndex(url);
|
|
120
|
+
return union(codes.flatMap((c) => {
|
|
121
|
+
const box = index[layer.area === "small_area" ? c.slice(0, 5) : c];
|
|
122
|
+
return box ? [box] : [];
|
|
123
|
+
}));
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Draw rows on a MapLibre map. maplibre-gl is loaded on first use; include its CSS in your page.
|
|
127
|
+
* The map is fitted to the rows. Sources and licenses are not drawn here; the elements and React components add them.
|
|
128
|
+
*/
|
|
129
|
+
export const renderMap = async (el, layer, rows, { style, theme = "light" } = {}) => {
|
|
130
|
+
const { default: maplibregl } = await import("maplibre-gl");
|
|
131
|
+
const map = new maplibregl.Map({ container: el, style: style ?? MAP_STYLES[theme], center: [137, 37], zoom: 4 });
|
|
132
|
+
try {
|
|
133
|
+
// An error before the style loads stops the map. Later errors, such as a tile or a sprite that fails to
|
|
134
|
+
// load, leave it drawing, and MapLibre logs them once no listener is left.
|
|
135
|
+
await new Promise((resolve, reject) => {
|
|
136
|
+
const fail = (e) => reject(e.error);
|
|
137
|
+
map.on("error", fail);
|
|
138
|
+
map.once("style.load", () => map.off("error", fail));
|
|
139
|
+
map.once("load", () => resolve());
|
|
140
|
+
});
|
|
141
|
+
// Areas go under the first label of the base map, so place names stay readable; points go on top.
|
|
142
|
+
const below = map.getStyle().layers.find((l) => l.type === "symbol")?.id;
|
|
143
|
+
const opacity = layer.opacity ?? ("lng" in layer ? 0.9 : 0.6);
|
|
144
|
+
let codes = [];
|
|
145
|
+
let hover;
|
|
146
|
+
if ("lng" in layer) {
|
|
147
|
+
map.addSource("queria-rows", { type: "geojson", data: pointFeatures(rows, layer) });
|
|
148
|
+
map.addLayer({
|
|
149
|
+
id: "queria-rows",
|
|
150
|
+
type: "circle",
|
|
151
|
+
source: "queria-rows",
|
|
152
|
+
paint: { "circle-radius": 4, "circle-color": ["get", "color"], "circle-opacity": opacity, "circle-stroke-width": 1, "circle-stroke-color": "#ffffff" },
|
|
153
|
+
});
|
|
154
|
+
hover = (f) => f.properties.hover;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const source = boundarySource(layer.area);
|
|
158
|
+
if (!map.getSource(source))
|
|
159
|
+
throw new Error(`The map style has no source "${source}". Use Queria's style to draw areas`);
|
|
160
|
+
const areas = areaRows(rows, layer);
|
|
161
|
+
codes = [...areas.keys()];
|
|
162
|
+
if (codes.length > 0)
|
|
163
|
+
map.addLayer({
|
|
164
|
+
id: "queria-rows",
|
|
165
|
+
type: "fill",
|
|
166
|
+
source,
|
|
167
|
+
"source-layer": layer.area,
|
|
168
|
+
// A match on a literal list is a lookup table; "in" would scan the list for every feature.
|
|
169
|
+
filter: ["match", ["get", "code"], codes, true, false],
|
|
170
|
+
paint: {
|
|
171
|
+
"fill-color": ["match", ["get", "code"], ...[...areas].flatMap(([c, a]) => [c, a.color]), "rgba(0,0,0,0)"],
|
|
172
|
+
"fill-opacity": opacity,
|
|
173
|
+
"fill-outline-color": "#ffffff",
|
|
174
|
+
},
|
|
175
|
+
}, below);
|
|
176
|
+
hover = (f) => areas.get(String(f.properties.code))?.hover;
|
|
177
|
+
}
|
|
178
|
+
const popup = new maplibregl.Popup({ closeButton: false, closeOnClick: false });
|
|
179
|
+
map.on("mousemove", "queria-rows", (e) => {
|
|
180
|
+
const text = e.features?.[0] ? hover(e.features[0]) : undefined;
|
|
181
|
+
if (!text)
|
|
182
|
+
return popup.remove();
|
|
183
|
+
// The text comes from the data, so it is set as text, never as HTML.
|
|
184
|
+
const body = document.createElement("div");
|
|
185
|
+
body.style.whiteSpace = "pre-line";
|
|
186
|
+
body.textContent = text;
|
|
187
|
+
popup.setLngLat(e.lngLat).setDOMContent(body).addTo(map);
|
|
188
|
+
});
|
|
189
|
+
map.on("mouseleave", "queria-rows", () => popup.remove());
|
|
190
|
+
const bounds = await boundsOf(map, layer, rows, codes).catch(() => null);
|
|
191
|
+
if (bounds)
|
|
192
|
+
map.fitBounds(bounds, { padding: 24, maxZoom: 14, duration: 0 });
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
map.remove();
|
|
196
|
+
throw e;
|
|
197
|
+
}
|
|
198
|
+
return { map, finalize: () => map.remove() };
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=data-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-map.js","sourceRoot":"","sources":["../../src/render/data-map.ts"],"names":[],"mappings":"AAeA,0GAA0G;AAC1G,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,6CAA6C;IACpD,IAAI,EAAE,4CAA4C;CAC1C,CAAC;AAEX,8CAA8C;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAe,EAAU,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAe,EAAE,KAAc,EAAiB,EAAE;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACrG,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9F,MAAM,MAAM,GAAG,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACpF,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5B,MAAM,IAAI,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;AAC3B,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAElI,MAAM,GAAG,GAAG,CAAC,GAAa,EAAU,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AAElH;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAE,MAA0B,EAAY,EAAE;IAC3E,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;QAClG,6DAA6D;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,SAAS,CAAC;YACnE,MAAM,CAAC,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;YACpD,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF,+DAA+D;AAC/D,MAAM,UAAU,GAAG,CAAC,GAA4B,EAAE,KAAe,EAAY,EAAE,CAC7E;IACE,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACjE,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,KAAK,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAG,CAAC,KAAK,CAAC,KAAK,CAAY,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE;CACxK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpC,MAAM,UAAU,GAAG,CAAC,CAAU,EAAU,EAAE,CACxC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AAEhG,4EAA4E;AAC5E,MAAM,UAAU,GAAG,CAAC,GAA4B,EAAE,KAAmC,EAA2B,EAAE;IAChH,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC,CAAC;AAEF,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAU,EAAE,KAA8C,EAAsC,EAAE;IAC9H,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACtC,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YACjC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAkB,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/K,CAAC,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAEF,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAE,KAAmD,EAAiD,EAAE;IACzI,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAA4C,CAAC;IAChE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnH,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAIF,MAAM,KAAK,GAAG,CAAC,KAAa,EAAe,EAAE,CAC3C,KAAK,CAAC,MAAM,KAAK,CAAC;IAChB,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvH,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyC,CAAC;AAErE,wDAAwD;AACxD,MAAM,SAAS,GAAG,CAAC,GAAW,EAAiC,EAAE;IAC/D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;SACjB,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,OAAO,GAAG,CAAC,IAAI,EAAmC,CAAC;IACrD,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;QACpB,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,MAAM,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IACL,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,0GAA0G;AAC1G,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAgB,EAAE,KAAe,EAAE,IAAU,EAAE,KAAe,EAAwB,EAAE;IAC9G,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAU,EAAE;YACtC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAC/B,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,CAAC,CAAC,CAAC,CAAC;IACN,CAAC;IACD,MAAM,GAAG,GAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAgD,EAAE,CAAC,aAAa,CAAC,CAAC;IAC9F,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAU,EAAE;QACrC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC,CAAC;AACR,CAAC,CAAC;AAQF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,EAAe,EACf,KAAe,EACf,IAAU,EACV,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,KAAuB,EAAE,EACI,EAAE;IACvD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACjH,IAAI,CAAC;QACH,wGAAwG;QACxG,2EAA2E;QAC3E,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAG,CAAC,CAAmB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACtD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YACrD,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACH,kGAAkG;QAClG,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,EAAE,CAAC;QACzE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9D,IAAI,KAAK,GAAa,EAAE,CAAC;QACzB,IAAI,KAAyE,CAAC;QAC9E,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;YACnB,GAAG,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACpF,GAAG,CAAC,QAAQ,CAAC;gBACX,EAAE,EAAE,aAAa;gBACjB,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,EAAE,qBAAqB,EAAE,SAAS,EAAE;aACvJ,CAAC,CAAC;YACH,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAA2B,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,qCAAqC,CAAC,CAAC;YACzH,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACpC,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAClB,GAAG,CAAC,QAAQ,CAAC;oBACX,EAAE,EAAE,aAAa;oBACjB,IAAI,EAAE,MAAM;oBACZ,MAAM;oBACN,cAAc,EAAE,KAAK,CAAC,IAAI;oBAC1B,2FAA2F;oBAC3F,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;oBACtD,KAAK,EAAE;wBACL,YAAY,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAsB;wBAC/H,cAAc,EAAE,OAAO;wBACvB,oBAAoB,EAAE,SAAS;qBAChC;iBACF,EAAE,KAAK,CAAC,CAAC;YACZ,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC;QAC7D,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;YACvC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChE,IAAI,CAAC,IAAI;gBAAE,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,qEAAqE;YACrE,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;YACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACzE,IAAI,MAAM;YAAE,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,CAAC,CAAC;IACV,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;AAC/C,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/render/escape.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAA2B,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAEjH,iDAAiD;AACjD,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { attributionHtml } from "./attribution.js";
|
|
2
|
+
export { renderChart, withData, type ChartOptions, type ChartSpec, type Rows } from "./chart.js";
|
|
3
|
+
export { mountMap, type MapHandle } from "./map.js";
|
|
4
|
+
export { poweredByHtml } from "./poweredBy.js";
|
|
5
|
+
export { areaCode, MAP_STYLES, renderMap, type AreaLevel, type MapLayer, type MapRenderOptions, } from "./data-map.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { attributionHtml } from "./attribution.js";
|
|
2
|
+
export { renderChart, withData } from "./chart.js";
|
|
3
|
+
export { mountMap } from "./map.js";
|
|
4
|
+
export { poweredByHtml } from "./poweredBy.js";
|
|
5
|
+
export { areaCode, MAP_STYLES, renderMap, } from "./data-map.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAgD,MAAM,YAAY,CAAC;AACjG,OAAO,EAAE,QAAQ,EAAkB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,UAAU,EACV,SAAS,GAIV,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Map, MapOptions, StyleSpecification } from "maplibre-gl";
|
|
2
|
+
export type MapHandle = {
|
|
3
|
+
map: Promise<Map>;
|
|
4
|
+
destroy: () => void;
|
|
5
|
+
};
|
|
6
|
+
/** Create a MapLibre map in an element. maplibre-gl is loaded on first use; include its CSS in your page. */
|
|
7
|
+
export declare const mountMap: (el: HTMLElement, style: StyleSpecification | string, options?: Omit<MapOptions, "container" | "style">) => MapHandle;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Create a MapLibre map in an element. maplibre-gl is loaded on first use; include its CSS in your page. */
|
|
2
|
+
export const mountMap = (el, style, options = {}) => {
|
|
3
|
+
const map = import("maplibre-gl").then(({ default: maplibregl }) => new maplibregl.Map({ container: el, style, ...options }));
|
|
4
|
+
const destroy = () => {
|
|
5
|
+
map.then((m) => m.remove(), console.error);
|
|
6
|
+
};
|
|
7
|
+
return { map, destroy };
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/render/map.ts"],"names":[],"mappings":"AAIA,6GAA6G;AAC7G,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,EAAe,EACf,KAAkC,EAClC,UAAmD,EAAE,EAC1C,EAAE;IACb,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CACpC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CACtF,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC,CAAC;IACF,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC1B,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const logo = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8373.1 2008.4"> <g transform="translate(0 127.1)"> <g fill="none" stroke="#7846BE" stroke-linecap="round" stroke-linejoin="round"> <circle cx="753.3" cy="753.3" r="604.3" stroke-width="297.9"/> <path d="M912.4 912.4 L1356.2 1356.2" stroke-width="291.7"/> <path d="M1560.4 1207.8 L1560.4 1560.4 L1207.8 1560.4" stroke-width="202.3"/> </g> <path fill="currentColor" d="M2665.5 1506.5Q2471.1 1506.5 2322.7 1415.4Q2174.2 1324.3 2091.2 1153.6Q2008.1 982.9 2008.1 745.9Q2008.1 508.6 2091.2 341.7Q2174.2 174.8 2322.7 87.4Q2471.1 0 2665.5 0Q2861.7 0 3009.3 88.3Q3156.8 176.6 3239.9 342.6Q3323 508.6 3323 745.9Q3323 982.9 3239.9 1153.6Q3156.8 1324.3 3009.3 1415.4Q2861.7 1506.5 2665.5 1506.5ZM2665.5 1245.1Q2767.5 1245.1 2841.7 1186.2Q2915.9 1127.3 2956.7 1014.8Q2997.6 902.4 2997.6 745.9Q2997.6 598.1 2956.7 492Q2915.9 385.9 2841.7 330Q2767.5 274 2665.5 274Q2563.8 274 2489.5 330Q2415.2 385.9 2375.2 492Q2335.2 598.1 2335.2 745.9Q2335.2 902.4 2375.2 1014.8Q2415.2 1127.3 2489.5 1186.2Q2563.8 1245.1 2665.5 1245.1ZM3142.5 1881.2Q2984.8 1881.2 2859.6 1827.7Q2734.4 1774.2 2646.5 1680.6Q2558.7 1587 2509.9 1468.9L2834.2 1435.8Q2861.8 1503.8 2915.7 1546.7Q2969.5 1589.7 3038.9 1608.7Q3108.4 1627.7 3178.2 1627.7Q3225.4 1627.7 3266.5 1620.2Q3307.6 1612.7 3340 1601.4L3397.6 1835.1Q3356.5 1855.1 3290.6 1868.2Q3224.7 1881.2 3142.5 1881.2Z M3906.6 1506.5Q3725.4 1506.5 3643.9 1387.1Q3562.3 1267.7 3562.3 1060.9V374.8H3880.1V1021.7Q3880.1 1141.5 3914.3 1188.1Q3948.6 1234.6 4022.2 1234.6Q4085 1234.6 4131.2 1205.2Q4177.3 1175.8 4226.2 1109.3V374.8H4544V1479.3H4284.8L4261.2 1324.1H4253.9Q4184.3 1407.1 4101.9 1456.8Q4019.5 1506.5 3906.6 1506.5Z M5330.3 1506.5Q5173.3 1506.5 5047.3 1437.6Q4921.4 1368.6 4847.4 1238.7Q4773.3 1108.8 4773.3 926.5Q4773.3 792.4 4816.5 685.6Q4859.7 578.8 4933.7 503Q5007.8 427.2 5101 387.4Q5194.2 347.6 5292.5 347.6Q5448.4 347.6 5552 416.4Q5655.7 485.1 5708 604.8Q5760.3 724.5 5760.3 877.2Q5760.3 920.7 5755.9 959.1Q5751.6 997.5 5745.9 1019.1H5081.1Q5095 1101.8 5135.3 1155.4Q5175.7 1208.9 5236.1 1235.7Q5296.5 1262.5 5372.5 1262.5Q5436.2 1262.5 5494.3 1244Q5552.3 1225.6 5612.8 1189.5L5719 1382.5Q5635.9 1440.4 5533 1473.4Q5430.1 1506.5 5330.3 1506.5ZM5075.9 808.2H5489.7Q5489.7 712 5444.3 651.8Q5399 591.6 5297.7 591.6Q5245.8 591.6 5199.5 615.4Q5153.2 639.2 5120.4 686.8Q5087.6 734.5 5075.9 808.2Z M5989.7 1479.3V374.8H6248.7L6272.6 568.6H6278.3Q6339.6 459 6423.6 403.3Q6507.5 347.6 6592.5 347.6Q6640.8 347.6 6670.4 354.2Q6700 360.7 6723.7 370.9L6671.2 644.5Q6640.6 636.5 6614.2 631.7Q6587.9 626.9 6551.4 626.9Q6489.8 626.9 6421.1 673.7Q6352.4 720.6 6307.5 834.9V1479.3Z M6870.3 1479.3V374.8H7188.1V1479.3ZM7029.4 208.6Q6947.6 208.6 6898.4 162.7Q6849.2 116.8 6849.2 39.5Q6849.2 -35.5 6898.4 -81.3Q6947.6 -127.1 7029.4 -127.1Q7109.3 -127.1 7159.5 -81.3Q7209.6 -35.5 7209.6 39.5Q7209.6 116.8 7159.5 162.7Q7109.3 208.6 7029.4 208.6Z M7758 1506.5Q7658.6 1506.5 7585 1462.3Q7511.4 1418.2 7471.2 1342.6Q7430.9 1267 7430.9 1174.4Q7430.9 998.7 7579.4 900.9Q7727.9 803.2 8055.4 767.5Q8052.3 718.2 8034.6 680.8Q8016.9 643.3 7978.6 622.7Q7940.4 602.1 7878 602.1Q7806.7 602.1 7734.4 629.5Q7662 656.8 7581.5 702.9L7469.6 492.9Q7539.5 450.3 7614.4 418.1Q7689.3 385.9 7770.6 366.8Q7851.8 347.6 7937.7 347.6Q8079.9 347.6 8176.4 402.3Q8272.8 457 8323 566.9Q8373.1 676.7 8373.1 843.3V1479.3H8114.1L8092.2 1365H8082.8Q8013.2 1426.1 7932.3 1466.3Q7851.3 1506.5 7758 1506.5ZM7864.9 1259Q7922 1259 7966.6 1233.3Q8011.1 1207.5 8055.4 1161.5V962.3Q7935 977.1 7863.9 1004.6Q7792.8 1032.1 7763 1068.7Q7733.2 1105.3 7733.2 1149.8Q7733.2 1206.5 7769.5 1232.8Q7805.8 1259 7864.9 1259Z"/> </g></svg>`;
|
|
2
|
+
/** Markup of a link that shows the app is built on Queria. */
|
|
3
|
+
export const poweredByHtml = () => '<a class="queria-powered" href="https://queria.io/" target="_blank" rel="noopener">Powered by ' +
|
|
4
|
+
`<span role="img" aria-label="Queria" style="display:inline-block;height:1em;width:4.2em;vertical-align:-0.15em">${logo}</span></a>`;
|
|
5
|
+
//# sourceMappingURL=poweredBy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poweredBy.js","sourceRoot":"","sources":["../../src/render/poweredBy.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,qjHAAqjH,CAAC;AAEnkH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CACxC,gGAAgG;IAChG,mHAAmH,IAAI,aAAa,CAAC"}
|
package/dist/sql.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Quote a string as an SQL literal. */
|
|
2
|
+
export declare const lit: (s: string) => string;
|
|
3
|
+
/** Blank out string literals, quoted identifiers and comments, scanning left to right. */
|
|
4
|
+
export declare const stripLiterals: (sql: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Dataset names referenced in SQL. Tables are written as <dataset>.<schema>.<table>,
|
|
7
|
+
* so the first part of every three-part name outside string literals and comments is a dataset.
|
|
8
|
+
* A struct field read as alias.column.field also matches; the client skips names that are not datasets.
|
|
9
|
+
*/
|
|
10
|
+
export declare const datasetsIn: (sql: string) => string[];
|
package/dist/sql.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Quote a string as an SQL literal. */
|
|
2
|
+
export const lit = (s) => `'${s.replaceAll("'", "''")}'`;
|
|
3
|
+
/** Blank out string literals, quoted identifiers and comments, scanning left to right. */
|
|
4
|
+
export const stripLiterals = (sql) => sql.replace(/'(?:[^']|'')*'|"(?:[^"]|"")*"|--[^\n]*|\/\*[\s\S]*?\*\//g, (m) => (m.startsWith("'") ? "''" : " "));
|
|
5
|
+
/**
|
|
6
|
+
* Dataset names referenced in SQL. Tables are written as <dataset>.<schema>.<table>,
|
|
7
|
+
* so the first part of every three-part name outside string literals and comments is a dataset.
|
|
8
|
+
* A struct field read as alias.column.field also matches; the client skips names that are not datasets.
|
|
9
|
+
*/
|
|
10
|
+
export const datasetsIn = (sql) => [
|
|
11
|
+
...new Set([...stripLiterals(sql).matchAll(/\b([a-z_][a-z0-9_]*)\.[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_]*/gi)].map((m) => m[1].toLowerCase())),
|
|
12
|
+
];
|
|
13
|
+
//# sourceMappingURL=sql.js.map
|
package/dist/sql.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;AAEzE,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE,CACnD,GAAG,CAAC,OAAO,CAAC,0DAA0D,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAY,EAAE,CAAC;IACnD,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,4DAA4D,CAAC,CAAC,CAAC,GAAG,CAChG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAC1B,CACF;CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1 +1,93 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "queria",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Query and visualize Queria open data in the browser with DuckDB WASM, Vega-Lite and MapLibre",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/queria-io/queria-js.git"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"sideEffects": [
|
|
16
|
+
"./dist/elements/define.js"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./elements": {
|
|
24
|
+
"types": "./dist/elements/index.d.ts",
|
|
25
|
+
"default": "./dist/elements/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./elements/define": {
|
|
28
|
+
"types": "./dist/elements/define.d.ts",
|
|
29
|
+
"default": "./dist/elements/define.js"
|
|
30
|
+
},
|
|
31
|
+
"./react": {
|
|
32
|
+
"types": "./dist/react/index.d.ts",
|
|
33
|
+
"default": "./dist/react/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
41
|
+
"prepack": "pnpm build",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@duckdb/duckdb-wasm": "1.33.1-dev57.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"maplibre-gl": ">=4",
|
|
50
|
+
"react": ">=18",
|
|
51
|
+
"vega": ">=6",
|
|
52
|
+
"vega-embed": ">=7",
|
|
53
|
+
"vega-interpreter": ">=2",
|
|
54
|
+
"vega-lite": ">=6"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"maplibre-gl": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"react": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"vega": {
|
|
64
|
+
"optional": true
|
|
65
|
+
},
|
|
66
|
+
"vega-lite": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"vega-embed": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"vega-interpreter": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/react": "^19.3.0",
|
|
78
|
+
"@types/react-dom": "^19.3.0",
|
|
79
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
80
|
+
"maplibre-gl": "^5.24.0",
|
|
81
|
+
"pmtiles": "^4.5.0",
|
|
82
|
+
"react": "^19.3.1",
|
|
83
|
+
"react-dom": "^19.3.1",
|
|
84
|
+
"typescript": "^5.9.3",
|
|
85
|
+
"vega": "^6.4.0",
|
|
86
|
+
"vega-embed": "^7.3.0",
|
|
87
|
+
"vega-interpreter": "^2.3.2",
|
|
88
|
+
"vega-lite": "^6.5.0",
|
|
89
|
+
"vite": "^6.4.6",
|
|
90
|
+
"vitest": "^4.1.0"
|
|
91
|
+
},
|
|
92
|
+
"packageManager": "pnpm@10.28.0"
|
|
93
|
+
}
|
package/src/boot.test.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { runInNewContext } from "node:vm";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { authPatch, isSpatialMissing, needsSpatial } from "./boot.js";
|
|
4
|
+
|
|
5
|
+
type Listener = (event: { data: unknown; stopImmediatePropagation: () => void }) => void;
|
|
6
|
+
|
|
7
|
+
/** Run the patch the way the worker does: in its own globals, with only message events and XHR. */
|
|
8
|
+
const runPatch = () => {
|
|
9
|
+
const listeners: Listener[] = [];
|
|
10
|
+
class FakeXHR {
|
|
11
|
+
headers: Record<string, string> = {};
|
|
12
|
+
open(_method: string, _url: string) {}
|
|
13
|
+
setRequestHeader(name: string, value: string) {
|
|
14
|
+
this.headers[name] = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
runInNewContext(authPatch, { self: { addEventListener: (_: string, fn: Listener) => listeners.push(fn) }, XMLHttpRequest: FakeXHR });
|
|
18
|
+
const post = (data: unknown): boolean => {
|
|
19
|
+
let stopped = false;
|
|
20
|
+
listeners.forEach((fn) => fn({ data, stopImmediatePropagation: () => (stopped = true) }));
|
|
21
|
+
return stopped;
|
|
22
|
+
};
|
|
23
|
+
const open = (url: string): Record<string, string> => {
|
|
24
|
+
const xhr = new FakeXHR();
|
|
25
|
+
xhr.open("GET", url);
|
|
26
|
+
return xhr.headers;
|
|
27
|
+
};
|
|
28
|
+
return { post, open };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe("authPatch", () => {
|
|
32
|
+
it("sends nothing before it gets a token", () => {
|
|
33
|
+
expect(runPatch().open("https://data.queria.io/x")).toEqual({});
|
|
34
|
+
});
|
|
35
|
+
it("sends the token only to the given origins", () => {
|
|
36
|
+
const { post, open } = runPatch();
|
|
37
|
+
post({ queriaAuth: { token: "qd_t", origins: ["https://data.queria.io"] } });
|
|
38
|
+
expect(open("https://data.queria.io/d/ducklake.duckdb")).toEqual({ Authorization: "Bearer qd_t" });
|
|
39
|
+
expect(open("https://data.queria.io.example.com/x")).toEqual({});
|
|
40
|
+
expect(open("https://extensions.duckdb.org/x.wasm")).toEqual({});
|
|
41
|
+
});
|
|
42
|
+
it("keeps its messages from DuckDB and stops on a null token", () => {
|
|
43
|
+
const { post, open } = runPatch();
|
|
44
|
+
expect(post({ queriaAuth: { token: "qd_t", origins: ["https://data.queria.io"] } })).toBe(true);
|
|
45
|
+
expect(post({ type: "duckdb" })).toBe(false);
|
|
46
|
+
post({ queriaAuth: { token: null, origins: [] } });
|
|
47
|
+
expect(open("https://data.queria.io/x")).toEqual({});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("spatial", () => {
|
|
52
|
+
it("finds ST_ calls", () => {
|
|
53
|
+
expect(needsSpatial("select st_area(geom) from t")).toBe(true);
|
|
54
|
+
expect(needsSpatial("select first_name from t")).toBe(false);
|
|
55
|
+
expect(needsSpatial("select 'ST_Area(' as s -- ST_X(\nfrom t")).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it("recognizes the missing-extension errors", () => {
|
|
58
|
+
expect(isSpatialMissing("Function st_point is not in the catalog, but it exists in the spatial extension")).toBe(true);
|
|
59
|
+
expect(isSpatialMissing("Type with name GEOMETRY does not exist")).toBe(true);
|
|
60
|
+
expect(isSpatialMissing("Scalar Function with name st_area does not exist!")).toBe(true);
|
|
61
|
+
expect(isSpatialMissing("Table t does not exist")).toBe(false);
|
|
62
|
+
expect(isSpatialMissing("Table with name st_stations does not exist!")).toBe(false);
|
|
63
|
+
expect(isSpatialMissing("Referenced column geometry does not exist")).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|