@metabase/custom-viz 0.0.1-alpha.1 → 0.0.1-alpha.10

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/README.md CHANGED
@@ -1,53 +1,50 @@
1
1
  # @metabase/custom-viz
2
2
 
3
- CLI for creating and bundling custom visualizations for Metabase.
3
+ CLI and type definitions for creating custom visualizations for Metabase.
4
4
 
5
- ## Prerequisites
5
+ ## Getting Started
6
6
 
7
- - Node.js >= 20
8
- - npm >= 10
9
-
10
- ## Development
7
+ ### 1. Scaffold a new visualization
11
8
 
12
9
  ```bash
13
- # Install dependencies
14
- npm install
10
+ npx @metabase/custom-viz init my-viz
11
+ ```
15
12
 
16
- # Build in watch mode
17
- npm run dev
13
+ This creates a new directory with everything you need:
18
14
 
19
- # Production build
20
- npm run build
15
+ ```
16
+ my-viz/
17
+ src/index.tsx # Your visualization code
18
+ package.json
19
+ vite.config.ts
20
+ tsconfig.json
21
21
  ```
22
22
 
23
- ## Linting & Formatting
23
+ ### 2. Install dependencies and start developing
24
24
 
25
25
  ```bash
26
- # Lint
27
- npm run lint
28
-
29
- # Format code
30
- npm run format
31
-
32
- # Check formatting
33
- npm run format:check
26
+ cd my-viz
27
+ npm install
28
+ npm run dev # Watch mode — rebuilds on changes
34
29
  ```
35
30
 
36
- ## Publishing
37
-
38
- This package uses [np](https://github.com/sindresorhus/np) for publishing.
31
+ ### 3. Build for production
39
32
 
40
33
  ```bash
41
- npm run release
34
+ npm run build
42
35
  ```
43
36
 
44
- `np` will guide you through version bumping, run the build, and publish to npm.
37
+ The build output will be in the `dist/` directory, ready to be loaded into Metabase.
45
38
 
46
39
  ## Project Structure
47
40
 
48
41
  ```
49
42
  src/
50
- cli.ts # CLI entry point (commander)
51
- dist/ # Build output
52
- vite.config.ts # Vite build configuration
43
+ cli.ts # CLI entry point (commander)
44
+ index.ts # Library entry point (type exports)
45
+ templates.ts # Scaffolding templates
46
+ templates/ # Template files for `init` command
47
+ types/ # Custom visualization type definitions
48
+ dist/ # Build output
49
+ vite.config.ts # Vite build configuration
53
50
  ```
package/dist/cli.js CHANGED
@@ -1,39 +1,107 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync as e } from "node:fs";
3
- import { mkdir as t, writeFile as n } from "node:fs/promises";
4
- import { join as r } from "node:path";
5
- import { Command as i } from "commander";
6
- //#region src/templates/.gitignore?raw
7
- var a = "node_modules/\n.DS_Store\n# dist must be committed\n", o = "import type {\n CreateCustomVisualization,\n CustomStaticVisualizationProps,\n CustomVisualizationProps,\n} from \"@metabase/custom-viz\";\n\ntype Settings = {\n threshold?: number;\n};\n\nconst createVisualization: CreateCustomVisualization<Settings> = () => {\n return {\n id: \"__CUSTOM_VIZ_NAME__\",\n getName: () => \"__CUSTOM_VIZ_NAME__\",\n minSize: { width: 1, height: 1 },\n defaultSize: { width: 2, height: 2 },\n isSensible({ cols, rows }) {\n return cols.length === 1 && rows.length === 1 && typeof rows[0][0] === \"number\";\n },\n checkRenderable(series, settings) {\n if (series.length !== 1) {\n throw new Error(\"Only 1 series is supported\");\n }\n\n const [\n {\n data: { cols, rows },\n },\n ] = series;\n\n if (cols.length !== 1) {\n throw new Error(\"Query results should only have 1 column\");\n }\n\n if (rows.length !== 1) {\n throw new Error(\"Query results should only have 1 row\");\n }\n\n if (typeof rows[0][0] !== \"number\") {\n throw new Error(\"Result is not a number\");\n }\n\n if (typeof settings.threshold !== \"number\") {\n throw new Error(\"Threshold setting is not set\");\n }\n },\n settings: {\n threshold: {\n id: \"1\",\n title: \"Threshold\",\n widget: \"number\",\n getDefault() {\n return 0;\n },\n getProps() {\n return {\n options: {\n isInteger: false,\n isNonNegative: false,\n },\n placeholder: \"Set threshold\",\n };\n },\n },\n },\n VisualizationComponent,\n StaticVisualizationComponent,\n };\n};\n\nconst VisualizationComponent = (props: CustomVisualizationProps<Settings>) => {\n const { height, series, settings, width } = props;\n const { threshold } = settings;\n const value = series[0].data.rows[0][0];\n\n if (typeof value !== \"number\" || typeof threshold !== \"number\") {\n throw new Error(\"Value and threshold need to be numbers\");\n }\n\n const emoji = value >= threshold ? \"👍\" : \"👎\";\n\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n width,\n height,\n fontSize: \"10rem\",\n }}\n >\n {emoji}\n </div>\n );\n};\n\nconst StaticVisualizationComponent = (\n props: CustomStaticVisualizationProps<Settings>,\n) => {\n const width = 540;\n const height = 360;\n const { series, settings } = props;\n const { threshold } = settings;\n const value = series[0].data.rows[0][0];\n\n if (typeof value !== \"number\" || typeof threshold !== \"number\") {\n throw new Error(\"Value and threshold need to be numbers\");\n }\n\n const emoji =\n value >= threshold ? (\n <img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAA0mVYSWZJSSoACAAAAAoAAAEEAAEAAACgAAAAAQEEAAEAAACgAAAAAgEDAAMAAACGAAAAEgEDAAEAAAABAAAAGgEFAAEAAACMAAAAGwEFAAEAAACUAAAAKAEDAAEAAAACAAAAMQECAA8AAACcAAAAMgECABQAAACsAAAAaYcEAAEAAADAAAAAAAAAAAgACAAIACwBAAABAAAALAEAAAEAAABHSU1QIDMuMC4wLVJDMQAAMjAyNjowMzoxOCAxNjoyNzo1OQABAAGgAwABAAAAAQAAAAAAAAD8VR8dAAABhWlDQ1BJQ0MgcHJvZmlsZQAAeJx9kb9Lw0AcxV9bpSoVQTuIPyBDdbKLijjWKhShQqgVWnUwufQXNGlIUlwcBdeCgz8Wqw4uzro6uAqC4A8Q/wBxUnSREr+XFFrEeHDch3f3HnfvAH+9zFSzIwaommWkEnEhk10Vgq8IoB/dGMaoxEx9ThST8Bxf9/Dx9S7Ks7zP/Tl6lZzJAJ9AHGO6YRFvEM9sWjrnfeIwK0oK8TnxhEEXJH7kuuzyG+eCw36eGTbSqXniMLFQaGO5jVnRUImniSOKqlG+P+OywnmLs1qusuY9+QtDOW1lmes0R5DAIpYgQoCMKkoow0KUVo0UEynaj3v4hxy/SC6ZXCUwciygAhWS4wf/g9/dmvmpSTcpFAc6X2z7YwwI7gKNmm1/H9t24wQIPANXWstfqQOzn6TXWlrkCOjbBi6uW5q8B1zuAINPumRIjhSg6c/ngfcz+qYsMHAL9Ky5vTX3cfoApKmr5A1wcAiMFyh73ePdXe29/Xum2d8PeZVyqWZhNiAAAA16aVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpHSU1QPSJodHRwOi8vd3d3LmdpbXAub3JnL3htcC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgeG1wTU06RG9jdW1lbnRJRD0iZ2ltcDpkb2NpZDpnaW1wOjUyMGY3ZWIzLTNiNjktNDlkMy04NjZjLWIwOWI4YzQ4MzgwZSIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozZDFlNjVmZS1kYWQ5LTQ4MjQtYmE5MS1hNGMyYzhmOWNjMmIiCiAgIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo4YzU1Zjg3MC02NjE4LTQ1MjAtYTE2Yy0wZmVlYWJjODE4ZTIiCiAgIEdJTVA6QVBJPSIzLjAiCiAgIEdJTVA6UGxhdGZvcm09IkxpbnV4IgogICBHSU1QOlRpbWVTdGFtcD0iMTc3MzgyNjA4MDI4Mzg3NSIKICAgR0lNUDpWZXJzaW9uPSIzLjAuMC1SQzEiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjY6MDM6MThUMTY6Mjc6NTkrMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDI2OjAzOjE4VDE2OjI3OjU5KzA3OjAwIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YTc4M2Q4MzktMTY2Yy00MTM2LWI3ZDgtMWJlNGU1ZTcxNjFjIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHSU1QIDMuMC4wLVJDMSAoTGludXgpIgogICAgICBzdEV2dDp3aGVuPSIyMDI2LTAzLTE4VDE2OjI4OjAwKzA3OjAwIi8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PlfBSK4AAAAGYktHRAAAAEgAkHfF9EMAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfqAxIJHAAvHRFSAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAACzdJREFUeNrtnXuQ1lUZxz/LLrHcZLnIgoYNN02oNGAyCUqUS2o6aRenZlKwEawxGa0ZJhswrZFwYsCKGqapyHEatYYIzUshTWqCFGCajFxWwEkEgWW5yHXh7Y/z21iWRZ7zvuf3vr/L9zNzZvjj8J7fec53z/08TxWiFGqBScBEYCQwCKgDCkAjsAFYC7wAPA/slMlECHoCDwC7IrFZ0olIjPcDQ2RCUSw3A7s9hNdeOg48BlwgcwornYDflii8tmk/MEWmFWejM/BcYPG1TrNlYnEmOgBLYhRfS5olU4v2uKcM4mtZpFwtc4vWXAwcKZMAC8A2oFueDFwtjb0viyIRlovuwHu4fUORcy6JhsVCmdO2PHUMHaSzMzIFqPLI/wTuVKQP0BsYA8yMVs/NHr/TH7hK5hdvGXusZmDqWX6rHvidRy/4oMyfbwYSfg+vCnjG+JsvqgnyzXVGoeyNFg5WJhp/9zDu5EVzwJxiPaNdjjtOs7ICdw58NjrhbtdIgDmlvzHfG56/ux/4jzHvaAkwv9Qb820v4rdXGPNdJgHml37GfO/EKMDhEqAEeDZ2xCjAoXlYiEiA7dPXmO/dIn57U7R6Phs1kQglQM0Bgw7BBdxbEQvDJMD8UWcc+o4ae7L2sApwuASYP87zmP8VYhbgQAkwfwyKcfhtYb0x3/kSYP6wPplsKKGMjRKgBFhqD/hmCWVsCTwdkABz2ANuKqGMPdjuCHYHzpEA1QOGHoJbXHdY6C8B5odqj5VnQ4ll7Tbm6y4B5ocPAR8w5DtY4ioYnF8ZC90kwPwwwmMBUiiTALtKgPnh48Z86wKUdUA9oATYFust5NUByrL2oOoB1QOexpoAZZ0w5uskAeaDAdiuYRUCCdDaAzZLgPlglDHfFux7eCF6QAkwJ4wv4/zPpwc8JgHmg0llnP8BdFQPKAG2MAQYbMz7UqAye0qAEmALnzXmOwisDFRmb2O+fRJg9rnWmO9FnMPKEPQw5tstAWabQcAEY95nApbbSwIUAHOxe8IaFLDcQ8Yyu6qJsks33J6eRQivBiy3DruXrEyT9yH42x6r0V8HLNe64lZsuQzTN1phWnqi9zyEauEmY7nPqwfMLj/Eftv4Ydw7jlCU4+WdBJhghuMXo+3nMay8LbwpAWaPauCXOOc/FpYCrwX+hnK8vBMJZQb2bZdmwvtnqcIeZ/gTaq5sMQz7/lsBWBjDN1yIPXZcnZosO9QAL3uI7wDxvMn9mrH8DXlolDzNAWd6DmlzKf3pZXtYv2GN+ozsMD6az1l7vwbiOwJbZfyG76jZssFA3IG+z8IjrhAJnXDHa5bvuDIv86Is0wN4EvvNE4B5hLt02pax2F+5VQM34B5LDcB5yuoZLUx6tEot74abOPWa/8HoD28Hzpf11mhbZxMuVske9U3x/3E9i1+o1HVAbYzfNJfyh389U9qIC6D4Lez7ksJjcfWwZ4McI/7gMOsSJMC2aT3wY8oboDuTVOGOznwb4N4yzEULKUgncBdvPyIpFSe++UUY/ekybEl9MyUCbD0izMH+ek/DLu6M19fQW7A/ECqFpSkTYOvYxf0kr/enFni0COPuBy4p0zduT6kAW05lLpDM2qcv8I8ijNqMC0xdLvanWIAF3NWwesntVC4FNhdp0Oll/tZ/plyAhWh/tFayOzmpP1SkIe+rwPdOy4AAC8BPQ68a00Y9sAD4QpH/fz5wV4UWSX8Erjfm3xb17m/hTjG2Av/FxadrnZqi/B051ZtqXTQ9OTfaAhoKfBjnhLNXCfUoABOBZXncYrkVv3PdtmlBhf/oanC3cna2+qaDuBjCC6NefQzxxwYZAtwGLC5ybvoG2T/GPYXLgRdKHDrmJKjHr45EMCgB+2x1uAdaRz3teXsehPcxYEmAectMTZnPyoRoSPfZP63OoiFaboEsDyC8I8BkacvMGM+e8HNZEt044GfR5DvEam0n8Glpypu7PWz8+7QvKsZGogt9SrAGu/sLcXq7vGS0cxMpPCuuwp1ArI5xn6qTdFQSEz3sPTpNFRsSYDV7prQLuFHaCdZJWE+YpqWlUlNxTx3jEN8j2GJ8CDu/MNp+Xhr+mmbHJLwG7N7thR+3G9tgUdIrsiAG4e0A7sQWWlUUh9WFXKJXwtMDC68RmEXGI0gmhMke059EMhb/450zpdejya78JZePHxnb5qEkfnw17u1pKaLbDfwGuIp03tpJO68a2+nuNHff7Z1eLIz2ofQYpnJc4dFmVySxApvwfxD+JXJ2xSeh1GC/vX0Yu5vjsnEp/nf0dHKRHB7waLs/J7EC93pUYJ7aO1Hc5tl53JzESvwN+4UBDbnJmrcf9xDftqSOXG8bK3CT2jy14ku0/0LrS7U+avdEMKUI8a0jwadQ1kpob6/yVOHvwq4A3JLkSlkrIZJBZ+CvngJ8XAIUoUW4DD/PWf0kQBGSLh47GAXgGxKgCE0/7FGcnpQARRxYb8E0kdB3wRJgurnIow2HlVpYB9lbtGE9zhGSBQlQxMK/jPmGSoAiDl4x5uslAYo42G7MVycBijhoMubrKQGKSgqwhwQo4qCLMd9BCVDEgXVobZIARRxYFxd7JUARB9YN5kYJUMTBCGO+t5P48ToLTjddce99LW34KQlQhGYy9lh750iAIiRVwEpj+60OUaDmgKI104HLjHkTG6pLPWB6h16f55kjJUBRKfG9nuTKSIDpopiH6V+XAEWoRUcxD9MHS4AiFL5vghPtF0YCTK8IfbwjPCUBitD4PEzfJgGKOBhibLvjJNi3owSYbqzu9YKEzNBJiGhNDTa/fydwDookQBGUkUZNvIMLQiQBiqCMM+bbGqpACVC01sKtxryvSYAiNJOwu9pYluSKaBWcPqqAVdgvovaWAEVIvkLKoyNJgOmlD+5kw9puN0iAIuTQ+yePNttMCqKYHjNWplbtX3Huw+8WzNQ0VGqPsTKj1P4VxTcwYQMJjo7UmrXGCi2UBirGZPxvQV+Xlsr9ymM5f420kArxLU1TBa/3qNhhYBraEC8Xxbz/2Amcl6ZKdgYO4B99cRZwLXBhWuYaKVzxFvP+I5VhdRcUUdG2w/MW4DngJ7jI3BerpwzSOfi+/7g6jRWtB/aVKML20l7ce4Q7o55SxC/COWmt6HdjEGDbtAn4AS66j7DTBfi70cbPprWSHfDbZS81rYyGas0fbUygjE6IKkV34N9lFGEBd1v3eyTUdViCGG6058a0V7RntJgolDntAmZg9/ieN6zbZauyUNmO0cr4RAWEuAX4ovR2GjPJyPUrH0YCKyogwgLu0fVHpbv/z88bjHZ7MIuVvwZ4HLsv4lDpGDCfADHOUs7nPWz25Swboi5ajc0AHsWFCW0sgxDfxV0tqs6h+Opwr9qsBwL1efwL7QVcDtwBLMI5RIxDiGuBz+TIrp3wc0L0F81WTnI+7tngH7C7j7Cm5cB43HlpVjkXu/OhlvRVya59ekRifDmwEDcC9xAgFH2CqMZt0G/3tMWGnE5RvBkNLIlhi2cz8AhwF85jwOBoCEsDnYFPAvd7rHYr0vtlacgZBcyOhtI4acRFiWwG9ifMBrXRIqOe0tynPY0uCxfNjVHvVVAqKjUCAySj0oeg7+MCKktU9nQUuFLyCccgYLGEZfZ6OlmSiYdxwCsS2RnTEZx7DhHzdsQ03HUtie5k2q5ht/wrxTuwH0dlOS2ONqhFBajB3Yl7ItpSyZPwVuFeIIqE0Be4BXgMu2uRtKWDuBtIidrfq5L22rXJUGBElC4CPog7i07TzZB9uMsWa3BHlk+RvI1zCbCI+WNn3Fl0B9ypQ5JseAh3SrMn+rcQQojE8j/2Mm8tOLYIDgAAAABJRU5ErkJggg==\" />\n ) : (\n <img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAA0mVYSWZJSSoACAAAAAoAAAEEAAEAAACgAAAAAQEEAAEAAACgAAAAAgEDAAMAAACGAAAAEgEDAAEAAAABAAAAGgEFAAEAAACMAAAAGwEFAAEAAACUAAAAKAEDAAEAAAACAAAAMQECAA8AAACcAAAAMgECABQAAACsAAAAaYcEAAEAAADAAAAAAAAAAAgACAAIACwBAAABAAAALAEAAAEAAABHSU1QIDMuMC4wLVJDMQAAMjAyNjowMzoxOCAxNjoyODowOAABAAGgAwABAAAAAQAAAAAAAABiEXj2AAABhWlDQ1BJQ0MgcHJvZmlsZQAAeJx9kb9Lw0AcxV9bpSoVQTuIPyBDdbKLijjWKhShQqgVWnUwufQXNGlIUlwcBdeCgz8Wqw4uzro6uAqC4A8Q/wBxUnSREr+XFFrEeHDch3f3HnfvAH+9zFSzIwaommWkEnEhk10Vgq8IoB/dGMaoxEx9ThST8Bxf9/Dx9S7Ks7zP/Tl6lZzJAJ9AHGO6YRFvEM9sWjrnfeIwK0oK8TnxhEEXJH7kuuzyG+eCw36eGTbSqXniMLFQaGO5jVnRUImniSOKqlG+P+OywnmLs1qusuY9+QtDOW1lmes0R5DAIpYgQoCMKkoow0KUVo0UEynaj3v4hxy/SC6ZXCUwciygAhWS4wf/g9/dmvmpSTcpFAc6X2z7YwwI7gKNmm1/H9t24wQIPANXWstfqQOzn6TXWlrkCOjbBi6uW5q8B1zuAINPumRIjhSg6c/ngfcz+qYsMHAL9Ky5vTX3cfoApKmr5A1wcAiMFyh73ePdXe29/Xum2d8PeZVyqWZhNiAAAA16aVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpHSU1QPSJodHRwOi8vd3d3LmdpbXAub3JnL3htcC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgeG1wTU06RG9jdW1lbnRJRD0iZ2ltcDpkb2NpZDpnaW1wOmI5OGQ1OTk1LTRkZjktNDdkMS1hMGRmLTJjYWJhOTU2NjFjZSIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4MzNlNzUzYS0zZDhmLTRhNTAtODA1NC0wNmQ0N2JhNzQ1NWMiCiAgIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoyYzJiM2I3Zi04OTU0LTQyZTgtOWNkOS1lOTc3Y2ExZmMwMGYiCiAgIEdJTVA6QVBJPSIzLjAiCiAgIEdJTVA6UGxhdGZvcm09IkxpbnV4IgogICBHSU1QOlRpbWVTdGFtcD0iMTc3MzgyNjA4OTM4NzIzMiIKICAgR0lNUDpWZXJzaW9uPSIzLjAuMC1SQzEiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjY6MDM6MThUMTY6Mjg6MDgrMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDI2OjAzOjE4VDE2OjI4OjA4KzA3OjAwIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NDM0NWQ1MjktYzlmYi00NjQ5LTlmZDctYmVkMDNiYjMzNjUzIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHSU1QIDMuMC4wLVJDMSAoTGludXgpIgogICAgICBzdEV2dDp3aGVuPSIyMDI2LTAzLTE4VDE2OjI4OjA5KzA3OjAwIi8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PkUgIFwAAAAGYktHRAAAAEgAkHfF9EMAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfqAxIJHAlWwan2AAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAACwtJREFUeNrtnXuwVlUZh5+DAnI9ykWBJC9cdHAgRSUh1Kwhi6KG0TTorpjTDScNRm1Kx/5wqhHTAjRMssbRaaBxiDIgyUKHSASV0FIUUFFB4CBXhQNff6x1GOZ08Lzr+9be3778npk1wMzi23ut97fXfb1vA6ItOgBDgHP9nwOBk/2fXYDjfb4TMvbe7wI7gCZgC7AaeBpYAbwks2abYcB0YCmwE6gULD0L3AR8UKbODgOBHwHrCii4o6X9wL0SYn0ZAywAmkskvNbpPeAHwLGSQ3qMAh4rsejaSsuB0ySNZOnvu52DElyb6S1gpGQSn+P8wHuXRNZu2gmMlWTiMaFkk4sYaatfdhI1MBR4VGKqOv0X6CEZhdML+Jmf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\" />\n );\n\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n width,\n height,\n fontSize: \"10rem\",\n }}\n >\n {emoji}\n </div>\n );\n};\n\nexport default createVisualization;\n", s = "{\n \"name\": \"__CUSTOM_VIZ_NAME__\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"vite build\",\n \"dev\": \"vite build --watch & vite preview\",\n \"type-check\": \"tsc --noEmit\"\n },\n \"devDependencies\": {\n \"@metabase/custom-viz\": \"^0.0.1\",\n \"@types/react\": \"^19.2.14\",\n \"react\": \"^19.1.0\",\n \"typescript\": \"^5.9.3\",\n \"vite\": \"^8.0.0\"\n }\n}\n", c = "{\n \"compilerOptions\": {\n \"target\": \"ES2020\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"jsx\": \"react-jsx\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"outDir\": \"dist\",\n \"declaration\": true\n },\n \"include\": [\"src\"]\n}\n", l = "import { resolve } from \"path\";\nimport { createServer } from \"http\";\nimport { defineConfig } from \"vite\";\n\n/**\n * Vite plugin that replaces `react` and `react/jsx-runtime` imports with\n * virtual modules that read from Metabase's `window.__METABASE_VIZ_API__`.\n *\n * This is necessary because the ES module output format cannot use\n * `output.globals`, and bare `import 'react'` would fail in the browser.\n */\nfunction metabaseVizExternals() {\n const VIRTUAL_REACT = \"\\0virtual:react\";\n const VIRTUAL_JSX_RUNTIME = \"\\0virtual:react/jsx-runtime\";\n\n return {\n name: \"metabase-viz-externals\",\n enforce: \"pre\" as const,\n\n resolveId(source) {\n if (source === \"react\") {\n return VIRTUAL_REACT;\n }\n if (source === \"react/jsx-runtime\") {\n return VIRTUAL_JSX_RUNTIME;\n }\n return null;\n },\n\n load(id) {\n if (id === VIRTUAL_REACT) {\n return [\n \"const React = window.__METABASE_VIZ_API__.React;\",\n \"export default React;\",\n \"export const { useState, useEffect, useRef, useCallback, useMemo, useReducer, useContext, createElement, Fragment } = React;\",\n ].join(\"\\n\");\n }\n if (id === VIRTUAL_JSX_RUNTIME) {\n return [\n \"const jsxRuntime = window.__METABASE_VIZ_API__.jsxRuntime;\",\n \"export const { jsx, jsxs, Fragment } = jsxRuntime;\",\n ].join(\"\\n\");\n }\n return null;\n },\n };\n}\n\nconst NOTIFY_PORT = 5175;\n\n/**\n * Vite plugin that starts a tiny SSE server and sends a \"reload\" event\n * to all connected clients after each rebuild completes.\n * Metabase's frontend connects to this to live-reload the custom viz.\n */\nfunction metabaseNotifyReload() {\n const clients = new Set<import(\"http\").ServerResponse>();\n let server: ReturnType<typeof createServer> | null = null;\n\n return {\n name: \"metabase-notify-reload\",\n\n buildStart() {\n if (server) {\n return;\n }\n server = createServer((req, res) => {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n clients.add(res);\n req.on(\"close\", () => clients.delete(res));\n });\n server.listen(NOTIFY_PORT, () => {\n console.log(\n `[metabase-notify] SSE server listening on http://localhost:${NOTIFY_PORT}`,\n );\n });\n },\n\n closeBundle() {\n for (const client of clients) {\n client.write(\"data: reload\\n\\n\");\n }\n console.log(\n `[metabase-notify] Build complete, notified ${clients.size} client(s)`,\n );\n },\n };\n}\n\nconst isWatch = process.argv.includes(\"--watch\");\n\nexport default defineConfig({\n plugins: [metabaseVizExternals(), ...(isWatch ? [metabaseNotifyReload()] : [])],\n build: {\n outDir: \"dist\",\n lib: {\n entry: resolve(__dirname, \"src/index.tsx\"),\n formats: [\"iife\"],\n fileName: () => \"index.js\",\n name: \"__customVizPlugin__\",\n },\n },\n preview: {\n port: 5174,\n host: true,\n cors: true,\n },\n});\n", u = "__CUSTOM_VIZ_NAME__";
8
- function d(e, t) {
9
- return e.split(u).join(t);
2
+ import { existsSync as e, readFileSync as t } from "node:fs";
3
+ import { mkdir as n, writeFile as r } from "node:fs/promises";
4
+ import { dirname as i, join as a } from "node:path";
5
+ import { createInterface as o } from "node:readline";
6
+ import { Command as s } from "commander";
7
+ import { fileURLToPath as c } from "node:url";
8
+ //#region package.json
9
+ var l = "0.0.1-alpha.10", u = "node_modules/\n.DS_Store\n# dist must be committed\n", d = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.79978 6.86661C1.65041 7.01583 1.53192 7.19302 1.45107 7.38806C1.37023 7.58309 1.32861 7.79215 1.32861 8.00328C1.32861 8.21441 1.37023 8.42347 1.45107 8.61851C1.53192 8.81354 1.65041 8.99073 1.79978 9.13995L6.85978 14.1999C7.00899 14.3493 7.18618 14.4678 7.38122 14.5487C7.57626 14.6295 7.78531 14.6711 7.99644 14.6711C8.20757 14.6711 8.41663 14.6295 8.61167 14.5487C8.80671 14.4678 8.9839 14.3493 9.13311 14.1999L14.1931 9.13995C14.3425 8.99073 14.461 8.81354 14.5418 8.61851C14.6227 8.42347 14.6643 8.21441 14.6643 8.00328C14.6643 7.79215 14.6227 7.58309 14.5418 7.38806C14.461 7.19302 14.3425 7.01583 14.1931 6.86661L9.13311 1.80661C8.9839 1.65725 8.80671 1.53875 8.61167 1.45791C8.41663 1.37706 8.20757 1.33545 7.99644 1.33545C7.78531 1.33545 7.57626 1.37706 7.38122 1.45791C7.18618 1.53875 7.00899 1.65725 6.85978 1.80661L1.79978 6.86661Z\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n", f = "import type {\n CreateCustomVisualization,\n CustomStaticVisualizationProps,\n CustomVisualizationProps,\n} from \"../\";\n\ntype Settings = {\n threshold?: number;\n};\n\nconst createVisualization: CreateCustomVisualization<Settings> = ({\n defineSetting,\n getAssetUrl,\n}) => {\n const VisualizationComponent = (\n props: CustomVisualizationProps<Settings>,\n ) => {\n const { height, series, settings, width } = props;\n const { threshold } = settings;\n const value = series[0].data.rows[0][0];\n\n if (!height || !width) {\n return null;\n }\n\n if (typeof value !== \"number\" || typeof threshold !== \"number\") {\n throw new Error(\"Value and threshold need to be numbers\");\n }\n\n const emoji = value >= threshold ? \"👍\" : \"👎\";\n\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n width,\n height,\n fontSize: \"10rem\",\n }}\n >\n {emoji}\n </div>\n );\n };\n\n const StaticVisualizationComponent = (\n props: CustomStaticVisualizationProps<Settings>,\n ) => {\n const width = 540;\n const height = 360;\n const { series, settings } = props;\n const { threshold } = settings;\n const value = series[0].data.rows[0][0];\n\n if (typeof value !== \"number\" || typeof threshold !== \"number\") {\n throw new Error(\"Value and threshold need to be numbers\");\n }\n\n const emoji =\n value >= threshold ? (\n <img src={getAssetUrl(\"thumbs-up.png\")} />\n ) : (\n <img src={getAssetUrl(\"thumbs-down.png\")} />\n );\n\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n width,\n height,\n fontSize: \"10rem\",\n }}\n >\n {emoji}\n </div>\n );\n };\n\n return {\n id: \"__CUSTOM_VIZ_NAME__\",\n getName: () => \"__CUSTOM_VIZ_NAME__\",\n minSize: { width: 4, height: 4 },\n defaultSize: { width: 4, height: 4 },\n checkRenderable(series, settings) {\n if (series.length !== 1) {\n throw new Error(\"Only 1 series is supported\");\n }\n\n const [\n {\n data: { cols, rows },\n },\n ] = series;\n\n if (cols.length !== 1) {\n throw new Error(\"Query results should only have 1 column\");\n }\n\n if (rows.length !== 1) {\n throw new Error(\"Query results should only have 1 row\");\n }\n\n if (typeof rows[0][0] !== \"number\") {\n throw new Error(\"Result is not a number\");\n }\n\n if (typeof settings.threshold !== \"number\") {\n throw new Error(\"Threshold setting is not set\");\n }\n },\n settings: {\n threshold: defineSetting({\n id: \"threshold\",\n title: \"Threshold\",\n widget: \"number\",\n getDefault() {\n return 0;\n },\n getProps() {\n return {\n options: {\n isInteger: false,\n isNonNegative: false,\n },\n placeholder: \"Set threshold\",\n };\n },\n }),\n },\n VisualizationComponent,\n StaticVisualizationComponent,\n };\n};\n\nexport default createVisualization;\n", p = "{\n \"name\": \"__CUSTOM_VIZ_NAME__\",\n \"icon\": \"icon.svg\",\n \"assets\": [\"icon.svg\", \"thumbs-up.png\", \"thumbs-down.png\"],\n \"metabase\": {\n \"version\": \">=59\"\n }\n}\n", m = "{\n \"name\": \"__CUSTOM_VIZ_NAME__\",\n \"version\": \"0.0.1\",\n \"lockfileVersion\": 3,\n \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"__CUSTOM_VIZ_NAME__\",\n \"version\": \"0.0.1\",\n \"devDependencies\": {\n \"@metabase/custom-viz\": \"__CUSTOM_VIZ_VERSION__\",\n \"@types/react\": \"^19.2.14\",\n \"react\": \"^19.1.0\",\n \"typescript\": \"^5.9.3\",\n \"vite\": \"^8.0.0\"\n }\n },\n \"node_modules/@emnapi/core\": {\n \"version\": \"1.9.1\",\n \"resolved\": \"https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz\",\n \"integrity\": \"sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"peer\": true,\n \"dependencies\": {\n \"@emnapi/wasi-threads\": \"1.2.0\",\n \"tslib\": \"^2.4.0\"\n }\n },\n \"node_modules/@emnapi/runtime\": {\n \"version\": \"1.9.1\",\n \"resolved\": \"https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz\",\n \"integrity\": \"sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"peer\": true,\n \"dependencies\": {\n \"tslib\": \"^2.4.0\"\n }\n },\n \"node_modules/@emnapi/wasi-threads\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz\",\n \"integrity\": \"sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"peer\": true,\n \"dependencies\": {\n \"tslib\": \"^2.4.0\"\n }\n },\n \"node_modules/@metabase/custom-viz\": {\n \"version\": \"__CUSTOM_VIZ_VERSION__\",\n \"resolved\": \"https://registry.npmjs.org/@metabase/custom-viz/-/custom-viz-__CUSTOM_VIZ_VERSION__.tgz\",\n \"dev\": true,\n \"dependencies\": {\n \"commander\": \"^13.1.0\"\n },\n \"bin\": {\n \"metabase-custom-viz\": \"dist/cli.js\"\n }\n },\n \"node_modules/@napi-rs/wasm-runtime\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz\",\n \"integrity\": \"sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@tybys/wasm-util\": \"^0.10.1\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/Brooooooklyn\"\n },\n \"peerDependencies\": {\n \"@emnapi/core\": \"^1.7.1\",\n \"@emnapi/runtime\": \"^1.7.1\"\n }\n },\n \"node_modules/@oxc-project/types\": {\n \"version\": \"0.122.0\",\n \"resolved\": \"https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz\",\n \"integrity\": \"sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"funding\": {\n \"url\": \"https://github.com/sponsors/Boshen\"\n }\n },\n \"node_modules/@rolldown/binding-android-arm64\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-darwin-arm64\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-darwin-x64\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-freebsd-x64\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-arm-gnueabihf\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-arm64-gnu\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-arm64-musl\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-ppc64-gnu\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-s390x-gnu\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-x64-gnu\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-linux-x64-musl\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-openharmony-arm64\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openharmony\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-wasm32-wasi\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==\",\n \"cpu\": [\n \"wasm32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@napi-rs/wasm-runtime\": \"^1.1.1\"\n },\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/@rolldown/binding-win32-arm64-msvc\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/binding-win32-x64-msvc\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n }\n },\n \"node_modules/@rolldown/pluginutils\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@tybys/wasm-util\": {\n \"version\": \"0.10.1\",\n \"resolved\": \"https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz\",\n \"integrity\": \"sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"tslib\": \"^2.4.0\"\n }\n },\n \"node_modules/@types/react\": {\n \"version\": \"19.2.14\",\n \"resolved\": \"https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz\",\n \"integrity\": \"sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"csstype\": \"^3.2.2\"\n }\n },\n \"node_modules/commander\": {\n \"version\": \"13.1.0\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-13.1.0.tgz\",\n \"integrity\": \"sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/csstype\": {\n \"version\": \"3.2.3\",\n \"resolved\": \"https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz\",\n \"integrity\": \"sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/detect-libc\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz\",\n \"integrity\": \"sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/fdir\": {\n \"version\": \"6.5.0\",\n \"resolved\": \"https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz\",\n \"integrity\": \"sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"peerDependencies\": {\n \"picomatch\": \"^3 || ^4\"\n },\n \"peerDependenciesMeta\": {\n \"picomatch\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/fsevents\": {\n \"version\": \"2.3.3\",\n \"resolved\": \"https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz\",\n \"integrity\": \"sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \"^8.16.0 || ^10.6.0 || >=11.0.0\"\n }\n },\n \"node_modules/lightningcss\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz\",\n \"integrity\": \"sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==\",\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"dependencies\": {\n \"detect-libc\": \"^2.0.3\"\n },\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n },\n \"optionalDependencies\": {\n \"lightningcss-android-arm64\": \"1.32.0\",\n \"lightningcss-darwin-arm64\": \"1.32.0\",\n \"lightningcss-darwin-x64\": \"1.32.0\",\n \"lightningcss-freebsd-x64\": \"1.32.0\",\n \"lightningcss-linux-arm-gnueabihf\": \"1.32.0\",\n \"lightningcss-linux-arm64-gnu\": \"1.32.0\",\n \"lightningcss-linux-arm64-musl\": \"1.32.0\",\n \"lightningcss-linux-x64-gnu\": \"1.32.0\",\n \"lightningcss-linux-x64-musl\": \"1.32.0\",\n \"lightningcss-win32-arm64-msvc\": \"1.32.0\",\n \"lightningcss-win32-x64-msvc\": \"1.32.0\"\n }\n },\n \"node_modules/lightningcss-android-arm64\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz\",\n \"integrity\": \"sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-darwin-arm64\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz\",\n \"integrity\": \"sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-darwin-x64\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz\",\n \"integrity\": \"sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-freebsd-x64\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz\",\n \"integrity\": \"sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-linux-arm-gnueabihf\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz\",\n \"integrity\": \"sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-linux-arm64-gnu\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz\",\n \"integrity\": \"sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-linux-arm64-musl\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz\",\n \"integrity\": \"sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-linux-x64-gnu\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz\",\n \"integrity\": \"sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-linux-x64-musl\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz\",\n \"integrity\": \"sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-win32-arm64-msvc\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz\",\n \"integrity\": \"sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/lightningcss-win32-x64-msvc\": {\n \"version\": \"1.32.0\",\n \"resolved\": \"https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz\",\n \"integrity\": \"sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MPL-2.0\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 12.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/parcel\"\n }\n },\n \"node_modules/nanoid\": {\n \"version\": \"3.3.11\",\n \"resolved\": \"https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz\",\n \"integrity\": \"sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"bin\": {\n \"nanoid\": \"bin/nanoid.cjs\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || ^13.7 || ^14 || >=15.0.1\"\n }\n },\n \"node_modules/picocolors\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz\",\n \"integrity\": \"sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==\",\n \"dev\": true,\n \"license\": \"ISC\"\n },\n \"node_modules/picomatch\": {\n \"version\": \"4.0.4\",\n \"resolved\": \"https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz\",\n \"integrity\": \"sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/jonschlinkert\"\n }\n },\n \"node_modules/postcss\": {\n \"version\": \"8.5.8\",\n \"resolved\": \"https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz\",\n \"integrity\": \"sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/postcss/\"\n },\n {\n \"type\": \"tidelift\",\n \"url\": \"https://tidelift.com/funding/github/npm/postcss\"\n },\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"nanoid\": \"^3.3.11\",\n \"picocolors\": \"^1.1.1\",\n \"source-map-js\": \"^1.2.1\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || >=14\"\n }\n },\n \"node_modules/react\": {\n \"version\": \"19.2.4\",\n \"resolved\": \"https://registry.npmjs.org/react/-/react-19.2.4.tgz\",\n \"integrity\": \"sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/rolldown\": {\n \"version\": \"1.0.0-rc.12\",\n \"resolved\": \"https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz\",\n \"integrity\": \"sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@oxc-project/types\": \"=0.122.0\",\n \"@rolldown/pluginutils\": \"1.0.0-rc.12\"\n },\n \"bin\": {\n \"rolldown\": \"bin/cli.mjs\"\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"optionalDependencies\": {\n \"@rolldown/binding-android-arm64\": \"1.0.0-rc.12\",\n \"@rolldown/binding-darwin-arm64\": \"1.0.0-rc.12\",\n \"@rolldown/binding-darwin-x64\": \"1.0.0-rc.12\",\n \"@rolldown/binding-freebsd-x64\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-arm-gnueabihf\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-arm64-gnu\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-arm64-musl\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-ppc64-gnu\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-s390x-gnu\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-x64-gnu\": \"1.0.0-rc.12\",\n \"@rolldown/binding-linux-x64-musl\": \"1.0.0-rc.12\",\n \"@rolldown/binding-openharmony-arm64\": \"1.0.0-rc.12\",\n \"@rolldown/binding-wasm32-wasi\": \"1.0.0-rc.12\",\n \"@rolldown/binding-win32-arm64-msvc\": \"1.0.0-rc.12\",\n \"@rolldown/binding-win32-x64-msvc\": \"1.0.0-rc.12\"\n }\n },\n \"node_modules/source-map-js\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz\",\n \"integrity\": \"sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==\",\n \"dev\": true,\n \"license\": \"BSD-3-Clause\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/tinyglobby\": {\n \"version\": \"0.2.15\",\n \"resolved\": \"https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz\",\n \"integrity\": \"sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"fdir\": \"^6.5.0\",\n \"picomatch\": \"^4.0.3\"\n },\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/SuperchupuDev\"\n }\n },\n \"node_modules/tslib\": {\n \"version\": \"2.8.1\",\n \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz\",\n \"integrity\": \"sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==\",\n \"dev\": true,\n \"license\": \"0BSD\",\n \"optional\": true\n },\n \"node_modules/typescript\": {\n \"version\": \"5.9.3\",\n \"resolved\": \"https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz\",\n \"integrity\": \"sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"tsc\": \"bin/tsc\",\n \"tsserver\": \"bin/tsserver\"\n },\n \"engines\": {\n \"node\": \">=14.17\"\n }\n },\n \"node_modules/vite\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/vite/-/vite-8.0.3.tgz\",\n \"integrity\": \"sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"lightningcss\": \"^1.32.0\",\n \"picomatch\": \"^4.0.4\",\n \"postcss\": \"^8.5.8\",\n \"rolldown\": \"1.0.0-rc.12\",\n \"tinyglobby\": \"^0.2.15\"\n },\n \"bin\": {\n \"vite\": \"bin/vite.js\"\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/vitejs/vite?sponsor=1\"\n },\n \"optionalDependencies\": {\n \"fsevents\": \"~2.3.3\"\n },\n \"peerDependencies\": {\n \"@types/node\": \"^20.19.0 || >=22.12.0\",\n \"@vitejs/devtools\": \"^0.1.0\",\n \"esbuild\": \"^0.27.0\",\n \"jiti\": \">=1.21.0\",\n \"less\": \"^4.0.0\",\n \"sass\": \"^1.70.0\",\n \"sass-embedded\": \"^1.70.0\",\n \"stylus\": \">=0.54.8\",\n \"sugarss\": \"^5.0.0\",\n \"terser\": \"^5.16.0\",\n \"tsx\": \"^4.8.1\",\n \"yaml\": \"^2.4.2\"\n },\n \"peerDependenciesMeta\": {\n \"@types/node\": {\n \"optional\": true\n },\n \"@vitejs/devtools\": {\n \"optional\": true\n },\n \"esbuild\": {\n \"optional\": true\n },\n \"jiti\": {\n \"optional\": true\n },\n \"less\": {\n \"optional\": true\n },\n \"sass\": {\n \"optional\": true\n },\n \"sass-embedded\": {\n \"optional\": true\n },\n \"stylus\": {\n \"optional\": true\n },\n \"sugarss\": {\n \"optional\": true\n },\n \"terser\": {\n \"optional\": true\n },\n \"tsx\": {\n \"optional\": true\n },\n \"yaml\": {\n \"optional\": true\n }\n }\n }\n }\n}\n", h = "{\n \"name\": \"__CUSTOM_VIZ_NAME__\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"vite build\",\n \"dev\": \"vite build --watch\",\n \"type-check\": \"tsc --noEmit\"\n },\n \"devDependencies\": {\n \"@metabase/custom-viz\": \"__CUSTOM_VIZ_VERSION__\",\n \"@types/react\": \"^19.2.14\",\n \"react\": \"^19.1.0\",\n \"typescript\": \"^5.9.3\",\n \"vite\": \"^8.0.0\"\n }\n}\n", g = "{\n \"compilerOptions\": {\n \"target\": \"ES2020\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"jsx\": \"react-jsx\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"outDir\": \"dist\",\n \"declaration\": true\n },\n \"include\": [\"src\"]\n}\n", _ = "import { cpSync, existsSync, watch } from \"fs\";\nimport { createServer } from \"http\";\nimport { resolve } from \"path\";\nimport { defineConfig } from \"vite\";\n\n/**\n * Vite plugin that replaces `react` and `react/jsx-runtime` imports with\n * virtual modules that read from Metabase's `window.__METABASE_VIZ_API__`.\n *\n * This is necessary because the ES module output format cannot use\n * `output.globals`, and bare `import 'react'` would fail in the browser.\n */\nfunction metabaseVizExternals() {\n const VIRTUAL_REACT = \"\\0virtual:react\";\n const VIRTUAL_JSX_RUNTIME = \"\\0virtual:react/jsx-runtime\";\n return {\n name: \"metabase-viz-externals\",\n enforce: \"pre\" as const,\n\n resolveId(source) {\n if (source === \"react\") {\n return VIRTUAL_REACT;\n }\n if (source === \"react/jsx-runtime\") {\n return VIRTUAL_JSX_RUNTIME;\n }\n return null;\n },\n\n load(id) {\n if (id === VIRTUAL_REACT) {\n return [\n \"const React = window.__METABASE_VIZ_API__.React;\",\n \"export default React;\",\n \"export const { useState, useEffect, useRef, useCallback, useMemo, useReducer, useContext, createElement, Fragment } = React;\",\n ].join(\"\\n\");\n }\n if (id === VIRTUAL_JSX_RUNTIME) {\n return [\n \"const jsxRuntime = window.__METABASE_VIZ_API__.jsxRuntime;\",\n \"export const { jsx, jsxs, Fragment } = jsxRuntime;\",\n ].join(\"\\n\");\n }\n return null;\n },\n };\n}\n\nconst DEV_PORT = 5174;\n\n/**\n * Vite plugin that starts a dev server serving both static files from dist/\n * and an SSE endpoint at /__sse for hot-reload notifications.\n * Metabase's frontend connects to /__sse on the same origin as dev_bundle_url.\n */\nfunction metabaseDevServer() {\n const clients = new Set<import(\"http\").ServerResponse>();\n let server: ReturnType<typeof createServer> | null = null;\n\n return {\n name: \"metabase-dev-server\",\n\n buildStart() {\n if (server) {\n return;\n }\n\n const distDir = resolve(__dirname, \"dist\");\n\n server = createServer((req, res) => {\n const url = req.url ?? \"/\";\n\n // SSE endpoint for hot-reload\n if (url === \"/__sse\") {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n clients.add(res);\n req.on(\"close\", () => clients.delete(res));\n return;\n }\n\n // CORS headers for all static responses\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n\n // Serve static files from dist/\n const { readFile, stat } = require(\"fs\");\n const { join, extname } = require(\"path\");\n\n const filePath =\n url === \"/\" ? join(distDir, \"index.html\") : join(distDir, url);\n\n // Prevent directory traversal\n if (!filePath.startsWith(distDir)) {\n res.writeHead(403);\n res.end(\"Forbidden\");\n return;\n }\n\n stat(filePath, (err: NodeJS.ErrnoException | null) => {\n if (err) {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const mimeTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n };\n const contentType =\n mimeTypes[extname(filePath)] ?? \"application/octet-stream\";\n\n readFile(\n filePath,\n (readErr: NodeJS.ErrnoException | null, data: Buffer) => {\n if (readErr) {\n res.writeHead(500);\n res.end(\"Internal server error\");\n return;\n }\n res.writeHead(200, { \"Content-Type\": contentType });\n res.end(data);\n },\n );\n });\n });\n\n server.listen(DEV_PORT, () => {\n console.log(\n `[custom-viz] Dev server listening on http://localhost:${DEV_PORT}`,\n );\n });\n\n // Watch public/assets/ for changes — copy to dist/assets/ and notify\n const assetsDir = resolve(__dirname, \"public/assets\");\n if (existsSync(assetsDir)) {\n watch(assetsDir, { recursive: true }, (_event, filename) => {\n if (!filename) {\n return;\n }\n cpSync(\n resolve(assetsDir, filename),\n resolve(__dirname, \"dist/assets\", filename),\n );\n for (const client of clients) {\n client.write(\"data: reload\\n\\n\");\n }\n console.log(\n `[custom-viz] Asset changed: ${filename}, notified ${clients.size} client(s)`,\n );\n });\n }\n },\n\n closeBundle() {\n for (const client of clients) {\n client.write(\"data: reload\\n\\n\");\n }\n console.log(\n `[custom-viz] Build complete, notified ${clients.size} client(s)`,\n );\n },\n };\n}\n\nconst isWatch = process.argv.includes(\"--watch\");\n\nexport default defineConfig({\n plugins: [metabaseVizExternals(), ...(isWatch ? [metabaseDevServer()] : [])],\n publicDir: \"public\",\n define: {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n \"process.env\": JSON.stringify({}),\n },\n build: {\n outDir: \"dist\",\n lib: {\n entry: resolve(__dirname, \"src/index.tsx\"),\n formats: [\"iife\"],\n fileName: () => \"index.js\",\n name: \"__customVizPlugin__\",\n },\n },\n});\n", v = "__CUSTOM_VIZ_NAME__", y = "__CUSTOM_VIZ_VERSION__";
10
+ function b(e, t) {
11
+ return e.split(v).join(t);
10
12
  }
11
- function f(e) {
12
- return d(s, e);
13
+ function x(e) {
14
+ return e.replace("../", "@metabase/custom-viz");
13
15
  }
14
- function p() {
15
- return l;
16
+ function S(e) {
17
+ return b(h, e).split(y).join(l);
16
18
  }
17
- function m() {
18
- return c;
19
+ function C(e) {
20
+ return b(m, e).split(y).join(l);
19
21
  }
20
- function h(e) {
21
- return d(o, e);
22
+ function w() {
23
+ return _;
22
24
  }
23
- function g() {
24
- return a;
25
+ function T() {
26
+ return g;
27
+ }
28
+ function E(e) {
29
+ return b(x(f), e);
30
+ }
31
+ function D(e) {
32
+ return b(p, e);
33
+ }
34
+ function O() {
35
+ return d;
36
+ }
37
+ var k = a(i(c(import.meta.url)), "templates");
38
+ function A(e) {
39
+ return t(a(k, e));
40
+ }
41
+ function j() {
42
+ return u;
43
+ }
44
+ function M(e) {
45
+ let t = JSON.parse(e), n = JSON.parse(h.split(v).join("__placeholder__").split(y).join(l));
46
+ return t.devDependencies = {
47
+ ...t.devDependencies,
48
+ ...n.devDependencies
49
+ }, t.scripts = {
50
+ ...t.scripts,
51
+ ...n.scripts
52
+ }, JSON.stringify(t, null, 2) + "\n";
25
53
  }
26
54
  //#endregion
27
55
  //#region src/cli.ts
28
- var _ = new i();
29
- _.name("metabase-custom-viz").description("CLI for creating custom visualizations for Metabase").version("0.0.1"), _.command("init").description("Scaffold a new custom visualization").argument("<name>", "Name of the custom visualization").action(async (i) => {
30
- let a = i.trim().replace(/\s+/g, "-").toLowerCase();
31
- (!a || !/^[a-z0-9@][a-z0-9._\-/]*$/.test(a)) && (console.error(`Error: "${i}" is not a valid project name. Use letters, numbers, hyphens, and dots.`), process.exit(1)), e(a) && (console.error(`Error: Directory "${a}" already exists.`), process.exit(1)), console.log(`Scaffolding custom visualization: ${a}\n`), await t(r(a, "src"), { recursive: !0 }), await Promise.all([
32
- n(r(a, "package.json"), f(a)),
33
- n(r(a, "vite.config.ts"), p()),
34
- n(r(a, "tsconfig.json"), m()),
35
- n(r(a, "src", "index.tsx"), h(a)),
36
- n(r(a, ".gitignore"), g())
37
- ]), console.log("Created files:"), console.log(` ${a}/package.json`), console.log(` ${a}/vite.config.ts`), console.log(` ${a}/tsconfig.json`), console.log(` ${a}/src/index.tsx`), console.log(` ${a}/.gitignore`), console.log(), console.log("Next steps:"), console.log(` cd ${a}`), console.log(" npm install"), console.log(" npm run dev # Watch mode"), console.log(" npm run build # Production build");
38
- }), _.parse();
56
+ var N = new s();
57
+ N.name("metabase-custom-viz").description("CLI for creating custom visualizations for Metabase").version(l), N.command("init").description("Scaffold a new custom visualization").argument("<name>", "Name of the custom visualization").action(async (t) => {
58
+ let i = t.trim().replace(/\s+/g, "-").toLowerCase();
59
+ (!i || !/^[a-z0-9@][a-z0-9._\-/]*$/.test(i)) && (console.error(`Error: "${t}" is not a valid project name. Use letters, numbers, hyphens, and dots.`), process.exit(1)), e(i) && (console.error(`Error: Directory "${i}" already exists.`), process.exit(1)), console.log(`Scaffolding custom visualization: ${i}\n`), await Promise.all([n(a(i, "src"), { recursive: !0 }), n(a(i, "public", "assets"), { recursive: !0 })]), await Promise.all([
60
+ r(a(i, "package.json"), S(i)),
61
+ r(a(i, "package-lock.json"), C(i)),
62
+ r(a(i, "vite.config.ts"), w()),
63
+ r(a(i, "tsconfig.json"), T()),
64
+ r(a(i, "src", "index.tsx"), E(i)),
65
+ r(a(i, "metabase-plugin.json"), D(i)),
66
+ r(a(i, "public", "assets", "icon.svg"), O()),
67
+ r(a(i, "public", "assets", "thumbs-up.png"), A("thumbs-up.png")),
68
+ r(a(i, "public", "assets", "thumbs-down.png"), A("thumbs-down.png")),
69
+ r(a(i, ".gitignore"), j())
70
+ ]), console.log("Created files:"), console.log(` ${i}/package.json`), console.log(` ${i}/package-lock.json`), console.log(` ${i}/vite.config.ts`), console.log(` ${i}/tsconfig.json`), console.log(` ${i}/src/index.tsx`), console.log(` ${i}/metabase-plugin.json`), console.log(` ${i}/public/assets/icon.svg`), console.log(` ${i}/public/assets/thumbs-up.png`), console.log(` ${i}/public/assets/thumbs-down.png`), console.log(` ${i}/.gitignore`), console.log(), console.log("Next steps:"), console.log(` cd ${i}`), console.log(" npm install"), console.log(" npm run dev # Watch mode"), console.log(" npm run build # Production build");
71
+ }), N.command("upgrade").description("Upgrade an existing custom visualization to the latest template version").action(async () => {
72
+ let n = process.cwd(), i = a(n, "package.json");
73
+ e(i) || (console.error("Error: No package.json found. Run this command from the root of a custom visualization project."), process.exit(1));
74
+ let o;
75
+ try {
76
+ o = JSON.parse(t(i, "utf-8"));
77
+ } catch {
78
+ console.error("Error: Could not parse package.json."), process.exit(1);
79
+ }
80
+ let s = o.devDependencies?.["@metabase/custom-viz"];
81
+ if (s || (console.error("Error: @metabase/custom-viz not found in devDependencies. Is this a custom visualization project?"), process.exit(1)), s === "0.0.1-alpha.10") {
82
+ console.log(`Already up to date (v${l}). No changes needed.`);
83
+ return;
84
+ }
85
+ if (console.log(`Upgrading from @metabase/custom-viz ${s} → ${l}\n`), console.log("The following changes will be made:\n"), console.log(" vite.config.ts — Replace with the latest build configuration"), console.log(" tsconfig.json — Replace with the latest TypeScript configuration"), console.log(" .gitignore — Replace with the latest gitignore rules"), console.log(" package.json — Update devDependencies and scripts to latest versions"), console.log(), console.log("Your source code (src/), assets (public/), and metabase-plugin.json will NOT be modified.\n"), !await P("Proceed with upgrade?")) {
86
+ console.log("Upgrade cancelled.");
87
+ return;
88
+ }
89
+ console.log();
90
+ let c = [];
91
+ await r(a(n, "vite.config.ts"), w()), c.push("vite.config.ts"), await r(a(n, "tsconfig.json"), T()), c.push("tsconfig.json"), await r(a(n, ".gitignore"), j()), c.push(".gitignore"), await r(i, M(t(i, "utf-8"))), c.push("package.json"), console.log("Updated files:");
92
+ for (let e of c) console.log(` ${e}`);
93
+ console.log(), console.log("Next steps:"), console.log(" npm install # Install updated dependencies");
94
+ });
95
+ function P(e) {
96
+ let t = o({
97
+ input: process.stdin,
98
+ output: process.stdout
99
+ });
100
+ return new Promise((n) => {
101
+ t.question(`${e} (y/N) `, (e) => {
102
+ t.close(), n(e.trim().toLowerCase() === "y");
103
+ });
104
+ });
105
+ }
106
+ N.parse();
39
107
  //#endregion
@@ -0,0 +1,40 @@
1
+ import { ColumnPredicate, ColumnTypes } from './types/column-types';
2
+ import { Column } from './types/data';
3
+ export declare const isDate: ColumnPredicate;
4
+ export declare const isNumeric: ColumnPredicate;
5
+ export declare const isInteger: ColumnPredicate;
6
+ export declare const isBoolean: ColumnPredicate;
7
+ export declare const isString: ColumnPredicate;
8
+ export declare const isStringLike: ColumnPredicate;
9
+ export declare const isSummable: ColumnPredicate;
10
+ export declare const isNumericBaseType: ColumnPredicate;
11
+ export declare const isDateWithoutTime: ColumnPredicate;
12
+ export declare const isNumber: ColumnPredicate;
13
+ export declare const isFloat: ColumnPredicate;
14
+ export declare const isTime: ColumnPredicate;
15
+ export declare const isFK: ColumnPredicate;
16
+ export declare const isPK: ColumnPredicate;
17
+ export declare const isEntityName: ColumnPredicate;
18
+ export declare const isTitle: ColumnPredicate;
19
+ export declare const isProduct: ColumnPredicate;
20
+ export declare const isSource: ColumnPredicate;
21
+ export declare const isAddress: ColumnPredicate;
22
+ export declare const isScore: ColumnPredicate;
23
+ export declare const isQuantity: ColumnPredicate;
24
+ export declare const isCategory: ColumnPredicate;
25
+ export declare const isAny: ColumnPredicate;
26
+ export declare const isState: ColumnPredicate;
27
+ export declare const isCountry: ColumnPredicate;
28
+ export declare const isCoordinate: ColumnPredicate;
29
+ export declare const isLatitude: ColumnPredicate;
30
+ export declare const isLongitude: ColumnPredicate;
31
+ export declare const isCurrency: ColumnPredicate;
32
+ export declare const isPercentage: ColumnPredicate;
33
+ export declare const isID: ColumnPredicate;
34
+ export declare const isURL: ColumnPredicate;
35
+ export declare const isEmail: ColumnPredicate;
36
+ export declare const isAvatarURL: ColumnPredicate;
37
+ export declare const isImageURL: ColumnPredicate;
38
+ export declare const hasLatitudeAndLongitudeColumns: (cols: Column[]) => boolean;
39
+ export type { ColumnPredicate, ColumnTypes };
40
+ //# sourceMappingURL=column-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-types.d.ts","sourceRoot":"","sources":["../src/column-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAQ3C,eAAO,MAAM,MAAM,EAAE,eAA2C,CAAC;AACjE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,QAAQ,EAAE,eAA6C,CAAC;AACrE,eAAO,MAAM,YAAY,EAAE,eAAiD,CAAC;AAC7E,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,iBAAiB,EAAE,eACH,CAAC;AAC9B,eAAO,MAAM,iBAAiB,EAAE,eACH,CAAC;AAC9B,eAAO,MAAM,QAAQ,EAAE,eAA6C,CAAC;AACrE,eAAO,MAAM,OAAO,EAAE,eAA4C,CAAC;AACnE,eAAO,MAAM,MAAM,EAAE,eAA2C,CAAC;AACjE,eAAO,MAAM,IAAI,EAAE,eAAyC,CAAC;AAC7D,eAAO,MAAM,IAAI,EAAE,eAAyC,CAAC;AAC7D,eAAO,MAAM,YAAY,EAAE,eAAiD,CAAC;AAC7E,eAAO,MAAM,OAAO,EAAE,eAA4C,CAAC;AACnE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,QAAQ,EAAE,eAA6C,CAAC;AACrE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,OAAO,EAAE,eAA4C,CAAC;AACnE,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,KAAK,EAAE,eAA0C,CAAC;AAC/D,eAAO,MAAM,OAAO,EAAE,eAA4C,CAAC;AACnE,eAAO,MAAM,SAAS,EAAE,eAA8C,CAAC;AACvE,eAAO,MAAM,YAAY,EAAE,eAAiD,CAAC;AAC7E,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,WAAW,EAAE,eAAgD,CAAC;AAC3E,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,YAAY,EAAE,eAAiD,CAAC;AAC7E,eAAO,MAAM,IAAI,EAAE,eAAyC,CAAC;AAC7D,eAAO,MAAM,KAAK,EAAE,eAA0C,CAAC;AAC/D,eAAO,MAAM,OAAO,EAAE,eAA4C,CAAC;AACnE,eAAO,MAAM,WAAW,EAAE,eAAgD,CAAC;AAC3E,eAAO,MAAM,UAAU,EAAE,eAA+C,CAAC;AACzE,eAAO,MAAM,8BAA8B,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAEnB,CAAC;AAE/C,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { FormatValue, FormatValueOptions } from './types/format';
2
+ export declare const formatValue: FormatValue;
3
+ export type { FormatValue, FormatValueOptions };
4
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAItE,eAAO,MAAM,WAAW,EAAE,WACgC,CAAC;AAE3D,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
+ export * from './column-types';
2
+ export * from './format';
3
+ export * from './measure-text';
1
4
  export * from './types';
2
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,11 @@
1
- //#region src/types/date-time.ts
2
- var e = [
1
+ //#region src/column-types.ts
2
+ function e() {
3
+ return window.__METABASE_VIZ_API__.columnTypes;
4
+ }
5
+ var t = (t) => e().isDate(t), n = (t) => e().isNumeric(t), r = (t) => e().isInteger(t), i = (t) => e().isBoolean(t), a = (t) => e().isString(t), o = (t) => e().isStringLike(t), s = (t) => e().isSummable(t), c = (t) => e().isNumericBaseType(t), l = (t) => e().isDateWithoutTime(t), u = (t) => e().isNumber(t), d = (t) => e().isFloat(t), f = (t) => e().isTime(t), p = (t) => e().isFK(t), m = (t) => e().isPK(t), h = (t) => e().isEntityName(t), g = (t) => e().isTitle(t), _ = (t) => e().isProduct(t), v = (t) => e().isSource(t), y = (t) => e().isAddress(t), b = (t) => e().isScore(t), x = (t) => e().isQuantity(t), S = (t) => e().isCategory(t), C = (t) => e().isAny(t), w = (t) => e().isState(t), T = (t) => e().isCountry(t), E = (t) => e().isCoordinate(t), D = (t) => e().isLatitude(t), O = (t) => e().isLongitude(t), k = (t) => e().isCurrency(t), A = (t) => e().isPercentage(t), j = (t) => e().isID(t), M = (t) => e().isURL(t), N = (t) => e().isEmail(t), P = (t) => e().isAvatarURL(t), F = (t) => e().isImageURL(t), I = (t) => e().hasLatitudeAndLongitudeColumns(t), L = (e, t) => window.__METABASE_VIZ_API__.formatValue(e, t), R = () => ({
6
+ width: 0,
7
+ height: 0
8
+ }), z = () => 0, B = () => 0, V = [
3
9
  "minute",
4
10
  "hour",
5
11
  "day",
@@ -7,7 +13,7 @@ var e = [
7
13
  "month",
8
14
  "quarter",
9
15
  "year"
10
- ], t = [
16
+ ], H = [
11
17
  "minute-of-hour",
12
18
  "hour-of-day",
13
19
  "day-of-week",
@@ -16,6 +22,6 @@ var e = [
16
22
  "week-of-year",
17
23
  "month-of-year",
18
24
  "quarter-of-year"
19
- ], n = [...e, ...t];
25
+ ], U = [...V, ...H];
20
26
  //#endregion
21
- export { e as dateTimeAbsoluteUnits, t as dateTimeRelativeUnits, n as dateTimeUnits };
27
+ export { V as dateTimeAbsoluteUnits, H as dateTimeRelativeUnits, U as dateTimeUnits, L as formatValue, I as hasLatitudeAndLongitudeColumns, y as isAddress, C as isAny, P as isAvatarURL, i as isBoolean, S as isCategory, E as isCoordinate, T as isCountry, k as isCurrency, t as isDate, l as isDateWithoutTime, N as isEmail, h as isEntityName, p as isFK, d as isFloat, j as isID, F as isImageURL, r as isInteger, D as isLatitude, O as isLongitude, u as isNumber, n as isNumeric, c as isNumericBaseType, m as isPK, A as isPercentage, _ as isProduct, x as isQuantity, b as isScore, v as isSource, w as isState, a as isString, o as isStringLike, s as isSummable, f as isTime, g as isTitle, M as isURL, R as measureText, B as measureTextHeight, z as measureTextWidth };
@@ -0,0 +1,5 @@
1
+ import { TextHeightMeasurer, TextMeasurer, TextWidthMeasurer } from './types/measure-text';
2
+ export declare const measureText: TextMeasurer;
3
+ export declare const measureTextWidth: TextWidthMeasurer;
4
+ export declare const measureTextHeight: TextHeightMeasurer;
5
+ //# sourceMappingURL=measure-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure-text.d.ts","sourceRoot":"","sources":["../src/measure-text.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,WAAW,EAAE,YAA8C,CAAC;AACzE,eAAO,MAAM,gBAAgB,EAAE,iBAA2B,CAAC;AAC3D,eAAO,MAAM,iBAAiB,EAAE,kBAA4B,CAAC"}
@@ -0,0 +1,3 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M1.79978 6.86661C1.65041 7.01583 1.53192 7.19302 1.45107 7.38806C1.37023 7.58309 1.32861 7.79215 1.32861 8.00328C1.32861 8.21441 1.37023 8.42347 1.45107 8.61851C1.53192 8.81354 1.65041 8.99073 1.79978 9.13995L6.85978 14.1999C7.00899 14.3493 7.18618 14.4678 7.38122 14.5487C7.57626 14.6295 7.78531 14.6711 7.99644 14.6711C8.20757 14.6711 8.41663 14.6295 8.61167 14.5487C8.80671 14.4678 8.9839 14.3493 9.13311 14.1999L14.1931 9.13995C14.3425 8.99073 14.461 8.81354 14.5418 8.61851C14.6227 8.42347 14.6643 8.21441 14.6643 8.00328C14.6643 7.79215 14.6227 7.58309 14.5418 7.38806C14.461 7.19302 14.3425 7.01583 14.1931 6.86661L9.13311 1.80661C8.9839 1.65725 8.80671 1.53875 8.61167 1.45791C8.41663 1.37706 8.20757 1.33545 7.99644 1.33545C7.78531 1.33545 7.57626 1.37706 7.38122 1.45791C7.18618 1.53875 7.00899 1.65725 6.85978 1.80661L1.79978 6.86661Z" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>