@outsidedata/dolex 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 +154 -0
- package/data/geo/continents/africa.json +1 -0
- package/data/geo/continents/asia.json +1 -0
- package/data/geo/continents/europe.json +1 -0
- package/data/geo/continents/north-america.json +1 -0
- package/data/geo/continents/oceania.json +1 -0
- package/data/geo/continents/south-america.json +1 -0
- package/data/geo/countries/argentina/provinces.json +1 -0
- package/data/geo/countries/australia/states.json +1 -0
- package/data/geo/countries/brazil/states.json +1 -0
- package/data/geo/countries/canada/provinces.json +1 -0
- package/data/geo/countries/china/provinces.json +1 -0
- package/data/geo/countries/colombia/departments.json +1 -0
- package/data/geo/countries/france/departments.json +1 -0
- package/data/geo/countries/germany/regions.json +1 -0
- package/data/geo/countries/india/states.json +1 -0
- package/data/geo/countries/italy/regions.json +1 -0
- package/data/geo/countries/japan/prefectures.json +1 -0
- package/data/geo/countries/mexico/states.json +1 -0
- package/data/geo/countries/russia/regions.json +1 -0
- package/data/geo/countries/south-africa/provinces.json +1 -0
- package/data/geo/countries/south-korea/provinces.json +1 -0
- package/data/geo/countries/spain/comunidades.json +1 -0
- package/data/geo/countries/uk/counties.json +1 -0
- package/data/geo/countries-110m.json +1 -0
- package/data/geo/countries-50m.json +1 -0
- package/data/geo/countries-no-antarctica.json +1 -0
- package/data/geo/states-10m.json +1 -0
- package/data/geo/us/congressional-districts-20m.json +1 -0
- package/data/geo/us/counties-10m.json +1 -0
- package/data/geo/us/counties-albers-10m.json +1 -0
- package/data/geo/us/nation-10m.json +1 -0
- package/data/geo/us/nation-albers-10m.json +1 -0
- package/data/geo/us/states-10m.json +1 -0
- package/data/geo/us/states-albers-10m.json +1 -0
- package/dist/src/analysis/classify.d.ts +4 -0
- package/dist/src/analysis/classify.d.ts.map +1 -0
- package/dist/src/analysis/classify.js +60 -0
- package/dist/src/analysis/classify.js.map +1 -0
- package/dist/src/analysis/index.d.ts +5 -0
- package/dist/src/analysis/index.d.ts.map +1 -0
- package/dist/src/analysis/index.js +4 -0
- package/dist/src/analysis/index.js.map +1 -0
- package/dist/src/analysis/planner.d.ts +4 -0
- package/dist/src/analysis/planner.d.ts.map +1 -0
- package/dist/src/analysis/planner.js +51 -0
- package/dist/src/analysis/planner.js.map +1 -0
- package/dist/src/analysis/rules.d.ts +5 -0
- package/dist/src/analysis/rules.d.ts.map +1 -0
- package/dist/src/analysis/rules.js +139 -0
- package/dist/src/analysis/rules.js.map +1 -0
- package/dist/src/analysis/types.d.ts +39 -0
- package/dist/src/analysis/types.d.ts.map +1 -0
- package/dist/src/analysis/types.js +2 -0
- package/dist/src/analysis/types.js.map +1 -0
- package/dist/src/connectors/csv.d.ts +11 -0
- package/dist/src/connectors/csv.d.ts.map +1 -0
- package/dist/src/connectors/csv.js +330 -0
- package/dist/src/connectors/csv.js.map +1 -0
- package/dist/src/connectors/dsl-compiler.d.ts +21 -0
- package/dist/src/connectors/dsl-compiler.d.ts.map +1 -0
- package/dist/src/connectors/dsl-compiler.js +313 -0
- package/dist/src/connectors/dsl-compiler.js.map +1 -0
- package/dist/src/connectors/dsl-validator.d.ts +19 -0
- package/dist/src/connectors/dsl-validator.d.ts.map +1 -0
- package/dist/src/connectors/dsl-validator.js +434 -0
- package/dist/src/connectors/dsl-validator.js.map +1 -0
- package/dist/src/connectors/index.d.ts +12 -0
- package/dist/src/connectors/index.d.ts.map +1 -0
- package/dist/src/connectors/index.js +13 -0
- package/dist/src/connectors/index.js.map +1 -0
- package/dist/src/connectors/js-aggregation.d.ts +22 -0
- package/dist/src/connectors/js-aggregation.d.ts.map +1 -0
- package/dist/src/connectors/js-aggregation.js +342 -0
- package/dist/src/connectors/js-aggregation.js.map +1 -0
- package/dist/src/connectors/manager.d.ts +92 -0
- package/dist/src/connectors/manager.d.ts.map +1 -0
- package/dist/src/connectors/manager.js +341 -0
- package/dist/src/connectors/manager.js.map +1 -0
- package/dist/src/connectors/mysql.d.ts +11 -0
- package/dist/src/connectors/mysql.d.ts.map +1 -0
- package/dist/src/connectors/mysql.js +293 -0
- package/dist/src/connectors/mysql.js.map +1 -0
- package/dist/src/connectors/postgres.d.ts +11 -0
- package/dist/src/connectors/postgres.d.ts.map +1 -0
- package/dist/src/connectors/postgres.js +289 -0
- package/dist/src/connectors/postgres.js.map +1 -0
- package/dist/src/connectors/sqlite.d.ts +10 -0
- package/dist/src/connectors/sqlite.d.ts.map +1 -0
- package/dist/src/connectors/sqlite.js +297 -0
- package/dist/src/connectors/sqlite.js.map +1 -0
- package/dist/src/connectors/types.d.ts +57 -0
- package/dist/src/connectors/types.d.ts.map +1 -0
- package/dist/src/connectors/types.js +5 -0
- package/dist/src/connectors/types.js.map +1 -0
- package/dist/src/index.d.ts +26 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +27 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/app-shell.d.ts +15 -0
- package/dist/src/mcp/app-shell.d.ts.map +1 -0
- package/dist/src/mcp/app-shell.js +260 -0
- package/dist/src/mcp/app-shell.js.map +1 -0
- package/dist/src/mcp/index.d.ts +28 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +262 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/prompts.d.ts +3 -0
- package/dist/src/mcp/prompts.d.ts.map +1 -0
- package/dist/src/mcp/prompts.js +30 -0
- package/dist/src/mcp/prompts.js.map +1 -0
- package/dist/src/mcp/spec-store.d.ts +37 -0
- package/dist/src/mcp/spec-store.d.ts.map +1 -0
- package/dist/src/mcp/spec-store.js +99 -0
- package/dist/src/mcp/spec-store.js.map +1 -0
- package/dist/src/mcp/tools/analyze.d.ts +22 -0
- package/dist/src/mcp/tools/analyze.d.ts.map +1 -0
- package/dist/src/mcp/tools/analyze.js +34 -0
- package/dist/src/mcp/tools/analyze.js.map +1 -0
- package/dist/src/mcp/tools/bug-report.d.ts +42 -0
- package/dist/src/mcp/tools/bug-report.d.ts.map +1 -0
- package/dist/src/mcp/tools/bug-report.js +154 -0
- package/dist/src/mcp/tools/bug-report.js.map +1 -0
- package/dist/src/mcp/tools/dashboard-refine.d.ts +23 -0
- package/dist/src/mcp/tools/dashboard-refine.d.ts.map +1 -0
- package/dist/src/mcp/tools/dashboard-refine.js +394 -0
- package/dist/src/mcp/tools/dashboard-refine.js.map +1 -0
- package/dist/src/mcp/tools/dashboard.d.ts +14 -0
- package/dist/src/mcp/tools/dashboard.d.ts.map +1 -0
- package/dist/src/mcp/tools/dashboard.js +40 -0
- package/dist/src/mcp/tools/dashboard.js.map +1 -0
- package/dist/src/mcp/tools/dsl-schemas.d.ts +1540 -0
- package/dist/src/mcp/tools/dsl-schemas.d.ts.map +1 -0
- package/dist/src/mcp/tools/dsl-schemas.js +237 -0
- package/dist/src/mcp/tools/dsl-schemas.js.map +1 -0
- package/dist/src/mcp/tools/export-html.d.ts +18 -0
- package/dist/src/mcp/tools/export-html.d.ts.map +1 -0
- package/dist/src/mcp/tools/export-html.js +40 -0
- package/dist/src/mcp/tools/export-html.js.map +1 -0
- package/dist/src/mcp/tools/list-patterns.d.ts +9 -0
- package/dist/src/mcp/tools/list-patterns.d.ts.map +1 -0
- package/dist/src/mcp/tools/list-patterns.js +286 -0
- package/dist/src/mcp/tools/list-patterns.js.map +1 -0
- package/dist/src/mcp/tools/operation-log.d.ts +54 -0
- package/dist/src/mcp/tools/operation-log.d.ts.map +1 -0
- package/dist/src/mcp/tools/operation-log.js +70 -0
- package/dist/src/mcp/tools/operation-log.js.map +1 -0
- package/dist/src/mcp/tools/query-data.d.ts +43 -0
- package/dist/src/mcp/tools/query-data.d.ts.map +1 -0
- package/dist/src/mcp/tools/query-data.js +65 -0
- package/dist/src/mcp/tools/query-data.js.map +1 -0
- package/dist/src/mcp/tools/query-source.d.ts +336 -0
- package/dist/src/mcp/tools/query-source.d.ts.map +1 -0
- package/dist/src/mcp/tools/query-source.js +62 -0
- package/dist/src/mcp/tools/query-source.js.map +1 -0
- package/dist/src/mcp/tools/refine.d.ts +24 -0
- package/dist/src/mcp/tools/refine.d.ts.map +1 -0
- package/dist/src/mcp/tools/refine.js +345 -0
- package/dist/src/mcp/tools/refine.js.map +1 -0
- package/dist/src/mcp/tools/result-cache.d.ts +24 -0
- package/dist/src/mcp/tools/result-cache.d.ts.map +1 -0
- package/dist/src/mcp/tools/result-cache.js +48 -0
- package/dist/src/mcp/tools/result-cache.js.map +1 -0
- package/dist/src/mcp/tools/screenshot.d.ts +30 -0
- package/dist/src/mcp/tools/screenshot.d.ts.map +1 -0
- package/dist/src/mcp/tools/screenshot.js +79 -0
- package/dist/src/mcp/tools/screenshot.js.map +1 -0
- package/dist/src/mcp/tools/server-privacy.d.ts +28 -0
- package/dist/src/mcp/tools/server-privacy.d.ts.map +1 -0
- package/dist/src/mcp/tools/server-privacy.js +77 -0
- package/dist/src/mcp/tools/server-privacy.js.map +1 -0
- package/dist/src/mcp/tools/shared.d.ts +49 -0
- package/dist/src/mcp/tools/shared.d.ts.map +1 -0
- package/dist/src/mcp/tools/shared.js +170 -0
- package/dist/src/mcp/tools/shared.js.map +1 -0
- package/dist/src/mcp/tools/sources.d.ts +160 -0
- package/dist/src/mcp/tools/sources.d.ts.map +1 -0
- package/dist/src/mcp/tools/sources.js +177 -0
- package/dist/src/mcp/tools/sources.js.map +1 -0
- package/dist/src/mcp/tools/visualize-from-source.d.ts +518 -0
- package/dist/src/mcp/tools/visualize-from-source.d.ts.map +1 -0
- package/dist/src/mcp/tools/visualize-from-source.js +61 -0
- package/dist/src/mcp/tools/visualize-from-source.js.map +1 -0
- package/dist/src/mcp/tools/visualize.d.ts +325 -0
- package/dist/src/mcp/tools/visualize.d.ts.map +1 -0
- package/dist/src/mcp/tools/visualize.js +190 -0
- package/dist/src/mcp/tools/visualize.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/bar.d.ts +10 -0
- package/dist/src/patterns/definitions/comparison/bar.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/bar.js +99 -0
- package/dist/src/patterns/definitions/comparison/bar.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/bullet.d.ts +11 -0
- package/dist/src/patterns/definitions/comparison/bullet.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/bullet.js +121 -0
- package/dist/src/patterns/definitions/comparison/bullet.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/bump-chart.d.ts +11 -0
- package/dist/src/patterns/definitions/comparison/bump-chart.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/bump-chart.js +124 -0
- package/dist/src/patterns/definitions/comparison/bump-chart.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/connected-dot-plot.d.ts +11 -0
- package/dist/src/patterns/definitions/comparison/connected-dot-plot.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/connected-dot-plot.js +99 -0
- package/dist/src/patterns/definitions/comparison/connected-dot-plot.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/diverging-bar.d.ts +10 -0
- package/dist/src/patterns/definitions/comparison/diverging-bar.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/diverging-bar.js +97 -0
- package/dist/src/patterns/definitions/comparison/diverging-bar.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/grouped-bar.d.ts +6 -0
- package/dist/src/patterns/definitions/comparison/grouped-bar.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/grouped-bar.js +103 -0
- package/dist/src/patterns/definitions/comparison/grouped-bar.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/index.d.ts +9 -0
- package/dist/src/patterns/definitions/comparison/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/index.js +9 -0
- package/dist/src/patterns/definitions/comparison/index.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/lollipop.d.ts +11 -0
- package/dist/src/patterns/definitions/comparison/lollipop.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/lollipop.js +122 -0
- package/dist/src/patterns/definitions/comparison/lollipop.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/slope-chart.d.ts +10 -0
- package/dist/src/patterns/definitions/comparison/slope-chart.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/slope-chart.js +99 -0
- package/dist/src/patterns/definitions/comparison/slope-chart.js.map +1 -0
- package/dist/src/patterns/definitions/comparison/waterfall.d.ts +6 -0
- package/dist/src/patterns/definitions/comparison/waterfall.d.ts.map +1 -0
- package/dist/src/patterns/definitions/comparison/waterfall.js +85 -0
- package/dist/src/patterns/definitions/comparison/waterfall.js.map +1 -0
- package/dist/src/patterns/definitions/composition/circle-pack.d.ts +9 -0
- package/dist/src/patterns/definitions/composition/circle-pack.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/circle-pack.js +103 -0
- package/dist/src/patterns/definitions/composition/circle-pack.js.map +1 -0
- package/dist/src/patterns/definitions/composition/donut.d.ts +6 -0
- package/dist/src/patterns/definitions/composition/donut.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/donut.js +101 -0
- package/dist/src/patterns/definitions/composition/donut.js.map +1 -0
- package/dist/src/patterns/definitions/composition/icicle.d.ts +10 -0
- package/dist/src/patterns/definitions/composition/icicle.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/icicle.js +114 -0
- package/dist/src/patterns/definitions/composition/icicle.js.map +1 -0
- package/dist/src/patterns/definitions/composition/index.d.ts +9 -0
- package/dist/src/patterns/definitions/composition/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/index.js +9 -0
- package/dist/src/patterns/definitions/composition/index.js.map +1 -0
- package/dist/src/patterns/definitions/composition/marimekko.d.ts +9 -0
- package/dist/src/patterns/definitions/composition/marimekko.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/marimekko.js +124 -0
- package/dist/src/patterns/definitions/composition/marimekko.js.map +1 -0
- package/dist/src/patterns/definitions/composition/metric.d.ts +9 -0
- package/dist/src/patterns/definitions/composition/metric.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/metric.js +112 -0
- package/dist/src/patterns/definitions/composition/metric.js.map +1 -0
- package/dist/src/patterns/definitions/composition/stacked-bar.d.ts +10 -0
- package/dist/src/patterns/definitions/composition/stacked-bar.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/stacked-bar.js +104 -0
- package/dist/src/patterns/definitions/composition/stacked-bar.js.map +1 -0
- package/dist/src/patterns/definitions/composition/sunburst.d.ts +10 -0
- package/dist/src/patterns/definitions/composition/sunburst.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/sunburst.js +100 -0
- package/dist/src/patterns/definitions/composition/sunburst.js.map +1 -0
- package/dist/src/patterns/definitions/composition/treemap.d.ts +10 -0
- package/dist/src/patterns/definitions/composition/treemap.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/treemap.js +104 -0
- package/dist/src/patterns/definitions/composition/treemap.js.map +1 -0
- package/dist/src/patterns/definitions/composition/waffle.d.ts +11 -0
- package/dist/src/patterns/definitions/composition/waffle.d.ts.map +1 -0
- package/dist/src/patterns/definitions/composition/waffle.js +111 -0
- package/dist/src/patterns/definitions/composition/waffle.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/beeswarm.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/beeswarm.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/beeswarm.js +103 -0
- package/dist/src/patterns/definitions/distribution/beeswarm.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/box-plot.d.ts +9 -0
- package/dist/src/patterns/definitions/distribution/box-plot.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/box-plot.js +104 -0
- package/dist/src/patterns/definitions/distribution/box-plot.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/density-plot.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/density-plot.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/density-plot.js +112 -0
- package/dist/src/patterns/definitions/distribution/density-plot.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/histogram.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/histogram.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/histogram.js +109 -0
- package/dist/src/patterns/definitions/distribution/histogram.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/index.d.ts +9 -0
- package/dist/src/patterns/definitions/distribution/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/index.js +9 -0
- package/dist/src/patterns/definitions/distribution/index.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/ridgeline.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/ridgeline.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/ridgeline.js +105 -0
- package/dist/src/patterns/definitions/distribution/ridgeline.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/strip-plot.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/strip-plot.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/strip-plot.js +93 -0
- package/dist/src/patterns/definitions/distribution/strip-plot.js.map +1 -0
- package/dist/src/patterns/definitions/distribution/violin.d.ts +10 -0
- package/dist/src/patterns/definitions/distribution/violin.d.ts.map +1 -0
- package/dist/src/patterns/definitions/distribution/violin.js +105 -0
- package/dist/src/patterns/definitions/distribution/violin.js.map +1 -0
- package/dist/src/patterns/definitions/flow/alluvial.d.ts +11 -0
- package/dist/src/patterns/definitions/flow/alluvial.d.ts.map +1 -0
- package/dist/src/patterns/definitions/flow/alluvial.js +107 -0
- package/dist/src/patterns/definitions/flow/alluvial.js.map +1 -0
- package/dist/src/patterns/definitions/flow/chord.d.ts +11 -0
- package/dist/src/patterns/definitions/flow/chord.d.ts.map +1 -0
- package/dist/src/patterns/definitions/flow/chord.js +123 -0
- package/dist/src/patterns/definitions/flow/chord.js.map +1 -0
- package/dist/src/patterns/definitions/flow/funnel.d.ts +6 -0
- package/dist/src/patterns/definitions/flow/funnel.d.ts.map +1 -0
- package/dist/src/patterns/definitions/flow/funnel.js +69 -0
- package/dist/src/patterns/definitions/flow/funnel.js.map +1 -0
- package/dist/src/patterns/definitions/flow/index.d.ts +7 -0
- package/dist/src/patterns/definitions/flow/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/flow/index.js +7 -0
- package/dist/src/patterns/definitions/flow/index.js.map +1 -0
- package/dist/src/patterns/definitions/flow/sankey.d.ts +10 -0
- package/dist/src/patterns/definitions/flow/sankey.d.ts.map +1 -0
- package/dist/src/patterns/definitions/flow/sankey.js +120 -0
- package/dist/src/patterns/definitions/flow/sankey.js.map +1 -0
- package/dist/src/patterns/definitions/geo/choropleth.d.ts +3 -0
- package/dist/src/patterns/definitions/geo/choropleth.d.ts.map +1 -0
- package/dist/src/patterns/definitions/geo/choropleth.js +72 -0
- package/dist/src/patterns/definitions/geo/choropleth.js.map +1 -0
- package/dist/src/patterns/definitions/geo/index.d.ts +6 -0
- package/dist/src/patterns/definitions/geo/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/geo/index.js +6 -0
- package/dist/src/patterns/definitions/geo/index.js.map +1 -0
- package/dist/src/patterns/definitions/geo/proportional-symbol.d.ts +10 -0
- package/dist/src/patterns/definitions/geo/proportional-symbol.d.ts.map +1 -0
- package/dist/src/patterns/definitions/geo/proportional-symbol.js +81 -0
- package/dist/src/patterns/definitions/geo/proportional-symbol.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/connected-scatter.d.ts +11 -0
- package/dist/src/patterns/definitions/relationship/connected-scatter.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/connected-scatter.js +108 -0
- package/dist/src/patterns/definitions/relationship/connected-scatter.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/heatmap.d.ts +10 -0
- package/dist/src/patterns/definitions/relationship/heatmap.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/heatmap.js +152 -0
- package/dist/src/patterns/definitions/relationship/heatmap.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/index.d.ts +8 -0
- package/dist/src/patterns/definitions/relationship/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/index.js +8 -0
- package/dist/src/patterns/definitions/relationship/index.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/parallel-coordinates.d.ts +10 -0
- package/dist/src/patterns/definitions/relationship/parallel-coordinates.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/parallel-coordinates.js +104 -0
- package/dist/src/patterns/definitions/relationship/parallel-coordinates.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/radar.d.ts +11 -0
- package/dist/src/patterns/definitions/relationship/radar.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/radar.js +125 -0
- package/dist/src/patterns/definitions/relationship/radar.js.map +1 -0
- package/dist/src/patterns/definitions/relationship/scatter.d.ts +10 -0
- package/dist/src/patterns/definitions/relationship/scatter.d.ts.map +1 -0
- package/dist/src/patterns/definitions/relationship/scatter.js +122 -0
- package/dist/src/patterns/definitions/relationship/scatter.js.map +1 -0
- package/dist/src/patterns/definitions/time/area.d.ts +9 -0
- package/dist/src/patterns/definitions/time/area.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/area.js +97 -0
- package/dist/src/patterns/definitions/time/area.js.map +1 -0
- package/dist/src/patterns/definitions/time/calendar-heatmap.d.ts +10 -0
- package/dist/src/patterns/definitions/time/calendar-heatmap.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/calendar-heatmap.js +109 -0
- package/dist/src/patterns/definitions/time/calendar-heatmap.js.map +1 -0
- package/dist/src/patterns/definitions/time/horizon-chart.d.ts +3 -0
- package/dist/src/patterns/definitions/time/horizon-chart.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/horizon-chart.js +92 -0
- package/dist/src/patterns/definitions/time/horizon-chart.js.map +1 -0
- package/dist/src/patterns/definitions/time/index.d.ts +8 -0
- package/dist/src/patterns/definitions/time/index.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/index.js +8 -0
- package/dist/src/patterns/definitions/time/index.js.map +1 -0
- package/dist/src/patterns/definitions/time/line.d.ts +10 -0
- package/dist/src/patterns/definitions/time/line.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/line.js +104 -0
- package/dist/src/patterns/definitions/time/line.js.map +1 -0
- package/dist/src/patterns/definitions/time/small-multiples.d.ts +11 -0
- package/dist/src/patterns/definitions/time/small-multiples.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/small-multiples.js +99 -0
- package/dist/src/patterns/definitions/time/small-multiples.js.map +1 -0
- package/dist/src/patterns/definitions/time/sparkline-grid.d.ts +10 -0
- package/dist/src/patterns/definitions/time/sparkline-grid.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/sparkline-grid.js +123 -0
- package/dist/src/patterns/definitions/time/sparkline-grid.js.map +1 -0
- package/dist/src/patterns/definitions/time/stream-graph.d.ts +10 -0
- package/dist/src/patterns/definitions/time/stream-graph.d.ts.map +1 -0
- package/dist/src/patterns/definitions/time/stream-graph.js +122 -0
- package/dist/src/patterns/definitions/time/stream-graph.js.map +1 -0
- package/dist/src/patterns/index.d.ts +23 -0
- package/dist/src/patterns/index.d.ts.map +1 -0
- package/dist/src/patterns/index.js +32 -0
- package/dist/src/patterns/index.js.map +1 -0
- package/dist/src/patterns/registry.d.ts +69 -0
- package/dist/src/patterns/registry.d.ts.map +1 -0
- package/dist/src/patterns/registry.js +230 -0
- package/dist/src/patterns/registry.js.map +1 -0
- package/dist/src/patterns/selector.d.ts +68 -0
- package/dist/src/patterns/selector.d.ts.map +1 -0
- package/dist/src/patterns/selector.js +441 -0
- package/dist/src/patterns/selector.js.map +1 -0
- package/dist/src/patterns/utils.d.ts +77 -0
- package/dist/src/patterns/utils.d.ts.map +1 -0
- package/dist/src/patterns/utils.js +353 -0
- package/dist/src/patterns/utils.js.map +1 -0
- package/dist/src/query-engine/candidate-matcher.d.ts +31 -0
- package/dist/src/query-engine/candidate-matcher.d.ts.map +1 -0
- package/dist/src/query-engine/candidate-matcher.js +157 -0
- package/dist/src/query-engine/candidate-matcher.js.map +1 -0
- package/dist/src/query-engine/chart-detector.d.ts +26 -0
- package/dist/src/query-engine/chart-detector.d.ts.map +1 -0
- package/dist/src/query-engine/chart-detector.js +61 -0
- package/dist/src/query-engine/chart-detector.js.map +1 -0
- package/dist/src/query-engine/index.d.ts +56 -0
- package/dist/src/query-engine/index.d.ts.map +1 -0
- package/dist/src/query-engine/index.js +185 -0
- package/dist/src/query-engine/index.js.map +1 -0
- package/dist/src/query-engine/llm-selector.d.ts +47 -0
- package/dist/src/query-engine/llm-selector.d.ts.map +1 -0
- package/dist/src/query-engine/llm-selector.js +223 -0
- package/dist/src/query-engine/llm-selector.js.map +1 -0
- package/dist/src/query-engine/schema-loader.d.ts +33 -0
- package/dist/src/query-engine/schema-loader.d.ts.map +1 -0
- package/dist/src/query-engine/schema-loader.js +144 -0
- package/dist/src/query-engine/schema-loader.js.map +1 -0
- package/dist/src/query-engine/session.d.ts +71 -0
- package/dist/src/query-engine/session.d.ts.map +1 -0
- package/dist/src/query-engine/session.js +117 -0
- package/dist/src/query-engine/session.js.map +1 -0
- package/dist/src/query-engine/sql-builder.d.ts +33 -0
- package/dist/src/query-engine/sql-builder.d.ts.map +1 -0
- package/dist/src/query-engine/sql-builder.js +146 -0
- package/dist/src/query-engine/sql-builder.js.map +1 -0
- package/dist/src/query-engine/validator.d.ts +29 -0
- package/dist/src/query-engine/validator.d.ts.map +1 -0
- package/dist/src/query-engine/validator.js +93 -0
- package/dist/src/query-engine/validator.js.map +1 -0
- package/dist/src/renderers/d3/comparison/bar.d.ts +6 -0
- package/dist/src/renderers/d3/comparison/bar.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/bar.js +306 -0
- package/dist/src/renderers/d3/comparison/bar.js.map +1 -0
- package/dist/src/renderers/d3/comparison/bullet.d.ts +3 -0
- package/dist/src/renderers/d3/comparison/bullet.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/bullet.js +209 -0
- package/dist/src/renderers/d3/comparison/bullet.js.map +1 -0
- package/dist/src/renderers/d3/comparison/bump-chart.d.ts +10 -0
- package/dist/src/renderers/d3/comparison/bump-chart.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/bump-chart.js +210 -0
- package/dist/src/renderers/d3/comparison/bump-chart.js.map +1 -0
- package/dist/src/renderers/d3/comparison/connected-dot-plot.d.ts +10 -0
- package/dist/src/renderers/d3/comparison/connected-dot-plot.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/connected-dot-plot.js +235 -0
- package/dist/src/renderers/d3/comparison/connected-dot-plot.js.map +1 -0
- package/dist/src/renderers/d3/comparison/diverging-bar.d.ts +7 -0
- package/dist/src/renderers/d3/comparison/diverging-bar.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/diverging-bar.js +295 -0
- package/dist/src/renderers/d3/comparison/diverging-bar.js.map +1 -0
- package/dist/src/renderers/d3/comparison/grouped-bar.d.ts +7 -0
- package/dist/src/renderers/d3/comparison/grouped-bar.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/grouped-bar.js +267 -0
- package/dist/src/renderers/d3/comparison/grouped-bar.js.map +1 -0
- package/dist/src/renderers/d3/comparison/index.d.ts +13 -0
- package/dist/src/renderers/d3/comparison/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/index.js +13 -0
- package/dist/src/renderers/d3/comparison/index.js.map +1 -0
- package/dist/src/renderers/d3/comparison/lollipop.d.ts +6 -0
- package/dist/src/renderers/d3/comparison/lollipop.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/lollipop.js +318 -0
- package/dist/src/renderers/d3/comparison/lollipop.js.map +1 -0
- package/dist/src/renderers/d3/comparison/slope-chart.d.ts +6 -0
- package/dist/src/renderers/d3/comparison/slope-chart.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/slope-chart.js +272 -0
- package/dist/src/renderers/d3/comparison/slope-chart.js.map +1 -0
- package/dist/src/renderers/d3/comparison/waterfall.d.ts +6 -0
- package/dist/src/renderers/d3/comparison/waterfall.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison/waterfall.js +208 -0
- package/dist/src/renderers/d3/comparison/waterfall.js.map +1 -0
- package/dist/src/renderers/d3/comparison.d.ts +8 -0
- package/dist/src/renderers/d3/comparison.d.ts.map +1 -0
- package/dist/src/renderers/d3/comparison.js +284 -0
- package/dist/src/renderers/d3/comparison.js.map +1 -0
- package/dist/src/renderers/d3/composition/circle-pack.d.ts +9 -0
- package/dist/src/renderers/d3/composition/circle-pack.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/circle-pack.js +196 -0
- package/dist/src/renderers/d3/composition/circle-pack.js.map +1 -0
- package/dist/src/renderers/d3/composition/donut.d.ts +7 -0
- package/dist/src/renderers/d3/composition/donut.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/donut.js +178 -0
- package/dist/src/renderers/d3/composition/donut.js.map +1 -0
- package/dist/src/renderers/d3/composition/icicle.d.ts +10 -0
- package/dist/src/renderers/d3/composition/icicle.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/icicle.js +380 -0
- package/dist/src/renderers/d3/composition/icicle.js.map +1 -0
- package/dist/src/renderers/d3/composition/index.d.ts +13 -0
- package/dist/src/renderers/d3/composition/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/index.js +13 -0
- package/dist/src/renderers/d3/composition/index.js.map +1 -0
- package/dist/src/renderers/d3/composition/marimekko.d.ts +3 -0
- package/dist/src/renderers/d3/composition/marimekko.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/marimekko.js +229 -0
- package/dist/src/renderers/d3/composition/marimekko.js.map +1 -0
- package/dist/src/renderers/d3/composition/metric.d.ts +9 -0
- package/dist/src/renderers/d3/composition/metric.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/metric.js +224 -0
- package/dist/src/renderers/d3/composition/metric.js.map +1 -0
- package/dist/src/renderers/d3/composition/stacked-bar.d.ts +7 -0
- package/dist/src/renderers/d3/composition/stacked-bar.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/stacked-bar.js +251 -0
- package/dist/src/renderers/d3/composition/stacked-bar.js.map +1 -0
- package/dist/src/renderers/d3/composition/sunburst.d.ts +11 -0
- package/dist/src/renderers/d3/composition/sunburst.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/sunburst.js +315 -0
- package/dist/src/renderers/d3/composition/sunburst.js.map +1 -0
- package/dist/src/renderers/d3/composition/treemap.d.ts +9 -0
- package/dist/src/renderers/d3/composition/treemap.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/treemap.js +224 -0
- package/dist/src/renderers/d3/composition/treemap.js.map +1 -0
- package/dist/src/renderers/d3/composition/waffle.d.ts +8 -0
- package/dist/src/renderers/d3/composition/waffle.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition/waffle.js +130 -0
- package/dist/src/renderers/d3/composition/waffle.js.map +1 -0
- package/dist/src/renderers/d3/composition.d.ts +8 -0
- package/dist/src/renderers/d3/composition.d.ts.map +1 -0
- package/dist/src/renderers/d3/composition.js +325 -0
- package/dist/src/renderers/d3/composition.js.map +1 -0
- package/dist/src/renderers/d3/connected-scatter.d.ts +10 -0
- package/dist/src/renderers/d3/connected-scatter.d.ts.map +1 -0
- package/dist/src/renderers/d3/connected-scatter.js +358 -0
- package/dist/src/renderers/d3/connected-scatter.js.map +1 -0
- package/dist/src/renderers/d3/distribution/beeswarm.d.ts +13 -0
- package/dist/src/renderers/d3/distribution/beeswarm.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/beeswarm.js +346 -0
- package/dist/src/renderers/d3/distribution/beeswarm.js.map +1 -0
- package/dist/src/renderers/d3/distribution/box-plot.d.ts +9 -0
- package/dist/src/renderers/d3/distribution/box-plot.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/box-plot.js +369 -0
- package/dist/src/renderers/d3/distribution/box-plot.js.map +1 -0
- package/dist/src/renderers/d3/distribution/density-plot.d.ts +10 -0
- package/dist/src/renderers/d3/distribution/density-plot.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/density-plot.js +325 -0
- package/dist/src/renderers/d3/distribution/density-plot.js.map +1 -0
- package/dist/src/renderers/d3/distribution/histogram.d.ts +12 -0
- package/dist/src/renderers/d3/distribution/histogram.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/histogram.js +359 -0
- package/dist/src/renderers/d3/distribution/histogram.js.map +1 -0
- package/dist/src/renderers/d3/distribution/index.d.ts +11 -0
- package/dist/src/renderers/d3/distribution/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/index.js +11 -0
- package/dist/src/renderers/d3/distribution/index.js.map +1 -0
- package/dist/src/renderers/d3/distribution/ridgeline.d.ts +9 -0
- package/dist/src/renderers/d3/distribution/ridgeline.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/ridgeline.js +230 -0
- package/dist/src/renderers/d3/distribution/ridgeline.js.map +1 -0
- package/dist/src/renderers/d3/distribution/strip-plot.d.ts +12 -0
- package/dist/src/renderers/d3/distribution/strip-plot.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/strip-plot.js +284 -0
- package/dist/src/renderers/d3/distribution/strip-plot.js.map +1 -0
- package/dist/src/renderers/d3/distribution/violin.d.ts +10 -0
- package/dist/src/renderers/d3/distribution/violin.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution/violin.js +298 -0
- package/dist/src/renderers/d3/distribution/violin.js.map +1 -0
- package/dist/src/renderers/d3/distribution.d.ts +8 -0
- package/dist/src/renderers/d3/distribution.d.ts.map +1 -0
- package/dist/src/renderers/d3/distribution.js +364 -0
- package/dist/src/renderers/d3/distribution.js.map +1 -0
- package/dist/src/renderers/d3/flow/alluvial.d.ts +10 -0
- package/dist/src/renderers/d3/flow/alluvial.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/alluvial.js +352 -0
- package/dist/src/renderers/d3/flow/alluvial.js.map +1 -0
- package/dist/src/renderers/d3/flow/chord.d.ts +9 -0
- package/dist/src/renderers/d3/flow/chord.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/chord.js +235 -0
- package/dist/src/renderers/d3/flow/chord.js.map +1 -0
- package/dist/src/renderers/d3/flow/funnel.d.ts +10 -0
- package/dist/src/renderers/d3/flow/funnel.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/funnel.js +284 -0
- package/dist/src/renderers/d3/flow/funnel.js.map +1 -0
- package/dist/src/renderers/d3/flow/index.d.ts +9 -0
- package/dist/src/renderers/d3/flow/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/index.js +8 -0
- package/dist/src/renderers/d3/flow/index.js.map +1 -0
- package/dist/src/renderers/d3/flow/sankey-layout.d.ts +35 -0
- package/dist/src/renderers/d3/flow/sankey-layout.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/sankey-layout.js +148 -0
- package/dist/src/renderers/d3/flow/sankey-layout.js.map +1 -0
- package/dist/src/renderers/d3/flow/sankey.d.ts +6 -0
- package/dist/src/renderers/d3/flow/sankey.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow/sankey.js +141 -0
- package/dist/src/renderers/d3/flow/sankey.js.map +1 -0
- package/dist/src/renderers/d3/flow.d.ts +10 -0
- package/dist/src/renderers/d3/flow.d.ts.map +1 -0
- package/dist/src/renderers/d3/flow.js +274 -0
- package/dist/src/renderers/d3/flow.js.map +1 -0
- package/dist/src/renderers/d3/geo/choropleth.d.ts +3 -0
- package/dist/src/renderers/d3/geo/choropleth.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/choropleth.js +176 -0
- package/dist/src/renderers/d3/geo/choropleth.js.map +1 -0
- package/dist/src/renderers/d3/geo/geo-registry.d.ts +18 -0
- package/dist/src/renderers/d3/geo/geo-registry.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/geo-registry.js +269 -0
- package/dist/src/renderers/d3/geo/geo-registry.js.map +1 -0
- package/dist/src/renderers/d3/geo/geo-scope.d.ts +31 -0
- package/dist/src/renderers/d3/geo/geo-scope.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/geo-scope.js +257 -0
- package/dist/src/renderers/d3/geo/geo-scope.js.map +1 -0
- package/dist/src/renderers/d3/geo/index.d.ts +7 -0
- package/dist/src/renderers/d3/geo/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/index.js +5 -0
- package/dist/src/renderers/d3/geo/index.js.map +1 -0
- package/dist/src/renderers/d3/geo/names/countries.d.ts +4 -0
- package/dist/src/renderers/d3/geo/names/countries.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/names/countries.js +225 -0
- package/dist/src/renderers/d3/geo/names/countries.js.map +1 -0
- package/dist/src/renderers/d3/geo/names/fuzzy.d.ts +8 -0
- package/dist/src/renderers/d3/geo/names/fuzzy.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/names/fuzzy.js +41 -0
- package/dist/src/renderers/d3/geo/names/fuzzy.js.map +1 -0
- package/dist/src/renderers/d3/geo/names/index.d.ts +6 -0
- package/dist/src/renderers/d3/geo/names/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/names/index.js +5 -0
- package/dist/src/renderers/d3/geo/names/index.js.map +1 -0
- package/dist/src/renderers/d3/geo/names/normalize.d.ts +2 -0
- package/dist/src/renderers/d3/geo/names/normalize.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/names/normalize.js +10 -0
- package/dist/src/renderers/d3/geo/names/normalize.js.map +1 -0
- package/dist/src/renderers/d3/geo/names/subdivisions.d.ts +3 -0
- package/dist/src/renderers/d3/geo/names/subdivisions.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/names/subdivisions.js +622 -0
- package/dist/src/renderers/d3/geo/names/subdivisions.js.map +1 -0
- package/dist/src/renderers/d3/geo/proportional-symbol.d.ts +13 -0
- package/dist/src/renderers/d3/geo/proportional-symbol.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/proportional-symbol.js +466 -0
- package/dist/src/renderers/d3/geo/proportional-symbol.js.map +1 -0
- package/dist/src/renderers/d3/geo/topojson-loader.d.ts +3 -0
- package/dist/src/renderers/d3/geo/topojson-loader.d.ts.map +1 -0
- package/dist/src/renderers/d3/geo/topojson-loader.js +13 -0
- package/dist/src/renderers/d3/geo/topojson-loader.js.map +1 -0
- package/dist/src/renderers/d3/heatmap.d.ts +9 -0
- package/dist/src/renderers/d3/heatmap.d.ts.map +1 -0
- package/dist/src/renderers/d3/heatmap.js +228 -0
- package/dist/src/renderers/d3/heatmap.js.map +1 -0
- package/dist/src/renderers/d3/index.d.ts +70 -0
- package/dist/src/renderers/d3/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/index.js +163 -0
- package/dist/src/renderers/d3/index.js.map +1 -0
- package/dist/src/renderers/d3/parallel-coordinates.d.ts +12 -0
- package/dist/src/renderers/d3/parallel-coordinates.d.ts.map +1 -0
- package/dist/src/renderers/d3/parallel-coordinates.js +181 -0
- package/dist/src/renderers/d3/parallel-coordinates.js.map +1 -0
- package/dist/src/renderers/d3/radar.d.ts +11 -0
- package/dist/src/renderers/d3/radar.d.ts.map +1 -0
- package/dist/src/renderers/d3/radar.js +258 -0
- package/dist/src/renderers/d3/radar.js.map +1 -0
- package/dist/src/renderers/d3/relationship.d.ts +6 -0
- package/dist/src/renderers/d3/relationship.d.ts.map +1 -0
- package/dist/src/renderers/d3/relationship.js +232 -0
- package/dist/src/renderers/d3/relationship.js.map +1 -0
- package/dist/src/renderers/d3/shared.d.ts +152 -0
- package/dist/src/renderers/d3/shared.d.ts.map +1 -0
- package/dist/src/renderers/d3/shared.js +869 -0
- package/dist/src/renderers/d3/shared.js.map +1 -0
- package/dist/src/renderers/d3/time/area.d.ts +8 -0
- package/dist/src/renderers/d3/time/area.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/area.js +415 -0
- package/dist/src/renderers/d3/time/area.js.map +1 -0
- package/dist/src/renderers/d3/time/calendar-heatmap.d.ts +11 -0
- package/dist/src/renderers/d3/time/calendar-heatmap.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/calendar-heatmap.js +471 -0
- package/dist/src/renderers/d3/time/calendar-heatmap.js.map +1 -0
- package/dist/src/renderers/d3/time/horizon-chart.d.ts +3 -0
- package/dist/src/renderers/d3/time/horizon-chart.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/horizon-chart.js +314 -0
- package/dist/src/renderers/d3/time/horizon-chart.js.map +1 -0
- package/dist/src/renderers/d3/time/index.d.ts +11 -0
- package/dist/src/renderers/d3/time/index.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/index.js +11 -0
- package/dist/src/renderers/d3/time/index.js.map +1 -0
- package/dist/src/renderers/d3/time/line.d.ts +8 -0
- package/dist/src/renderers/d3/time/line.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/line.js +313 -0
- package/dist/src/renderers/d3/time/line.js.map +1 -0
- package/dist/src/renderers/d3/time/small-multiples.d.ts +6 -0
- package/dist/src/renderers/d3/time/small-multiples.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/small-multiples.js +159 -0
- package/dist/src/renderers/d3/time/small-multiples.js.map +1 -0
- package/dist/src/renderers/d3/time/sparkline-grid.d.ts +9 -0
- package/dist/src/renderers/d3/time/sparkline-grid.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/sparkline-grid.js +190 -0
- package/dist/src/renderers/d3/time/sparkline-grid.js.map +1 -0
- package/dist/src/renderers/d3/time/stream-graph.d.ts +9 -0
- package/dist/src/renderers/d3/time/stream-graph.d.ts.map +1 -0
- package/dist/src/renderers/d3/time/stream-graph.js +301 -0
- package/dist/src/renderers/d3/time/stream-graph.js.map +1 -0
- package/dist/src/renderers/d3/time.d.ts +7 -0
- package/dist/src/renderers/d3/time.d.ts.map +1 -0
- package/dist/src/renderers/d3/time.js +298 -0
- package/dist/src/renderers/d3/time.js.map +1 -0
- package/dist/src/renderers/html/_generated/bundles.d.ts +44 -0
- package/dist/src/renderers/html/_generated/bundles.d.ts.map +1 -0
- package/dist/src/renderers/html/_generated/bundles.js +45 -0
- package/dist/src/renderers/html/_generated/bundles.js.map +1 -0
- package/dist/src/renderers/html/builders/alluvial.d.ts +3 -0
- package/dist/src/renderers/html/builders/alluvial.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/alluvial.js +6 -0
- package/dist/src/renderers/html/builders/alluvial.js.map +1 -0
- package/dist/src/renderers/html/builders/area.d.ts +3 -0
- package/dist/src/renderers/html/builders/area.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/area.js +6 -0
- package/dist/src/renderers/html/builders/area.js.map +1 -0
- package/dist/src/renderers/html/builders/bar.d.ts +3 -0
- package/dist/src/renderers/html/builders/bar.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/bar.js +6 -0
- package/dist/src/renderers/html/builders/bar.js.map +1 -0
- package/dist/src/renderers/html/builders/beeswarm.d.ts +3 -0
- package/dist/src/renderers/html/builders/beeswarm.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/beeswarm.js +6 -0
- package/dist/src/renderers/html/builders/beeswarm.js.map +1 -0
- package/dist/src/renderers/html/builders/box-plot.d.ts +3 -0
- package/dist/src/renderers/html/builders/box-plot.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/box-plot.js +6 -0
- package/dist/src/renderers/html/builders/box-plot.js.map +1 -0
- package/dist/src/renderers/html/builders/bullet.d.ts +3 -0
- package/dist/src/renderers/html/builders/bullet.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/bullet.js +6 -0
- package/dist/src/renderers/html/builders/bullet.js.map +1 -0
- package/dist/src/renderers/html/builders/bump-chart.d.ts +3 -0
- package/dist/src/renderers/html/builders/bump-chart.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/bump-chart.js +6 -0
- package/dist/src/renderers/html/builders/bump-chart.js.map +1 -0
- package/dist/src/renderers/html/builders/calendar-heatmap.d.ts +3 -0
- package/dist/src/renderers/html/builders/calendar-heatmap.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/calendar-heatmap.js +6 -0
- package/dist/src/renderers/html/builders/calendar-heatmap.js.map +1 -0
- package/dist/src/renderers/html/builders/chord.d.ts +3 -0
- package/dist/src/renderers/html/builders/chord.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/chord.js +6 -0
- package/dist/src/renderers/html/builders/chord.js.map +1 -0
- package/dist/src/renderers/html/builders/choropleth.d.ts +3 -0
- package/dist/src/renderers/html/builders/choropleth.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/choropleth.js +6 -0
- package/dist/src/renderers/html/builders/choropleth.js.map +1 -0
- package/dist/src/renderers/html/builders/circle-pack.d.ts +3 -0
- package/dist/src/renderers/html/builders/circle-pack.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/circle-pack.js +6 -0
- package/dist/src/renderers/html/builders/circle-pack.js.map +1 -0
- package/dist/src/renderers/html/builders/compound.d.ts +18 -0
- package/dist/src/renderers/html/builders/compound.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/compound.js +468 -0
- package/dist/src/renderers/html/builders/compound.js.map +1 -0
- package/dist/src/renderers/html/builders/connected-dot-plot.d.ts +3 -0
- package/dist/src/renderers/html/builders/connected-dot-plot.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/connected-dot-plot.js +6 -0
- package/dist/src/renderers/html/builders/connected-dot-plot.js.map +1 -0
- package/dist/src/renderers/html/builders/connected-scatter.d.ts +3 -0
- package/dist/src/renderers/html/builders/connected-scatter.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/connected-scatter.js +6 -0
- package/dist/src/renderers/html/builders/connected-scatter.js.map +1 -0
- package/dist/src/renderers/html/builders/dashboard.d.ts +26 -0
- package/dist/src/renderers/html/builders/dashboard.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/dashboard.js +420 -0
- package/dist/src/renderers/html/builders/dashboard.js.map +1 -0
- package/dist/src/renderers/html/builders/density-plot.d.ts +3 -0
- package/dist/src/renderers/html/builders/density-plot.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/density-plot.js +6 -0
- package/dist/src/renderers/html/builders/density-plot.js.map +1 -0
- package/dist/src/renderers/html/builders/diverging-bar.d.ts +3 -0
- package/dist/src/renderers/html/builders/diverging-bar.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/diverging-bar.js +6 -0
- package/dist/src/renderers/html/builders/diverging-bar.js.map +1 -0
- package/dist/src/renderers/html/builders/donut.d.ts +3 -0
- package/dist/src/renderers/html/builders/donut.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/donut.js +6 -0
- package/dist/src/renderers/html/builders/donut.js.map +1 -0
- package/dist/src/renderers/html/builders/funnel.d.ts +3 -0
- package/dist/src/renderers/html/builders/funnel.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/funnel.js +6 -0
- package/dist/src/renderers/html/builders/funnel.js.map +1 -0
- package/dist/src/renderers/html/builders/grouped-bar.d.ts +3 -0
- package/dist/src/renderers/html/builders/grouped-bar.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/grouped-bar.js +6 -0
- package/dist/src/renderers/html/builders/grouped-bar.js.map +1 -0
- package/dist/src/renderers/html/builders/heatmap.d.ts +3 -0
- package/dist/src/renderers/html/builders/heatmap.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/heatmap.js +6 -0
- package/dist/src/renderers/html/builders/heatmap.js.map +1 -0
- package/dist/src/renderers/html/builders/histogram.d.ts +3 -0
- package/dist/src/renderers/html/builders/histogram.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/histogram.js +6 -0
- package/dist/src/renderers/html/builders/histogram.js.map +1 -0
- package/dist/src/renderers/html/builders/horizon-chart.d.ts +3 -0
- package/dist/src/renderers/html/builders/horizon-chart.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/horizon-chart.js +6 -0
- package/dist/src/renderers/html/builders/horizon-chart.js.map +1 -0
- package/dist/src/renderers/html/builders/icicle.d.ts +3 -0
- package/dist/src/renderers/html/builders/icicle.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/icicle.js +6 -0
- package/dist/src/renderers/html/builders/icicle.js.map +1 -0
- package/dist/src/renderers/html/builders/line.d.ts +3 -0
- package/dist/src/renderers/html/builders/line.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/line.js +6 -0
- package/dist/src/renderers/html/builders/line.js.map +1 -0
- package/dist/src/renderers/html/builders/lollipop.d.ts +3 -0
- package/dist/src/renderers/html/builders/lollipop.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/lollipop.js +6 -0
- package/dist/src/renderers/html/builders/lollipop.js.map +1 -0
- package/dist/src/renderers/html/builders/marimekko.d.ts +3 -0
- package/dist/src/renderers/html/builders/marimekko.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/marimekko.js +6 -0
- package/dist/src/renderers/html/builders/marimekko.js.map +1 -0
- package/dist/src/renderers/html/builders/metric.d.ts +3 -0
- package/dist/src/renderers/html/builders/metric.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/metric.js +6 -0
- package/dist/src/renderers/html/builders/metric.js.map +1 -0
- package/dist/src/renderers/html/builders/parallel-coordinates.d.ts +3 -0
- package/dist/src/renderers/html/builders/parallel-coordinates.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/parallel-coordinates.js +6 -0
- package/dist/src/renderers/html/builders/parallel-coordinates.js.map +1 -0
- package/dist/src/renderers/html/builders/proportional-symbol.d.ts +3 -0
- package/dist/src/renderers/html/builders/proportional-symbol.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/proportional-symbol.js +6 -0
- package/dist/src/renderers/html/builders/proportional-symbol.js.map +1 -0
- package/dist/src/renderers/html/builders/radar.d.ts +3 -0
- package/dist/src/renderers/html/builders/radar.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/radar.js +6 -0
- package/dist/src/renderers/html/builders/radar.js.map +1 -0
- package/dist/src/renderers/html/builders/ridgeline.d.ts +3 -0
- package/dist/src/renderers/html/builders/ridgeline.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/ridgeline.js +6 -0
- package/dist/src/renderers/html/builders/ridgeline.js.map +1 -0
- package/dist/src/renderers/html/builders/sankey.d.ts +3 -0
- package/dist/src/renderers/html/builders/sankey.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/sankey.js +6 -0
- package/dist/src/renderers/html/builders/sankey.js.map +1 -0
- package/dist/src/renderers/html/builders/scatter.d.ts +3 -0
- package/dist/src/renderers/html/builders/scatter.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/scatter.js +6 -0
- package/dist/src/renderers/html/builders/scatter.js.map +1 -0
- package/dist/src/renderers/html/builders/slope-chart.d.ts +3 -0
- package/dist/src/renderers/html/builders/slope-chart.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/slope-chart.js +6 -0
- package/dist/src/renderers/html/builders/slope-chart.js.map +1 -0
- package/dist/src/renderers/html/builders/small-multiples.d.ts +3 -0
- package/dist/src/renderers/html/builders/small-multiples.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/small-multiples.js +6 -0
- package/dist/src/renderers/html/builders/small-multiples.js.map +1 -0
- package/dist/src/renderers/html/builders/sparkline-grid.d.ts +3 -0
- package/dist/src/renderers/html/builders/sparkline-grid.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/sparkline-grid.js +6 -0
- package/dist/src/renderers/html/builders/sparkline-grid.js.map +1 -0
- package/dist/src/renderers/html/builders/stacked-bar.d.ts +3 -0
- package/dist/src/renderers/html/builders/stacked-bar.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/stacked-bar.js +6 -0
- package/dist/src/renderers/html/builders/stacked-bar.js.map +1 -0
- package/dist/src/renderers/html/builders/stream-graph.d.ts +3 -0
- package/dist/src/renderers/html/builders/stream-graph.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/stream-graph.js +6 -0
- package/dist/src/renderers/html/builders/stream-graph.js.map +1 -0
- package/dist/src/renderers/html/builders/strip-plot.d.ts +3 -0
- package/dist/src/renderers/html/builders/strip-plot.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/strip-plot.js +6 -0
- package/dist/src/renderers/html/builders/strip-plot.js.map +1 -0
- package/dist/src/renderers/html/builders/sunburst.d.ts +3 -0
- package/dist/src/renderers/html/builders/sunburst.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/sunburst.js +6 -0
- package/dist/src/renderers/html/builders/sunburst.js.map +1 -0
- package/dist/src/renderers/html/builders/treemap.d.ts +3 -0
- package/dist/src/renderers/html/builders/treemap.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/treemap.js +6 -0
- package/dist/src/renderers/html/builders/treemap.js.map +1 -0
- package/dist/src/renderers/html/builders/violin.d.ts +3 -0
- package/dist/src/renderers/html/builders/violin.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/violin.js +6 -0
- package/dist/src/renderers/html/builders/violin.js.map +1 -0
- package/dist/src/renderers/html/builders/waffle.d.ts +3 -0
- package/dist/src/renderers/html/builders/waffle.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/waffle.js +6 -0
- package/dist/src/renderers/html/builders/waffle.js.map +1 -0
- package/dist/src/renderers/html/builders/waterfall.d.ts +3 -0
- package/dist/src/renderers/html/builders/waterfall.d.ts.map +1 -0
- package/dist/src/renderers/html/builders/waterfall.js +6 -0
- package/dist/src/renderers/html/builders/waterfall.js.map +1 -0
- package/dist/src/renderers/html/compound.d.ts +18 -0
- package/dist/src/renderers/html/compound.d.ts.map +1 -0
- package/dist/src/renderers/html/compound.js +150 -0
- package/dist/src/renderers/html/compound.js.map +1 -0
- package/dist/src/renderers/html/index.d.ts +82 -0
- package/dist/src/renderers/html/index.d.ts.map +1 -0
- package/dist/src/renderers/html/index.js +236 -0
- package/dist/src/renderers/html/index.js.map +1 -0
- package/dist/src/renderers/html/render/alluvial.render.d.ts +3 -0
- package/dist/src/renderers/html/render/alluvial.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/alluvial.render.js +3 -0
- package/dist/src/renderers/html/render/alluvial.render.js.map +1 -0
- package/dist/src/renderers/html/render/area.render.d.ts +3 -0
- package/dist/src/renderers/html/render/area.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/area.render.js +3 -0
- package/dist/src/renderers/html/render/area.render.js.map +1 -0
- package/dist/src/renderers/html/render/bar.render.d.ts +3 -0
- package/dist/src/renderers/html/render/bar.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/bar.render.js +3 -0
- package/dist/src/renderers/html/render/bar.render.js.map +1 -0
- package/dist/src/renderers/html/render/beeswarm.render.d.ts +3 -0
- package/dist/src/renderers/html/render/beeswarm.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/beeswarm.render.js +3 -0
- package/dist/src/renderers/html/render/beeswarm.render.js.map +1 -0
- package/dist/src/renderers/html/render/box-plot.render.d.ts +3 -0
- package/dist/src/renderers/html/render/box-plot.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/box-plot.render.js +3 -0
- package/dist/src/renderers/html/render/box-plot.render.js.map +1 -0
- package/dist/src/renderers/html/render/bullet.render.d.ts +3 -0
- package/dist/src/renderers/html/render/bullet.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/bullet.render.js +3 -0
- package/dist/src/renderers/html/render/bullet.render.js.map +1 -0
- package/dist/src/renderers/html/render/bump-chart.render.d.ts +3 -0
- package/dist/src/renderers/html/render/bump-chart.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/bump-chart.render.js +3 -0
- package/dist/src/renderers/html/render/bump-chart.render.js.map +1 -0
- package/dist/src/renderers/html/render/calendar-heatmap.render.d.ts +3 -0
- package/dist/src/renderers/html/render/calendar-heatmap.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/calendar-heatmap.render.js +3 -0
- package/dist/src/renderers/html/render/calendar-heatmap.render.js.map +1 -0
- package/dist/src/renderers/html/render/chord.render.d.ts +3 -0
- package/dist/src/renderers/html/render/chord.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/chord.render.js +3 -0
- package/dist/src/renderers/html/render/chord.render.js.map +1 -0
- package/dist/src/renderers/html/render/choropleth.render.d.ts +3 -0
- package/dist/src/renderers/html/render/choropleth.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/choropleth.render.js +5 -0
- package/dist/src/renderers/html/render/choropleth.render.js.map +1 -0
- package/dist/src/renderers/html/render/circle-pack.render.d.ts +3 -0
- package/dist/src/renderers/html/render/circle-pack.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/circle-pack.render.js +3 -0
- package/dist/src/renderers/html/render/circle-pack.render.js.map +1 -0
- package/dist/src/renderers/html/render/connected-dot-plot.render.d.ts +3 -0
- package/dist/src/renderers/html/render/connected-dot-plot.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/connected-dot-plot.render.js +3 -0
- package/dist/src/renderers/html/render/connected-dot-plot.render.js.map +1 -0
- package/dist/src/renderers/html/render/connected-scatter.render.d.ts +3 -0
- package/dist/src/renderers/html/render/connected-scatter.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/connected-scatter.render.js +3 -0
- package/dist/src/renderers/html/render/connected-scatter.render.js.map +1 -0
- package/dist/src/renderers/html/render/density-plot.render.d.ts +3 -0
- package/dist/src/renderers/html/render/density-plot.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/density-plot.render.js +3 -0
- package/dist/src/renderers/html/render/density-plot.render.js.map +1 -0
- package/dist/src/renderers/html/render/diverging-bar.render.d.ts +3 -0
- package/dist/src/renderers/html/render/diverging-bar.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/diverging-bar.render.js +3 -0
- package/dist/src/renderers/html/render/diverging-bar.render.js.map +1 -0
- package/dist/src/renderers/html/render/donut.render.d.ts +3 -0
- package/dist/src/renderers/html/render/donut.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/donut.render.js +3 -0
- package/dist/src/renderers/html/render/donut.render.js.map +1 -0
- package/dist/src/renderers/html/render/funnel.render.d.ts +3 -0
- package/dist/src/renderers/html/render/funnel.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/funnel.render.js +3 -0
- package/dist/src/renderers/html/render/funnel.render.js.map +1 -0
- package/dist/src/renderers/html/render/grouped-bar.render.d.ts +3 -0
- package/dist/src/renderers/html/render/grouped-bar.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/grouped-bar.render.js +3 -0
- package/dist/src/renderers/html/render/grouped-bar.render.js.map +1 -0
- package/dist/src/renderers/html/render/heatmap.render.d.ts +3 -0
- package/dist/src/renderers/html/render/heatmap.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/heatmap.render.js +3 -0
- package/dist/src/renderers/html/render/heatmap.render.js.map +1 -0
- package/dist/src/renderers/html/render/histogram.render.d.ts +3 -0
- package/dist/src/renderers/html/render/histogram.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/histogram.render.js +3 -0
- package/dist/src/renderers/html/render/histogram.render.js.map +1 -0
- package/dist/src/renderers/html/render/horizon-chart.render.d.ts +3 -0
- package/dist/src/renderers/html/render/horizon-chart.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/horizon-chart.render.js +3 -0
- package/dist/src/renderers/html/render/horizon-chart.render.js.map +1 -0
- package/dist/src/renderers/html/render/icicle.render.d.ts +3 -0
- package/dist/src/renderers/html/render/icicle.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/icicle.render.js +3 -0
- package/dist/src/renderers/html/render/icicle.render.js.map +1 -0
- package/dist/src/renderers/html/render/line.render.d.ts +3 -0
- package/dist/src/renderers/html/render/line.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/line.render.js +3 -0
- package/dist/src/renderers/html/render/line.render.js.map +1 -0
- package/dist/src/renderers/html/render/lollipop.render.d.ts +3 -0
- package/dist/src/renderers/html/render/lollipop.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/lollipop.render.js +3 -0
- package/dist/src/renderers/html/render/lollipop.render.js.map +1 -0
- package/dist/src/renderers/html/render/marimekko.render.d.ts +3 -0
- package/dist/src/renderers/html/render/marimekko.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/marimekko.render.js +3 -0
- package/dist/src/renderers/html/render/marimekko.render.js.map +1 -0
- package/dist/src/renderers/html/render/metric.render.d.ts +3 -0
- package/dist/src/renderers/html/render/metric.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/metric.render.js +3 -0
- package/dist/src/renderers/html/render/metric.render.js.map +1 -0
- package/dist/src/renderers/html/render/parallel-coordinates.render.d.ts +3 -0
- package/dist/src/renderers/html/render/parallel-coordinates.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/parallel-coordinates.render.js +3 -0
- package/dist/src/renderers/html/render/parallel-coordinates.render.js.map +1 -0
- package/dist/src/renderers/html/render/proportional-symbol.render.d.ts +3 -0
- package/dist/src/renderers/html/render/proportional-symbol.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/proportional-symbol.render.js +5 -0
- package/dist/src/renderers/html/render/proportional-symbol.render.js.map +1 -0
- package/dist/src/renderers/html/render/radar.render.d.ts +3 -0
- package/dist/src/renderers/html/render/radar.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/radar.render.js +3 -0
- package/dist/src/renderers/html/render/radar.render.js.map +1 -0
- package/dist/src/renderers/html/render/ridgeline.render.d.ts +3 -0
- package/dist/src/renderers/html/render/ridgeline.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/ridgeline.render.js +3 -0
- package/dist/src/renderers/html/render/ridgeline.render.js.map +1 -0
- package/dist/src/renderers/html/render/sankey.render.d.ts +3 -0
- package/dist/src/renderers/html/render/sankey.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/sankey.render.js +3 -0
- package/dist/src/renderers/html/render/sankey.render.js.map +1 -0
- package/dist/src/renderers/html/render/scatter.render.d.ts +3 -0
- package/dist/src/renderers/html/render/scatter.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/scatter.render.js +3 -0
- package/dist/src/renderers/html/render/scatter.render.js.map +1 -0
- package/dist/src/renderers/html/render/slope-chart.render.d.ts +3 -0
- package/dist/src/renderers/html/render/slope-chart.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/slope-chart.render.js +3 -0
- package/dist/src/renderers/html/render/slope-chart.render.js.map +1 -0
- package/dist/src/renderers/html/render/small-multiples.render.d.ts +3 -0
- package/dist/src/renderers/html/render/small-multiples.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/small-multiples.render.js +3 -0
- package/dist/src/renderers/html/render/small-multiples.render.js.map +1 -0
- package/dist/src/renderers/html/render/sparkline-grid.render.d.ts +3 -0
- package/dist/src/renderers/html/render/sparkline-grid.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/sparkline-grid.render.js +3 -0
- package/dist/src/renderers/html/render/sparkline-grid.render.js.map +1 -0
- package/dist/src/renderers/html/render/stacked-bar.render.d.ts +3 -0
- package/dist/src/renderers/html/render/stacked-bar.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/stacked-bar.render.js +3 -0
- package/dist/src/renderers/html/render/stacked-bar.render.js.map +1 -0
- package/dist/src/renderers/html/render/stream-graph.render.d.ts +3 -0
- package/dist/src/renderers/html/render/stream-graph.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/stream-graph.render.js +3 -0
- package/dist/src/renderers/html/render/stream-graph.render.js.map +1 -0
- package/dist/src/renderers/html/render/strip-plot.render.d.ts +3 -0
- package/dist/src/renderers/html/render/strip-plot.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/strip-plot.render.js +3 -0
- package/dist/src/renderers/html/render/strip-plot.render.js.map +1 -0
- package/dist/src/renderers/html/render/sunburst.render.d.ts +3 -0
- package/dist/src/renderers/html/render/sunburst.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/sunburst.render.js +3 -0
- package/dist/src/renderers/html/render/sunburst.render.js.map +1 -0
- package/dist/src/renderers/html/render/treemap.render.d.ts +3 -0
- package/dist/src/renderers/html/render/treemap.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/treemap.render.js +3 -0
- package/dist/src/renderers/html/render/treemap.render.js.map +1 -0
- package/dist/src/renderers/html/render/violin.render.d.ts +3 -0
- package/dist/src/renderers/html/render/violin.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/violin.render.js +3 -0
- package/dist/src/renderers/html/render/violin.render.js.map +1 -0
- package/dist/src/renderers/html/render/waffle.render.d.ts +3 -0
- package/dist/src/renderers/html/render/waffle.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/waffle.render.js +3 -0
- package/dist/src/renderers/html/render/waffle.render.js.map +1 -0
- package/dist/src/renderers/html/render/waterfall.render.d.ts +3 -0
- package/dist/src/renderers/html/render/waterfall.render.d.ts.map +1 -0
- package/dist/src/renderers/html/render/waterfall.render.js +3 -0
- package/dist/src/renderers/html/render/waterfall.render.js.map +1 -0
- package/dist/src/renderers/html/sizing.d.ts +12 -0
- package/dist/src/renderers/html/sizing.d.ts.map +1 -0
- package/dist/src/renderers/html/sizing.js +126 -0
- package/dist/src/renderers/html/sizing.js.map +1 -0
- package/dist/src/renderers/html/template.d.ts +30 -0
- package/dist/src/renderers/html/template.d.ts.map +1 -0
- package/dist/src/renderers/html/template.js +777 -0
- package/dist/src/renderers/html/template.js.map +1 -0
- package/dist/src/renderers/react/Alluvial.d.ts +7 -0
- package/dist/src/renderers/react/Alluvial.d.ts.map +1 -0
- package/dist/src/renderers/react/Alluvial.js +8 -0
- package/dist/src/renderers/react/Alluvial.js.map +1 -0
- package/dist/src/renderers/react/Area.d.ts +7 -0
- package/dist/src/renderers/react/Area.d.ts.map +1 -0
- package/dist/src/renderers/react/Area.js +8 -0
- package/dist/src/renderers/react/Area.js.map +1 -0
- package/dist/src/renderers/react/Bar.d.ts +7 -0
- package/dist/src/renderers/react/Bar.d.ts.map +1 -0
- package/dist/src/renderers/react/Bar.js +8 -0
- package/dist/src/renderers/react/Bar.js.map +1 -0
- package/dist/src/renderers/react/Beeswarm.d.ts +7 -0
- package/dist/src/renderers/react/Beeswarm.d.ts.map +1 -0
- package/dist/src/renderers/react/Beeswarm.js +8 -0
- package/dist/src/renderers/react/Beeswarm.js.map +1 -0
- package/dist/src/renderers/react/BoxPlot.d.ts +3 -0
- package/dist/src/renderers/react/BoxPlot.d.ts.map +1 -0
- package/dist/src/renderers/react/BoxPlot.js +8 -0
- package/dist/src/renderers/react/BoxPlot.js.map +1 -0
- package/dist/src/renderers/react/Bullet.d.ts +3 -0
- package/dist/src/renderers/react/Bullet.d.ts.map +1 -0
- package/dist/src/renderers/react/Bullet.js +8 -0
- package/dist/src/renderers/react/Bullet.js.map +1 -0
- package/dist/src/renderers/react/BumpChart.d.ts +9 -0
- package/dist/src/renderers/react/BumpChart.d.ts.map +1 -0
- package/dist/src/renderers/react/BumpChart.js +18 -0
- package/dist/src/renderers/react/BumpChart.js.map +1 -0
- package/dist/src/renderers/react/CalendarHeatmap.d.ts +7 -0
- package/dist/src/renderers/react/CalendarHeatmap.d.ts.map +1 -0
- package/dist/src/renderers/react/CalendarHeatmap.js +8 -0
- package/dist/src/renderers/react/CalendarHeatmap.js.map +1 -0
- package/dist/src/renderers/react/Chord.d.ts +7 -0
- package/dist/src/renderers/react/Chord.d.ts.map +1 -0
- package/dist/src/renderers/react/Chord.js +8 -0
- package/dist/src/renderers/react/Chord.js.map +1 -0
- package/dist/src/renderers/react/Choropleth.d.ts +7 -0
- package/dist/src/renderers/react/Choropleth.d.ts.map +1 -0
- package/dist/src/renderers/react/Choropleth.js +16 -0
- package/dist/src/renderers/react/Choropleth.js.map +1 -0
- package/dist/src/renderers/react/CirclePack.d.ts +7 -0
- package/dist/src/renderers/react/CirclePack.d.ts.map +1 -0
- package/dist/src/renderers/react/CirclePack.js +8 -0
- package/dist/src/renderers/react/CirclePack.js.map +1 -0
- package/dist/src/renderers/react/CompoundChart.d.ts +31 -0
- package/dist/src/renderers/react/CompoundChart.d.ts.map +1 -0
- package/dist/src/renderers/react/CompoundChart.js +80 -0
- package/dist/src/renderers/react/CompoundChart.js.map +1 -0
- package/dist/src/renderers/react/ConnectedDotPlot.d.ts +7 -0
- package/dist/src/renderers/react/ConnectedDotPlot.d.ts.map +1 -0
- package/dist/src/renderers/react/ConnectedDotPlot.js +8 -0
- package/dist/src/renderers/react/ConnectedDotPlot.js.map +1 -0
- package/dist/src/renderers/react/ConnectedScatter.d.ts +7 -0
- package/dist/src/renderers/react/ConnectedScatter.d.ts.map +1 -0
- package/dist/src/renderers/react/ConnectedScatter.js +8 -0
- package/dist/src/renderers/react/ConnectedScatter.js.map +1 -0
- package/dist/src/renderers/react/DataTable.d.ts +29 -0
- package/dist/src/renderers/react/DataTable.d.ts.map +1 -0
- package/dist/src/renderers/react/DataTable.js +128 -0
- package/dist/src/renderers/react/DataTable.js.map +1 -0
- package/dist/src/renderers/react/DensityPlot.d.ts +3 -0
- package/dist/src/renderers/react/DensityPlot.d.ts.map +1 -0
- package/dist/src/renderers/react/DensityPlot.js +8 -0
- package/dist/src/renderers/react/DensityPlot.js.map +1 -0
- package/dist/src/renderers/react/DivergingBar.d.ts +7 -0
- package/dist/src/renderers/react/DivergingBar.d.ts.map +1 -0
- package/dist/src/renderers/react/DivergingBar.js +8 -0
- package/dist/src/renderers/react/DivergingBar.js.map +1 -0
- package/dist/src/renderers/react/Donut.d.ts +7 -0
- package/dist/src/renderers/react/Donut.d.ts.map +1 -0
- package/dist/src/renderers/react/Donut.js +8 -0
- package/dist/src/renderers/react/Donut.js.map +1 -0
- package/dist/src/renderers/react/Funnel.d.ts +3 -0
- package/dist/src/renderers/react/Funnel.d.ts.map +1 -0
- package/dist/src/renderers/react/Funnel.js +8 -0
- package/dist/src/renderers/react/Funnel.js.map +1 -0
- package/dist/src/renderers/react/GroupedBar.d.ts +3 -0
- package/dist/src/renderers/react/GroupedBar.d.ts.map +1 -0
- package/dist/src/renderers/react/GroupedBar.js +8 -0
- package/dist/src/renderers/react/GroupedBar.js.map +1 -0
- package/dist/src/renderers/react/Heatmap.d.ts +3 -0
- package/dist/src/renderers/react/Heatmap.d.ts.map +1 -0
- package/dist/src/renderers/react/Heatmap.js +8 -0
- package/dist/src/renderers/react/Heatmap.js.map +1 -0
- package/dist/src/renderers/react/Histogram.d.ts +7 -0
- package/dist/src/renderers/react/Histogram.d.ts.map +1 -0
- package/dist/src/renderers/react/Histogram.js +8 -0
- package/dist/src/renderers/react/Histogram.js.map +1 -0
- package/dist/src/renderers/react/HorizonChart.d.ts +3 -0
- package/dist/src/renderers/react/HorizonChart.d.ts.map +1 -0
- package/dist/src/renderers/react/HorizonChart.js +8 -0
- package/dist/src/renderers/react/HorizonChart.js.map +1 -0
- package/dist/src/renderers/react/Icicle.d.ts +3 -0
- package/dist/src/renderers/react/Icicle.d.ts.map +1 -0
- package/dist/src/renderers/react/Icicle.js +8 -0
- package/dist/src/renderers/react/Icicle.js.map +1 -0
- package/dist/src/renderers/react/Line.d.ts +7 -0
- package/dist/src/renderers/react/Line.d.ts.map +1 -0
- package/dist/src/renderers/react/Line.js +8 -0
- package/dist/src/renderers/react/Line.js.map +1 -0
- package/dist/src/renderers/react/Lollipop.d.ts +3 -0
- package/dist/src/renderers/react/Lollipop.d.ts.map +1 -0
- package/dist/src/renderers/react/Lollipop.js +8 -0
- package/dist/src/renderers/react/Lollipop.js.map +1 -0
- package/dist/src/renderers/react/Marimekko.d.ts +7 -0
- package/dist/src/renderers/react/Marimekko.d.ts.map +1 -0
- package/dist/src/renderers/react/Marimekko.js +8 -0
- package/dist/src/renderers/react/Marimekko.js.map +1 -0
- package/dist/src/renderers/react/Metric.d.ts +7 -0
- package/dist/src/renderers/react/Metric.d.ts.map +1 -0
- package/dist/src/renderers/react/Metric.js +8 -0
- package/dist/src/renderers/react/Metric.js.map +1 -0
- package/dist/src/renderers/react/ParallelCoordinates.d.ts +7 -0
- package/dist/src/renderers/react/ParallelCoordinates.d.ts.map +1 -0
- package/dist/src/renderers/react/ParallelCoordinates.js +8 -0
- package/dist/src/renderers/react/ParallelCoordinates.js.map +1 -0
- package/dist/src/renderers/react/ProportionalSymbol.d.ts +7 -0
- package/dist/src/renderers/react/ProportionalSymbol.d.ts.map +1 -0
- package/dist/src/renderers/react/ProportionalSymbol.js +16 -0
- package/dist/src/renderers/react/ProportionalSymbol.js.map +1 -0
- package/dist/src/renderers/react/Radar.d.ts +7 -0
- package/dist/src/renderers/react/Radar.d.ts.map +1 -0
- package/dist/src/renderers/react/Radar.js +8 -0
- package/dist/src/renderers/react/Radar.js.map +1 -0
- package/dist/src/renderers/react/Ridgeline.d.ts +7 -0
- package/dist/src/renderers/react/Ridgeline.d.ts.map +1 -0
- package/dist/src/renderers/react/Ridgeline.js +8 -0
- package/dist/src/renderers/react/Ridgeline.js.map +1 -0
- package/dist/src/renderers/react/Sankey.d.ts +7 -0
- package/dist/src/renderers/react/Sankey.d.ts.map +1 -0
- package/dist/src/renderers/react/Sankey.js +8 -0
- package/dist/src/renderers/react/Sankey.js.map +1 -0
- package/dist/src/renderers/react/Scatter.d.ts +7 -0
- package/dist/src/renderers/react/Scatter.d.ts.map +1 -0
- package/dist/src/renderers/react/Scatter.js +8 -0
- package/dist/src/renderers/react/Scatter.js.map +1 -0
- package/dist/src/renderers/react/SlopeChart.d.ts +7 -0
- package/dist/src/renderers/react/SlopeChart.d.ts.map +1 -0
- package/dist/src/renderers/react/SlopeChart.js +8 -0
- package/dist/src/renderers/react/SlopeChart.js.map +1 -0
- package/dist/src/renderers/react/SmallMultiples.d.ts +7 -0
- package/dist/src/renderers/react/SmallMultiples.d.ts.map +1 -0
- package/dist/src/renderers/react/SmallMultiples.js +8 -0
- package/dist/src/renderers/react/SmallMultiples.js.map +1 -0
- package/dist/src/renderers/react/SparklineGrid.d.ts +7 -0
- package/dist/src/renderers/react/SparklineGrid.d.ts.map +1 -0
- package/dist/src/renderers/react/SparklineGrid.js +8 -0
- package/dist/src/renderers/react/SparklineGrid.js.map +1 -0
- package/dist/src/renderers/react/StackedBar.d.ts +7 -0
- package/dist/src/renderers/react/StackedBar.d.ts.map +1 -0
- package/dist/src/renderers/react/StackedBar.js +8 -0
- package/dist/src/renderers/react/StackedBar.js.map +1 -0
- package/dist/src/renderers/react/StreamGraph.d.ts +3 -0
- package/dist/src/renderers/react/StreamGraph.d.ts.map +1 -0
- package/dist/src/renderers/react/StreamGraph.js +8 -0
- package/dist/src/renderers/react/StreamGraph.js.map +1 -0
- package/dist/src/renderers/react/StripPlot.d.ts +7 -0
- package/dist/src/renderers/react/StripPlot.d.ts.map +1 -0
- package/dist/src/renderers/react/StripPlot.js +8 -0
- package/dist/src/renderers/react/StripPlot.js.map +1 -0
- package/dist/src/renderers/react/Sunburst.d.ts +7 -0
- package/dist/src/renderers/react/Sunburst.d.ts.map +1 -0
- package/dist/src/renderers/react/Sunburst.js +8 -0
- package/dist/src/renderers/react/Sunburst.js.map +1 -0
- package/dist/src/renderers/react/Treemap.d.ts +7 -0
- package/dist/src/renderers/react/Treemap.d.ts.map +1 -0
- package/dist/src/renderers/react/Treemap.js +8 -0
- package/dist/src/renderers/react/Treemap.js.map +1 -0
- package/dist/src/renderers/react/Violin.d.ts +7 -0
- package/dist/src/renderers/react/Violin.d.ts.map +1 -0
- package/dist/src/renderers/react/Violin.js +8 -0
- package/dist/src/renderers/react/Violin.js.map +1 -0
- package/dist/src/renderers/react/Waffle.d.ts +7 -0
- package/dist/src/renderers/react/Waffle.d.ts.map +1 -0
- package/dist/src/renderers/react/Waffle.js +8 -0
- package/dist/src/renderers/react/Waffle.js.map +1 -0
- package/dist/src/renderers/react/Waterfall.d.ts +3 -0
- package/dist/src/renderers/react/Waterfall.d.ts.map +1 -0
- package/dist/src/renderers/react/Waterfall.js +8 -0
- package/dist/src/renderers/react/Waterfall.js.map +1 -0
- package/dist/src/renderers/react/index.d.ts +60 -0
- package/dist/src/renderers/react/index.d.ts.map +1 -0
- package/dist/src/renderers/react/index.js +66 -0
- package/dist/src/renderers/react/index.js.map +1 -0
- package/dist/src/renderers/react/types.d.ts +17 -0
- package/dist/src/renderers/react/types.d.ts.map +1 -0
- package/dist/src/renderers/react/types.js +5 -0
- package/dist/src/renderers/react/types.js.map +1 -0
- package/dist/src/renderers/react/useChart.d.ts +21 -0
- package/dist/src/renderers/react/useChart.d.ts.map +1 -0
- package/dist/src/renderers/react/useChart.js +45 -0
- package/dist/src/renderers/react/useChart.js.map +1 -0
- package/dist/src/theme/colors.d.ts +128 -0
- package/dist/src/theme/colors.d.ts.map +1 -0
- package/dist/src/theme/colors.js +242 -0
- package/dist/src/theme/colors.js.map +1 -0
- package/dist/src/theme/index.d.ts +293 -0
- package/dist/src/theme/index.d.ts.map +1 -0
- package/dist/src/theme/index.js +83 -0
- package/dist/src/theme/index.js.map +1 -0
- package/dist/src/theme/spacing.d.ts +170 -0
- package/dist/src/theme/spacing.d.ts.map +1 -0
- package/dist/src/theme/spacing.js +143 -0
- package/dist/src/theme/spacing.js.map +1 -0
- package/dist/src/theme/typography.d.ts +137 -0
- package/dist/src/theme/typography.d.ts.map +1 -0
- package/dist/src/theme/typography.js +139 -0
- package/dist/src/theme/typography.js.map +1 -0
- package/dist/src/types.d.ts +473 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +20 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/export.d.ts +42 -0
- package/dist/src/utils/export.d.ts.map +1 -0
- package/dist/src/utils/export.js +124 -0
- package/dist/src/utils/export.js.map +1 -0
- package/dist/src/utils/index.d.ts +9 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +7 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/labels.d.ts +81 -0
- package/dist/src/utils/labels.d.ts.map +1 -0
- package/dist/src/utils/labels.js +208 -0
- package/dist/src/utils/labels.js.map +1 -0
- package/dist/src/utils/responsive.d.ts +55 -0
- package/dist/src/utils/responsive.d.ts.map +1 -0
- package/dist/src/utils/responsive.js +91 -0
- package/dist/src/utils/responsive.js.map +1 -0
- package/package.json +115 -0
- package/src/analysis/classify.ts +64 -0
- package/src/analysis/index.ts +4 -0
- package/src/analysis/planner.ts +60 -0
- package/src/analysis/rules.ts +249 -0
- package/src/analysis/types.ts +32 -0
- package/src/connectors/csv.ts +407 -0
- package/src/connectors/dsl-compiler.ts +367 -0
- package/src/connectors/dsl-validator.ts +490 -0
- package/src/connectors/index.ts +23 -0
- package/src/connectors/js-aggregation.ts +399 -0
- package/src/connectors/manager.ts +414 -0
- package/src/connectors/mysql.ts +378 -0
- package/src/connectors/postgres.ts +367 -0
- package/src/connectors/sqlite.ts +364 -0
- package/src/connectors/types.ts +59 -0
- package/src/index.ts +130 -0
- package/src/mcp/app-shell.ts +263 -0
- package/src/mcp/index.ts +394 -0
- package/src/mcp/prompts.ts +35 -0
- package/src/mcp/spec-store.ts +141 -0
- package/src/mcp/tools/analyze.ts +45 -0
- package/src/mcp/tools/bug-report.ts +183 -0
- package/src/mcp/tools/dashboard-refine.ts +456 -0
- package/src/mcp/tools/dashboard.ts +62 -0
- package/src/mcp/tools/dsl-schemas.ts +262 -0
- package/src/mcp/tools/export-html.ts +46 -0
- package/src/mcp/tools/list-patterns.ts +301 -0
- package/src/mcp/tools/operation-log.ts +110 -0
- package/src/mcp/tools/query-source.ts +69 -0
- package/src/mcp/tools/refine.ts +385 -0
- package/src/mcp/tools/result-cache.ts +61 -0
- package/src/mcp/tools/screenshot.ts +99 -0
- package/src/mcp/tools/server-privacy.ts +92 -0
- package/src/mcp/tools/shared.ts +220 -0
- package/src/mcp/tools/sources.ts +203 -0
- package/src/mcp/tools/visualize-from-source.ts +77 -0
- package/src/mcp/tools/visualize.ts +229 -0
- package/src/patterns/definitions/comparison/bar.ts +110 -0
- package/src/patterns/definitions/comparison/bullet.ts +136 -0
- package/src/patterns/definitions/comparison/bump-chart.ts +143 -0
- package/src/patterns/definitions/comparison/connected-dot-plot.ts +113 -0
- package/src/patterns/definitions/comparison/diverging-bar.ts +110 -0
- package/src/patterns/definitions/comparison/grouped-bar.ts +119 -0
- package/src/patterns/definitions/comparison/index.ts +9 -0
- package/src/patterns/definitions/comparison/lollipop.ts +138 -0
- package/src/patterns/definitions/comparison/slope-chart.ts +110 -0
- package/src/patterns/definitions/comparison/waterfall.ts +99 -0
- package/src/patterns/definitions/composition/circle-pack.ts +117 -0
- package/src/patterns/definitions/composition/donut.ts +115 -0
- package/src/patterns/definitions/composition/icicle.ts +130 -0
- package/src/patterns/definitions/composition/index.ts +9 -0
- package/src/patterns/definitions/composition/marimekko.ts +140 -0
- package/src/patterns/definitions/composition/metric.ts +126 -0
- package/src/patterns/definitions/composition/stacked-bar.ts +118 -0
- package/src/patterns/definitions/composition/sunburst.ts +114 -0
- package/src/patterns/definitions/composition/treemap.ts +118 -0
- package/src/patterns/definitions/composition/waffle.ts +127 -0
- package/src/patterns/definitions/distribution/beeswarm.ts +115 -0
- package/src/patterns/definitions/distribution/box-plot.ts +115 -0
- package/src/patterns/definitions/distribution/density-plot.ts +126 -0
- package/src/patterns/definitions/distribution/histogram.ts +125 -0
- package/src/patterns/definitions/distribution/index.ts +9 -0
- package/src/patterns/definitions/distribution/ridgeline.ts +120 -0
- package/src/patterns/definitions/distribution/strip-plot.ts +106 -0
- package/src/patterns/definitions/distribution/violin.ts +118 -0
- package/src/patterns/definitions/flow/alluvial.ts +124 -0
- package/src/patterns/definitions/flow/chord.ts +132 -0
- package/src/patterns/definitions/flow/funnel.ts +75 -0
- package/src/patterns/definitions/flow/index.ts +7 -0
- package/src/patterns/definitions/flow/sankey.ts +140 -0
- package/src/patterns/definitions/geo/choropleth.ts +82 -0
- package/src/patterns/definitions/geo/index.ts +6 -0
- package/src/patterns/definitions/geo/proportional-symbol.ts +94 -0
- package/src/patterns/definitions/relationship/connected-scatter.ts +123 -0
- package/src/patterns/definitions/relationship/heatmap.ts +168 -0
- package/src/patterns/definitions/relationship/index.ts +8 -0
- package/src/patterns/definitions/relationship/parallel-coordinates.ts +118 -0
- package/src/patterns/definitions/relationship/radar.ts +143 -0
- package/src/patterns/definitions/relationship/scatter.ts +138 -0
- package/src/patterns/definitions/time/area.ts +111 -0
- package/src/patterns/definitions/time/calendar-heatmap.ts +121 -0
- package/src/patterns/definitions/time/horizon-chart.ts +105 -0
- package/src/patterns/definitions/time/index.ts +8 -0
- package/src/patterns/definitions/time/line.ts +120 -0
- package/src/patterns/definitions/time/small-multiples.ts +113 -0
- package/src/patterns/definitions/time/sparkline-grid.ts +139 -0
- package/src/patterns/definitions/time/stream-graph.ts +136 -0
- package/src/patterns/index.ts +87 -0
- package/src/patterns/registry.ts +275 -0
- package/src/patterns/selector.ts +548 -0
- package/src/patterns/utils.ts +406 -0
- package/src/renderers/d3/comparison/bar.ts +397 -0
- package/src/renderers/d3/comparison/bullet.ts +252 -0
- package/src/renderers/d3/comparison/bump-chart.ts +262 -0
- package/src/renderers/d3/comparison/connected-dot-plot.ts +305 -0
- package/src/renderers/d3/comparison/diverging-bar.ts +374 -0
- package/src/renderers/d3/comparison/grouped-bar.ts +323 -0
- package/src/renderers/d3/comparison/index.ts +13 -0
- package/src/renderers/d3/comparison/lollipop.ts +422 -0
- package/src/renderers/d3/comparison/slope-chart.ts +322 -0
- package/src/renderers/d3/comparison/waterfall.ts +263 -0
- package/src/renderers/d3/composition/circle-pack.ts +246 -0
- package/src/renderers/d3/composition/donut.ts +226 -0
- package/src/renderers/d3/composition/icicle.ts +456 -0
- package/src/renderers/d3/composition/index.ts +13 -0
- package/src/renderers/d3/composition/marimekko.ts +312 -0
- package/src/renderers/d3/composition/metric.ts +238 -0
- package/src/renderers/d3/composition/stacked-bar.ts +309 -0
- package/src/renderers/d3/composition/sunburst.ts +403 -0
- package/src/renderers/d3/composition/treemap.ts +274 -0
- package/src/renderers/d3/composition/waffle.ts +170 -0
- package/src/renderers/d3/connected-scatter.ts +429 -0
- package/src/renderers/d3/distribution/beeswarm.ts +455 -0
- package/src/renderers/d3/distribution/box-plot.ts +453 -0
- package/src/renderers/d3/distribution/density-plot.ts +394 -0
- package/src/renderers/d3/distribution/histogram.ts +461 -0
- package/src/renderers/d3/distribution/index.ts +11 -0
- package/src/renderers/d3/distribution/ridgeline.ts +298 -0
- package/src/renderers/d3/distribution/strip-plot.ts +376 -0
- package/src/renderers/d3/distribution/violin.ts +381 -0
- package/src/renderers/d3/flow/alluvial.ts +464 -0
- package/src/renderers/d3/flow/chord.ts +278 -0
- package/src/renderers/d3/flow/funnel.ts +346 -0
- package/src/renderers/d3/flow/index.ts +9 -0
- package/src/renderers/d3/flow/sankey-layout.ts +202 -0
- package/src/renderers/d3/flow/sankey.ts +189 -0
- package/src/renderers/d3/geo/choropleth.ts +198 -0
- package/src/renderers/d3/geo/geo-registry.ts +289 -0
- package/src/renderers/d3/geo/geo-scope.ts +313 -0
- package/src/renderers/d3/geo/index.ts +6 -0
- package/src/renderers/d3/geo/names/countries.ts +245 -0
- package/src/renderers/d3/geo/names/fuzzy.ts +56 -0
- package/src/renderers/d3/geo/names/index.ts +5 -0
- package/src/renderers/d3/geo/names/normalize.ts +9 -0
- package/src/renderers/d3/geo/names/subdivisions.ts +642 -0
- package/src/renderers/d3/geo/proportional-symbol.ts +511 -0
- package/src/renderers/d3/geo/topojson-loader.ts +15 -0
- package/src/renderers/d3/heatmap.ts +273 -0
- package/src/renderers/d3/index.ts +230 -0
- package/src/renderers/d3/parallel-coordinates.ts +227 -0
- package/src/renderers/d3/radar.ts +313 -0
- package/src/renderers/d3/relationship.ts +288 -0
- package/src/renderers/d3/shared.ts +1029 -0
- package/src/renderers/d3/time/area.ts +552 -0
- package/src/renderers/d3/time/calendar-heatmap.ts +544 -0
- package/src/renderers/d3/time/horizon-chart.ts +395 -0
- package/src/renderers/d3/time/index.ts +11 -0
- package/src/renderers/d3/time/line.ts +409 -0
- package/src/renderers/d3/time/small-multiples.ts +190 -0
- package/src/renderers/d3/time/sparkline-grid.ts +237 -0
- package/src/renderers/d3/time/stream-graph.ts +401 -0
- package/src/renderers/html/_generated/bundles.ts +45 -0
- package/src/renderers/html/builders/alluvial.ts +7 -0
- package/src/renderers/html/builders/area.ts +7 -0
- package/src/renderers/html/builders/bar.ts +7 -0
- package/src/renderers/html/builders/beeswarm.ts +7 -0
- package/src/renderers/html/builders/box-plot.ts +7 -0
- package/src/renderers/html/builders/bullet.ts +7 -0
- package/src/renderers/html/builders/bump-chart.ts +7 -0
- package/src/renderers/html/builders/calendar-heatmap.ts +7 -0
- package/src/renderers/html/builders/chord.ts +7 -0
- package/src/renderers/html/builders/choropleth.ts +7 -0
- package/src/renderers/html/builders/circle-pack.ts +7 -0
- package/src/renderers/html/builders/compound.ts +481 -0
- package/src/renderers/html/builders/connected-dot-plot.ts +7 -0
- package/src/renderers/html/builders/connected-scatter.ts +7 -0
- package/src/renderers/html/builders/dashboard.ts +449 -0
- package/src/renderers/html/builders/density-plot.ts +7 -0
- package/src/renderers/html/builders/diverging-bar.ts +7 -0
- package/src/renderers/html/builders/donut.ts +7 -0
- package/src/renderers/html/builders/funnel.ts +7 -0
- package/src/renderers/html/builders/grouped-bar.ts +7 -0
- package/src/renderers/html/builders/heatmap.ts +7 -0
- package/src/renderers/html/builders/histogram.ts +7 -0
- package/src/renderers/html/builders/horizon-chart.ts +7 -0
- package/src/renderers/html/builders/icicle.ts +7 -0
- package/src/renderers/html/builders/line.ts +7 -0
- package/src/renderers/html/builders/lollipop.ts +7 -0
- package/src/renderers/html/builders/marimekko.ts +7 -0
- package/src/renderers/html/builders/metric.ts +7 -0
- package/src/renderers/html/builders/parallel-coordinates.ts +7 -0
- package/src/renderers/html/builders/proportional-symbol.ts +7 -0
- package/src/renderers/html/builders/radar.ts +7 -0
- package/src/renderers/html/builders/ridgeline.ts +7 -0
- package/src/renderers/html/builders/sankey.ts +7 -0
- package/src/renderers/html/builders/scatter.ts +7 -0
- package/src/renderers/html/builders/slope-chart.ts +7 -0
- package/src/renderers/html/builders/small-multiples.ts +7 -0
- package/src/renderers/html/builders/sparkline-grid.ts +7 -0
- package/src/renderers/html/builders/stacked-bar.ts +7 -0
- package/src/renderers/html/builders/stream-graph.ts +7 -0
- package/src/renderers/html/builders/strip-plot.ts +7 -0
- package/src/renderers/html/builders/sunburst.ts +7 -0
- package/src/renderers/html/builders/treemap.ts +7 -0
- package/src/renderers/html/builders/violin.ts +7 -0
- package/src/renderers/html/builders/waffle.ts +7 -0
- package/src/renderers/html/builders/waterfall.ts +7 -0
- package/src/renderers/html/compound.ts +178 -0
- package/src/renderers/html/index.ts +257 -0
- package/src/renderers/html/render/alluvial.render.ts +2 -0
- package/src/renderers/html/render/area.render.ts +2 -0
- package/src/renderers/html/render/bar.render.ts +2 -0
- package/src/renderers/html/render/beeswarm.render.ts +2 -0
- package/src/renderers/html/render/box-plot.render.ts +2 -0
- package/src/renderers/html/render/bullet.render.ts +2 -0
- package/src/renderers/html/render/bump-chart.render.ts +2 -0
- package/src/renderers/html/render/calendar-heatmap.render.ts +2 -0
- package/src/renderers/html/render/chord.render.ts +2 -0
- package/src/renderers/html/render/choropleth.render.ts +6 -0
- package/src/renderers/html/render/circle-pack.render.ts +2 -0
- package/src/renderers/html/render/connected-dot-plot.render.ts +2 -0
- package/src/renderers/html/render/connected-scatter.render.ts +2 -0
- package/src/renderers/html/render/density-plot.render.ts +2 -0
- package/src/renderers/html/render/diverging-bar.render.ts +2 -0
- package/src/renderers/html/render/donut.render.ts +2 -0
- package/src/renderers/html/render/funnel.render.ts +2 -0
- package/src/renderers/html/render/grouped-bar.render.ts +2 -0
- package/src/renderers/html/render/heatmap.render.ts +2 -0
- package/src/renderers/html/render/histogram.render.ts +2 -0
- package/src/renderers/html/render/horizon-chart.render.ts +2 -0
- package/src/renderers/html/render/icicle.render.ts +2 -0
- package/src/renderers/html/render/line.render.ts +2 -0
- package/src/renderers/html/render/lollipop.render.ts +2 -0
- package/src/renderers/html/render/marimekko.render.ts +2 -0
- package/src/renderers/html/render/metric.render.ts +2 -0
- package/src/renderers/html/render/parallel-coordinates.render.ts +2 -0
- package/src/renderers/html/render/proportional-symbol.render.ts +6 -0
- package/src/renderers/html/render/radar.render.ts +2 -0
- package/src/renderers/html/render/ridgeline.render.ts +2 -0
- package/src/renderers/html/render/sankey.render.ts +2 -0
- package/src/renderers/html/render/scatter.render.ts +2 -0
- package/src/renderers/html/render/slope-chart.render.ts +2 -0
- package/src/renderers/html/render/small-multiples.render.ts +2 -0
- package/src/renderers/html/render/sparkline-grid.render.ts +2 -0
- package/src/renderers/html/render/stacked-bar.render.ts +2 -0
- package/src/renderers/html/render/stream-graph.render.ts +2 -0
- package/src/renderers/html/render/strip-plot.render.ts +2 -0
- package/src/renderers/html/render/sunburst.render.ts +2 -0
- package/src/renderers/html/render/treemap.render.ts +2 -0
- package/src/renderers/html/render/violin.render.ts +2 -0
- package/src/renderers/html/render/waffle.render.ts +2 -0
- package/src/renderers/html/render/waterfall.render.ts +2 -0
- package/src/renderers/html/sizing.ts +150 -0
- package/src/renderers/html/template.ts +789 -0
- package/src/renderers/react/Alluvial.tsx +21 -0
- package/src/renderers/react/Area.tsx +21 -0
- package/src/renderers/react/Bar.tsx +21 -0
- package/src/renderers/react/Beeswarm.tsx +21 -0
- package/src/renderers/react/BoxPlot.tsx +16 -0
- package/src/renderers/react/Bullet.tsx +15 -0
- package/src/renderers/react/BumpChart.tsx +37 -0
- package/src/renderers/react/CalendarHeatmap.tsx +21 -0
- package/src/renderers/react/Chord.tsx +21 -0
- package/src/renderers/react/Choropleth.tsx +35 -0
- package/src/renderers/react/CirclePack.tsx +21 -0
- package/src/renderers/react/CompoundChart.tsx +146 -0
- package/src/renderers/react/ConnectedDotPlot.tsx +21 -0
- package/src/renderers/react/ConnectedScatter.tsx +21 -0
- package/src/renderers/react/DataTable.tsx +214 -0
- package/src/renderers/react/DensityPlot.tsx +15 -0
- package/src/renderers/react/DivergingBar.tsx +21 -0
- package/src/renderers/react/Donut.tsx +21 -0
- package/src/renderers/react/Funnel.tsx +15 -0
- package/src/renderers/react/GroupedBar.tsx +15 -0
- package/src/renderers/react/Heatmap.tsx +16 -0
- package/src/renderers/react/Histogram.tsx +21 -0
- package/src/renderers/react/HorizonChart.tsx +15 -0
- package/src/renderers/react/Icicle.tsx +15 -0
- package/src/renderers/react/Line.tsx +21 -0
- package/src/renderers/react/Lollipop.tsx +15 -0
- package/src/renderers/react/Marimekko.tsx +21 -0
- package/src/renderers/react/Metric.tsx +21 -0
- package/src/renderers/react/ParallelCoordinates.tsx +21 -0
- package/src/renderers/react/ProportionalSymbol.tsx +35 -0
- package/src/renderers/react/Radar.tsx +21 -0
- package/src/renderers/react/Ridgeline.tsx +21 -0
- package/src/renderers/react/Sankey.tsx +21 -0
- package/src/renderers/react/Scatter.tsx +21 -0
- package/src/renderers/react/SlopeChart.tsx +21 -0
- package/src/renderers/react/SmallMultiples.tsx +21 -0
- package/src/renderers/react/SparklineGrid.tsx +21 -0
- package/src/renderers/react/StackedBar.tsx +21 -0
- package/src/renderers/react/StreamGraph.tsx +15 -0
- package/src/renderers/react/StripPlot.tsx +21 -0
- package/src/renderers/react/Sunburst.tsx +21 -0
- package/src/renderers/react/Treemap.tsx +21 -0
- package/src/renderers/react/Violin.tsx +21 -0
- package/src/renderers/react/Waffle.tsx +21 -0
- package/src/renderers/react/Waterfall.tsx +15 -0
- package/src/renderers/react/index.ts +86 -0
- package/src/renderers/react/types.ts +18 -0
- package/src/renderers/react/useChart.ts +58 -0
- package/src/theme/colors.ts +286 -0
- package/src/theme/index.ts +184 -0
- package/src/theme/spacing.ts +176 -0
- package/src/theme/typography.ts +170 -0
- package/src/types.ts +601 -0
- package/src/utils/export.ts +148 -0
- package/src/utils/index.ts +37 -0
- package/src/utils/labels.ts +266 -0
- package/src/utils/responsive.ts +121 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/build-render-bundles.ts — DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
export const alluvialBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var alluvial_render_exports={};__export(alluvial_render_exports,{renderChart:()=>renderAlluvial});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderAlluvial(container,spec){const{config,encoding,data}=spec;const stageFields=config.stageFields||[];const valueField=config.valueField||\"value\";const nodeWidth=config.nodeWidth??20;const nodePadding=config.nodePadding??10;const flowOpacity=config.flowOpacity??.4;const showLabels=config.showLabels!==false;const showValues=config.showValues===true;const colorBy=config.colorBy||\"source\";if(stageFields.length<2){container.innerHTML='<p style=\"color:#ef4444;padding:20px;\">Alluvial requires at least 2 stage fields</p>';return}const containerW=container.clientWidth||800;const containerH=container.clientHeight||500;const isSmall=containerW<450||containerH<320;const labelMargin=isSmall?10:80;const{svg,g,dims}=createSvg(container,spec,{top:40,left:labelMargin,right:labelMargin,bottom:isSmall?20:30});const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){renderEmptyState(g,dims);return}const allCategories=[];const catSet=new Set;for(const field of stageFields){for(const row of data){const cat=String(row[field]);if(!catSet.has(cat)){catSet.add(cat);allCategories.push(cat)}}}const colorField=encoding?.color?.field||stageFields[0];const syntheticColorData=allCategories.map(cat=>({[colorField]:cat}));const colorScale=encoding?.color?buildColorScale(encoding.color,syntheticColorData):d3.scaleOrdinal().domain(allCategories).range(categorical);const stageNodes=[];for(let si=0;si<stageFields.length;si++){const field=stageFields[si];const categoryTotals=new Map;for(const row of data){const cat=String(row[field]);const val=Number(row[valueField])||0;categoryTotals.set(cat,(categoryTotals.get(cat)||0)+val)}const sorted=[...categoryTotals.entries()].sort((a,b)=>b[1]-a[1]);const nodes=sorted.map(([category,value])=>({stage:si,category,value,x0:0,x1:0,y0:0,y1:0}));stageNodes.push(nodes)}const numStages=stageFields.length;const columnGap=numStages>1?(dims.innerWidth-nodeWidth)/(numStages-1):0;for(let si=0;si<numStages;si++){const nodes=stageNodes[si];const x0=si*columnGap;const x1=x0+nodeWidth;const totalValue=nodes.reduce((s,n)=>s+n.value,0);const totalPadding=Math.max(0,(nodes.length-1)*nodePadding);const availableHeight=dims.innerHeight-totalPadding;const scale=totalValue>0?availableHeight/totalValue:1;const MIN_NODE_HEIGHT=3;let y=0;for(const node of nodes){node.x0=x0;node.x1=x1;node.y0=y;node.y1=y+Math.max(node.value*scale,MIN_NODE_HEIGHT);y=node.y1+nodePadding}const excess=y-nodePadding-dims.innerHeight;if(excess>0&&nodes.length>0){const compressionFactor=dims.innerHeight/(y-nodePadding);let cy=0;for(const node of nodes){const h=(node.y1-node.y0)*compressionFactor;node.y0=cy;node.y1=cy+h;cy+=h+nodePadding*compressionFactor}}}const allFlows=[];for(let si=0;si<numStages-1;si++){const sourceField=stageFields[si];const targetField=stageFields[si+1];const flowMap=new Map;for(const row of data){const sCat=String(row[sourceField]);const tCat=String(row[targetField]);const val=Number(row[valueField])||0;const key=`${sCat}|||${tCat}`;flowMap.set(key,(flowMap.get(key)||0)+val)}const sourceNodeMap=new Map;for(const n of stageNodes[si])sourceNodeMap.set(n.category,n);const targetNodeMap=new Map;for(const n of stageNodes[si+1])targetNodeMap.set(n.category,n);const stageFlows=[];for(const[key,value]of flowMap){const[sCat,tCat]=key.split(\"|||\");const sourceNode=sourceNodeMap.get(sCat);const targetNode=targetNodeMap.get(tCat);if(!sourceNode||!targetNode)continue;stageFlows.push({sourceStage:si,sourceCategory:sCat,targetCategory:tCat,value,sy0:0,sy1:0,ty0:0,ty1:0,sourceNode,targetNode})}stageFlows.sort((a,b)=>{const sOrderA=stageNodes[si].indexOf(a.sourceNode);const sOrderB=stageNodes[si].indexOf(b.sourceNode);if(sOrderA!==sOrderB)return sOrderA-sOrderB;const tOrderA=stageNodes[si+1].indexOf(a.targetNode);const tOrderB=stageNodes[si+1].indexOf(b.targetNode);return tOrderA-tOrderB});const sourceOffsets=new Map;for(const n of stageNodes[si])sourceOffsets.set(n.category,n.y0);const MIN_FLOW_HEIGHT=2;for(const flow of stageFlows){const sourceNode=flow.sourceNode;const nodeHeight=sourceNode.y1-sourceNode.y0;const flowHeight=sourceNode.value>0?Math.max(flow.value/sourceNode.value*nodeHeight,MIN_FLOW_HEIGHT):0;const offset=sourceOffsets.get(flow.sourceCategory)||sourceNode.y0;flow.sy0=offset;flow.sy1=offset+flowHeight;sourceOffsets.set(flow.sourceCategory,offset+flowHeight)}const targetSorted=[...stageFlows].sort((a,b)=>{const tOrderA=stageNodes[si+1].indexOf(a.targetNode);const tOrderB=stageNodes[si+1].indexOf(b.targetNode);if(tOrderA!==tOrderB)return tOrderA-tOrderB;const sOrderA=stageNodes[si].indexOf(a.sourceNode);const sOrderB=stageNodes[si].indexOf(b.sourceNode);return sOrderA-sOrderB});const targetOffsets=new Map;for(const n of stageNodes[si+1])targetOffsets.set(n.category,n.y0);for(const flow of targetSorted){const targetNode=flow.targetNode;const nodeHeight=targetNode.y1-targetNode.y0;const flowHeight=targetNode.value>0?Math.max(flow.value/targetNode.value*nodeHeight,MIN_FLOW_HEIGHT):0;const offset=targetOffsets.get(flow.targetCategory)||targetNode.y0;flow.ty0=offset;flow.ty1=offset+flowHeight;targetOffsets.set(flow.targetCategory,offset+flowHeight)}allFlows.push(...stageFlows)}drawFlows(g,allFlows,colorScale,flowOpacity,colorBy,tooltip);const flatNodes=stageNodes.flat();drawNodes(g,flatNodes,allFlows,colorScale,flowOpacity,tooltip);if(showLabels&&!isSmall){drawLabels(g,stageNodes,stageFields,showValues,numStages,dims)}}function ribbonPath(flow){const sx=flow.sourceNode.x1;const tx=flow.targetNode.x0;const mx=(sx+tx)/2;return`\n M ${sx},${flow.sy0}\n C ${mx},${flow.sy0} ${mx},${flow.ty0} ${tx},${flow.ty0}\n L ${tx},${flow.ty1}\n C ${mx},${flow.ty1} ${mx},${flow.sy1} ${sx},${flow.sy1}\n Z\n `}function drawFlows(g,flows,colorScale,flowOpacity,colorBy,tooltip){g.selectAll(\".alluvial-flow\").data(flows).join(\"path\").attr(\"class\",\"alluvial-flow\").attr(\"d\",ribbonPath).attr(\"fill\",d=>colorBy===\"target\"?colorScale(d.targetCategory):colorScale(d.sourceCategory)).attr(\"opacity\",flowOpacity).attr(\"stroke\",\"none\").on(\"mouseover\",function(event,d){d3.select(this).attr(\"opacity\",Math.min(flowOpacity+.3,.9));showTooltip(tooltip,`<strong>${d.sourceCategory} \\u2192 ${d.targetCategory}</strong><br/>Value: ${formatValue(d.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"opacity\",flowOpacity);hideTooltip(tooltip)})}function drawNodes(g,nodes,allFlows,colorScale,flowOpacity,tooltip){g.selectAll(\".alluvial-node\").data(nodes).join(\"rect\").attr(\"class\",\"alluvial-node\").attr(\"x\",d=>d.x0).attr(\"y\",d=>d.y0).attr(\"width\",d=>d.x1-d.x0).attr(\"height\",d=>Math.max(d.y1-d.y0,3)).attr(\"fill\",d=>colorScale(d.category)).attr(\"rx\",2).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).on(\"mouseover\",function(event,d){d3.select(this).attr(\"opacity\",.8);g.selectAll(\".alluvial-flow\").attr(\"opacity\",f=>{const connected=f.sourceNode.stage===d.stage&&f.sourceCategory===d.category||f.targetNode.stage===d.stage&&f.targetCategory===d.category;return connected?Math.min(flowOpacity+.3,.9):.06});const inflows=allFlows.filter(f=>f.targetNode.stage===d.stage&&f.targetCategory===d.category);const outflows=allFlows.filter(f=>f.sourceNode.stage===d.stage&&f.sourceCategory===d.category);const inflowTotal=inflows.reduce((s,f)=>s+f.value,0);const outflowTotal=outflows.reduce((s,f)=>s+f.value,0);let html=`<strong>${d.category}</strong><br/>Total: ${formatValue(d.value)}`;if(inflowTotal>0)html+=`<br/>Inflow: ${formatValue(inflowTotal)}`;if(outflowTotal>0)html+=`<br/>Outflow: ${formatValue(outflowTotal)}`;showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"opacity\",1);g.selectAll(\".alluvial-flow\").attr(\"opacity\",flowOpacity);hideTooltip(tooltip)})}function drawLabels(g,stageNodes,stageFields,showValues,numStages,dims){for(let si=0;si<numStages;si++){const nodes=stageNodes[si];if(nodes.length===0)continue;const x=(nodes[0].x0+nodes[0].x1)/2;g.append(\"text\").attr(\"x\",x).attr(\"y\",dims.innerHeight+16).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(stageFields[si])}const lastStage=numStages-1;const flatNodes=stageNodes.flat();g.selectAll(\".alluvial-label\").data(flatNodes).join(\"text\").attr(\"class\",\"alluvial-label\").attr(\"x\",d=>{if(d.stage===0)return d.x0-6;if(d.stage===lastStage)return d.x1+6;return d.x1+6}).attr(\"y\",d=>(d.y0+d.y1)/2).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",d=>d.stage===0?\"end\":\"start\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>{if(d.y1-d.y0<12)return\"\";const isRight=d.stage>0;const availPx=isRight?dims.innerWidth-d.x1-6:d.x0-6;const maxChars=Math.min(18,Math.max(8,Math.floor(availPx/6)));const label=truncateLabel(d.category,maxChars);if(showValues)return`${label} (${formatValue(d.value)})`;return label})}return __toCommonJS(alluvial_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
4
|
+
export const areaBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var area_render_exports={};__export(area_render_exports,{renderChart:()=>renderArea});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderArea(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field||null;const stacked=config.stacked??false;const normalized=config.normalized??false;const fillOpacity=config.opacity??.7;const interpolation=config.curve||config.interpolation||\"monotone\";const parsedData=data.map(d=>({...d,_date:parseDate(d[timeField]),_value:Number(d[valueField])})).filter(d=>d._date!==null&&!isNaN(d._value));const colorScale=buildColorScale(encoding.color,data);const seriesNames=seriesField?[...new Set(parsedData.map(d=>d[seriesField]))]:[];const isMultiSeries=seriesNames.length>1;const isStacked=isMultiSeries&&(stacked||normalized);container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);if(isMultiSeries){const legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}const{svg,g,dims}=createSvg(chartWrapper,spec,{right:30,top:40,bottom:70});svg.style(\"background\",\"none\");const tooltip=createTooltip(chartWrapper);if(parsedData.every(d=>d._value===0)){renderEmptyState(g,dims);return}const curveMap={linear:d3.curveLinear,monotone:d3.curveMonotoneX,curve:d3.curveBasis,step:d3.curveStepAfter,cardinal:d3.curveCardinal,catmullRom:d3.curveCatmullRom};const curve=curveMap[interpolation]||d3.curveMonotoneX;const uniqueDateCount=new Set(parsedData.map(d=>d._date.getTime())).size;if(uniqueDateCount<=1){const xExtent=d3.extent(parsedData,d=>d._date);const xScale=d3.scaleTime().domain(xExtent).range([0,dims.innerWidth]);const yExtent=d3.extent(parsedData,d=>d._value);const yScale=d3.scaleLinear().domain([0,yExtent[1]*1.1||1]).range([dims.innerHeight,0]).nice();drawAxes(g,xScale,yScale,dims,false,1);parsedData.forEach(d=>{const c=isMultiSeries?colorScale(d[seriesField]):categorical[0];g.append(\"circle\").attr(\"cx\",xScale(d._date)).attr(\"cy\",yScale(d._value)).attr(\"r\",6).attr(\"fill\",c).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2);g.append(\"text\").attr(\"x\",xScale(d._date)).attr(\"y\",yScale(d._value)-14).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(formatValue(d._value))})}else if(isStacked){drawStackedArea(g,parsedData,seriesField,seriesNames,colorScale,curve,dims,tooltip,timeField,valueField,fillOpacity,normalized)}else if(isMultiSeries){drawOverlappingAreas(g,parsedData,seriesField,seriesNames,colorScale,curve,dims,tooltip,timeField,valueField,fillOpacity)}else{drawSingleArea(g,parsedData,curve,dims,tooltip,timeField,valueField,fillOpacity)}}function parseDate(v){if(v instanceof Date)return v;const d=new Date(v);return isNaN(d.getTime())?null:d}function drawSingleArea(g,parsedData,curve,dims,tooltip,timeField,valueField,fillOpacity){const sorted=[...parsedData].sort((a,b)=>a._date.getTime()-b._date.getTime());const color=categorical[0];const xExtent=d3.extent(sorted,d=>d._date);const xScale=d3.scaleTime().domain(xExtent).range([0,dims.innerWidth]);const yMin=d3.min(sorted,d=>d._value);const yMax=d3.max(sorted,d=>d._value);const yScale=d3.scaleLinear().domain([Math.min(0,yMin),yMax*1.05]).range([dims.innerHeight,0]).nice();drawAxes(g,xScale,yScale,dims,false,sorted.length);const areaGen=d3.area().x(d=>xScale(d._date)).y0(yScale(0)).y1(d=>yScale(d._value)).curve(curve);const lineGen=d3.line().x(d=>xScale(d._date)).y(d=>yScale(d._value)).curve(curve);g.append(\"path\").datum(sorted).attr(\"fill\",color).attr(\"opacity\",fillOpacity).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\");g.append(\"path\").datum(sorted).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",2).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\");addCrosshairHover(g,sorted,null,[],timeField,valueField,null,xScale,yScale,dims,tooltip,false)}function drawOverlappingAreas(g,parsedData,seriesField,seriesNames,colorScale,curve,dims,tooltip,timeField,valueField,fillOpacity){const xExtent=d3.extent(parsedData,d=>d._date);const xScale=d3.scaleTime().domain(xExtent).range([0,dims.innerWidth]);const yMinO=d3.min(parsedData,d=>d._value);const yMax=d3.max(parsedData,d=>d._value);const yScale=d3.scaleLinear().domain([Math.min(0,yMinO),yMax*1.05]).range([dims.innerHeight,0]).nice();const uniqueTimes=new Set(parsedData.map(d=>d._date.getTime())).size;drawAxes(g,xScale,yScale,dims,false,uniqueTimes);const areaGen=d3.area().x(d=>xScale(d._date)).y0(yScale(0)).y1(d=>yScale(d._value)).curve(curve);const lineGen=d3.line().x(d=>xScale(d._date)).y(d=>yScale(d._value)).curve(curve);seriesNames.forEach(name=>{const seriesData=parsedData.filter(d=>d[seriesField]===name).sort((a,b)=>a._date.getTime()-b._date.getTime());const color=colorScale(name);g.append(\"path\").datum(seriesData).attr(\"fill\",color).attr(\"opacity\",fillOpacity*.5).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\");g.append(\"path\").datum(seriesData).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",2).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\")});addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,true)}function drawStackedArea(g,parsedData,seriesField,seriesNames,colorScale,curve,dims,tooltip,timeField,valueField,fillOpacity,normalized){const dateMap=new Map;parsedData.forEach(d=>{const key=d._date.getTime();if(!dateMap.has(key))dateMap.set(key,{});dateMap.get(key)[d[seriesField]]=d._value});const sortedTimes=[...dateMap.keys()].sort((a,b)=>a-b);const wideData=sortedTimes.map(t=>{const row={_date:new Date(t)};const values=dateMap.get(t);seriesNames.forEach(name=>{row[name]=values[name]||0});return row});const stackGen=d3.stack().keys(seriesNames);if(normalized){stackGen.offset(d3.stackOffsetExpand)}const stacked=stackGen(wideData);const xScale=d3.scaleTime().domain(d3.extent(wideData,d=>d._date)).range([0,dims.innerWidth]);let yMinS;let yMaxS;if(normalized){yMinS=0;yMaxS=1}else{yMinS=d3.min(stacked,layer=>d3.min(layer,d=>d[0]));yMaxS=d3.max(stacked,layer=>d3.max(layer,d=>d[1]))}const yScale=d3.scaleLinear().domain([Math.min(0,yMinS),yMaxS]).range([dims.innerHeight,0]).nice();drawAxes(g,xScale,yScale,dims,normalized,wideData.length);const areaGen=d3.area().x(d=>xScale(d.data._date)).y0(d=>yScale(d[0])).y1(d=>yScale(d[1])).curve(curve);stacked.forEach(layer=>{const color=colorScale(layer.key);g.append(\"path\").datum(layer).attr(\"fill\",color).attr(\"opacity\",fillOpacity).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\");const lineGen=d3.line().x(d=>xScale(d.data._date)).y(d=>yScale(d[1])).curve(curve);g.append(\"path\").datum(layer).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",1).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\")});addStackedCrosshairHover(g,wideData,stacked,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,normalized)}function drawAxes(g,xScale,yScale,dims,normalized,dataPointCount){let xTickCount=getAdaptiveTickCount(dims.innerWidth);if(dataPointCount&&dataPointCount<xTickCount){xTickCount=dataPointCount}const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(0).tickPadding(8));styleAxis(xAxis);xAxis.selectAll(\".tick text\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\").attr(\"transform\",\"rotate(-35)\");const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxisCall=d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8);if(normalized){yAxisCall.tickFormat(d=>Math.round(d*100)+\"%\")}else{yAxisCall.tickFormat(d=>formatValue(d))}const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(yAxisCall);styleAxis(yAxis)}function addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,isMultiSeries){const dateMap=new Map;parsedData.forEach(d=>{const key=d._date.getTime();if(!dateMap.has(key))dateMap.set(key,[]);dateMap.get(key).push(d)});const sortedDates=[...dateMap.keys()].sort((a,b)=>a-b);const crosshairLine=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const highlightDots=g.append(\"g\").attr(\"class\",\"highlight-dots\").attr(\"pointer-events\",\"none\");g.append(\"rect\").attr(\"class\",\"hover-area\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,this);const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(d=>d).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestTime=sortedDates[idx];const nearestX=xScale(new Date(nearestTime));const points=dateMap.get(nearestTime)||[];crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();points.forEach(d=>{const color=isMultiSeries?colorScale(d[seriesField]):categorical[0];highlightDots.append(\"circle\").attr(\"cx\",nearestX).attr(\"cy\",yScale(d._value)).attr(\"r\",5).attr(\"fill\",color).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2)});const dateLabel=points[0]?.[timeField]??new Date(nearestTime).toLocaleDateString();let html=`<strong>${dateLabel}</strong>`;if(isMultiSeries){const sorted=[...points].sort((a,b)=>b._value-a._value);sorted.forEach(d=>{const color=colorScale(d[seriesField]);html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${d[seriesField]}: ${formatValue(d._value)}`})}else{html+=`<br/>${valueField}: ${formatValue(points[0]?._value)}`}showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();hideTooltip(tooltip)})}function addStackedCrosshairHover(g,wideData,stacked,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,normalized){const sortedDates=wideData.map(d=>d._date.getTime());const crosshairLine=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const highlightDots=g.append(\"g\").attr(\"class\",\"highlight-dots\").attr(\"pointer-events\",\"none\");g.append(\"rect\").attr(\"class\",\"hover-area\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,this);const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(d=>d).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestX=xScale(wideData[idx]._date);crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();const dateStr=wideData[idx]._date.toLocaleDateString();let html=`<strong>${dateStr}</strong>`;const reversedNames=[...seriesNames].reverse();reversedNames.forEach(name=>{const layer=stacked.find(l=>l.key===name);if(!layer)return;const pt=layer[idx];const val=pt.data[name];const stackedY=yScale(pt[1]);const color=colorScale(name);highlightDots.append(\"circle\").attr(\"cx\",nearestX).attr(\"cy\",stackedY).attr(\"r\",4).attr(\"fill\",color).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2);if(normalized){const pct=((pt[1]-pt[0])*100).toFixed(1);html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${name}: ${formatValue(val)} (${pct}%)`}else{html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${name}: ${formatValue(val)}`}});showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();hideTooltip(tooltip)})}return __toCommonJS(area_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
5
|
+
export const barBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var bar_render_exports={};__export(bar_render_exports,{renderChart:()=>renderBar});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderBar(container,spec){const{config,encoding,data}=spec;const isHorizontal=config.orientation===\"horizontal\";let sortedData=[...data];if(config.sortBy===\"value\"&&encoding.y){const yField=encoding.y.field;const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>order*(Number(a[yField])-Number(b[yField])))}if(config.sortBy===\"category\"&&encoding.x){const xField2=encoding.x.field;const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>{const aVal=String(a[xField2]);const bVal=String(b[xField2]);return order*aVal.localeCompare(bVal,void 0,{sensitivity:\"base\",numeric:true})})}let marginOverrides;if(isHorizontal){const yField=encoding.x.field;const labels=sortedData.map(d=>d[yField]);const leftMargin=calculateLeftMargin(labels);marginOverrides={left:leftMargin,bottom:40}}else{const xField2=encoding.x.field;const labels=sortedData.map(d=>d[xField2]);const containerWidth=container.clientWidth||800;const estimatedBarWidth=(containerWidth-140)/labels.length;const willRotate=shouldRotateLabels(labels,estimatedBarWidth);const bottomMargin=calculateBottomMargin(labels,willRotate);marginOverrides={bottom:bottomMargin,left:70}}const{svg,g,dims}=createSvg(container,spec,marginOverrides);const tooltip=createTooltip(container);if(isAllZeros(data,encoding.y.field)){renderEmptyState(g,dims);return}if(isHorizontal){renderHorizontalBar(g,sortedData,data,encoding,config,dims,tooltip)}else{renderVerticalBar(g,sortedData,data,encoding,config,dims,tooltip)}const xField=encoding.x?.field;const hasCategoricalLabels=xField&&sortedData.some(d=>{const value=d[xField];return typeof value===\"string\"&&isNaN(Number(value))});if(hasCategoricalLabels){addSortControls(svg,container,spec,dims,renderBar)}}function renderHorizontalBar(g,data,originalData,encoding,config,dims,tooltip){const yField=encoding.x.field;const xField=encoding.y.field;const categories=data.map(d=>d[yField]);const yScale=d3.scaleBand().domain(categories).range([0,dims.innerHeight]).padding(.2);const allVals=data.map(d=>Number(d[xField]));const minVal=d3.min(allVals);const maxVal=d3.max(allVals);const xScale=d3.scaleLinear().domain([Math.min(0,minVal),Math.max(0,maxVal)]).range([0,dims.innerWidth]).nice();const colorScale=buildColorScale(encoding.color,originalData,xField);const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(10).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);const maxBarHeight=Math.min(80,dims.innerHeight*.3);const barHeight=Math.min(yScale.bandwidth(),maxBarHeight);const barYOffset=(yScale.bandwidth()-barHeight)/2;g.selectAll(\".bar-hover-target\").data(data).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"y\",d=>yScale(d[yField])).attr(\"x\",0).attr(\"height\",yScale.bandwidth()).attr(\"width\",dims.innerWidth).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd[yField]===d[yField]).attr(\"opacity\",.8);showTooltip(tooltip,`<strong>${d[yField]}</strong><br/>${xField}: ${formatValue(Number(d[xField]))}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(data).join(\"rect\").attr(\"class\",\"bar\").attr(\"y\",d=>yScale(d[yField])+barYOffset).attr(\"x\",d=>{const v=Number(d[xField]);return v>=0?xScale(0):xScale(v)}).attr(\"height\",barHeight).attr(\"width\",d=>Math.max(2,Math.abs(xScale(Number(d[xField]))-xScale(0)))).attr(\"fill\",d=>colorScale(d[encoding.color?.field||yField])).attr(\"rx\",3).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,barHeight,true);if(showLabels){g.selectAll(\".bar-label\").data(data).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>{const v=Number(d[xField]);const bw=Math.abs(xScale(v)-xScale(0));if(v>=0){return bw>50?xScale(v)-5:xScale(v)+8}else{return bw>50?xScale(v)+5:xScale(v)-8}}).attr(\"y\",d=>yScale(d[yField])+yScale.bandwidth()/2).attr(\"text-anchor\",d=>{const v=Number(d[xField]);const barWidth=Math.abs(xScale(v)-xScale(0));if(v>=0)return barWidth>50?\"end\":\"start\";return barWidth>50?\"start\":\"end\"}).attr(\"dominant-baseline\",\"middle\").attr(\"fill\",d=>{const barWidth=Math.abs(xScale(Number(d[xField]))-xScale(0));return barWidth>50?\"#ffffff\":TEXT_MUTED}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").style(\"opacity\",1).text(d=>formatValue(Number(d[xField])))}}function renderVerticalBar(g,data,originalData,encoding,config,dims,tooltip){const xField=encoding.x.field;const yField=encoding.y.field;const categories=data.map(d=>d[xField]);const xScale=d3.scaleBand().domain(categories).range([0,dims.innerWidth]).padding(.2);const allValsV=data.map(d=>Number(d[yField]));const minValV=d3.min(allValsV);const maxValV=d3.max(allValsV);const yScale=d3.scaleLinear().domain([Math.min(0,minValV),Math.max(0,maxValV)]).range([dims.innerHeight,0]).nice();const colorScale=buildColorScale(encoding.color,originalData,yField);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);const bandwidth=xScale.bandwidth();const needsRotation=shouldRotateLabels(categories,bandwidth);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const maxBarWidth=Math.min(80,dims.innerWidth*.3);const barWidth=Math.min(xScale.bandwidth(),maxBarWidth);const barXOffset=(xScale.bandwidth()-barWidth)/2;g.selectAll(\".bar-hover-target\").data(data).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(d[xField])).attr(\"y\",0).attr(\"width\",xScale.bandwidth()).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd[xField]===d[xField]).attr(\"opacity\",.8);showTooltip(tooltip,`<strong>${d[xField]}</strong><br/>${yField}: ${formatValue(Number(d[yField]))}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(data).join(\"rect\").attr(\"class\",\"bar\").attr(\"x\",d=>xScale(d[xField])+barXOffset).attr(\"y\",d=>{const v=Number(d[yField]);return v>=0?yScale(v):yScale(0)}).attr(\"width\",barWidth).attr(\"height\",d=>Math.max(2,Math.abs(yScale(0)-yScale(Number(d[yField]))))).attr(\"fill\",d=>colorScale(d[encoding.color?.field||xField])).attr(\"rx\",3).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,barWidth,false);if(showLabels){g.selectAll(\".bar-label\").data(data).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>xScale(d[xField])+xScale.bandwidth()/2).attr(\"y\",d=>{const v=Number(d[yField]);const barHeight=Math.abs(yScale(0)-yScale(v));if(v>=0){return barHeight<20?yScale(v)-6:yScale(v)+14}else{return barHeight<20?yScale(0)+barHeight+14:yScale(0)+14}}).attr(\"text-anchor\",\"middle\").attr(\"fill\",d=>{const barHeight=Math.abs(yScale(0)-yScale(Number(d[yField])));return barHeight<20?TEXT_MUTED:\"#ffffff\"}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").style(\"opacity\",1).text(d=>formatValue(Number(d[yField])))}}return __toCommonJS(bar_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
6
|
+
export const beeswarmBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var beeswarm_render_exports={};__export(beeswarm_render_exports,{renderChart:()=>renderBeeswarm});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function dodgeBeeswarm(xPositions,spacing,maxOffset){const offsets=new Array(xPositions.length).fill(0);const placed=[];for(let i=0;i<xPositions.length;i++){const x=xPositions[i];let bestY=0;let found=false;for(let dy=0;dy<=maxOffset;dy+=spacing*.9){for(const sign of dy===0?[1]:[1,-1]){const candidateY=sign*dy;const overlaps=placed.some(p=>Math.sqrt((p.x-x)**2+(p.y-candidateY)**2)<spacing);if(!overlaps){bestY=candidateY;found=true;break}}if(found)break}offsets[i]=bestY;placed.push({x,y:bestY})}return offsets}function renderBeeswarm(container,spec){const{config,encoding,data}=spec;const valueField=config.valueField||encoding.x?.field||Object.keys(data[0])[0];const categoryField=config.categoryField||encoding.y?.field||null;const baseRadius=config.dotRadius??4;const opacity=config.opacity??.7;const hasLegend=categoryField!==null&&encoding.color?.field!=null;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const containerWidth=container.clientWidth||800;const isSmall=containerWidth<=400;let leftMargin=12;if(categoryField&&!isSmall){const groups=[...new Set(data.map(d=>String(d[categoryField])))];leftMargin=calculateLeftMargin(groups.map(l=>truncateLabel(l,25)))}const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin,right:20});const tooltip=createTooltip(container);const xValues=data.map(d=>Number(d[valueField]));const xExtent=d3.extent(xValues);const xPad=(xExtent[1]-xExtent[0])*.05||1;const xScale=d3.scaleLinear().domain([xExtent[0]-xPad,xExtent[1]+xPad]).range([0,dims.innerWidth]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const colorScale=buildColorScale(encoding.color,data);if(categoryField){renderGroupedBeeswarm(g,data,valueField,categoryField,encoding,config,xScale,colorScale,baseRadius,opacity,dims,tooltip,isSmall)}else{renderSingleBeeswarm(g,data,valueField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip)}if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"circle\",callbacks:{onHover:category=>{g.selectAll(\".dot\").each(function(){const match=d3.select(this).datum()?.[encoding.color?.field||categoryField]===category;d3.select(this).attr(\"opacity\",match?1:.08).attr(\"r\",match?Number(d3.select(this).attr(\"data-r\"))*1.3:Number(d3.select(this).attr(\"data-r\")))})},onLeave:()=>{g.selectAll(\".dot\").each(function(){d3.select(this).attr(\"opacity\",opacity).attr(\"r\",Number(d3.select(this).attr(\"data-r\")))})}}});container.appendChild(legendDiv)}}function renderGroupedBeeswarm(g,data,valueField,categoryField,encoding,config,xScale,colorScale,baseRadius,opacity,dims,tooltip,isSmall){const groups=[...new Set(data.map(d=>d[categoryField]))];const yScale=d3.scaleBand().domain(groups).range([0,dims.innerHeight]).padding(.15);const bandwidth=yScale.bandwidth();if(!isSmall){const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);const colorField=encoding.color?.field||categoryField;yAxis.selectAll(\".tick text\").each(function(label){d3.select(this).attr(\"fill\",colorScale(label))})}groups.forEach(group=>{const bandTop=yScale(group);g.append(\"line\").attr(\"x1\",0).attr(\"y1\",bandTop).attr(\"x2\",dims.innerWidth).attr(\"y2\",bandTop).attr(\"stroke\",\"#1f2937\").attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\")});const totalPoints=data.length;const plotArea=dims.innerWidth*bandwidth*groups.length/1e4;const density=totalPoints/Math.max(plotArea,1);let dotRadius=baseRadius;if(density>8)dotRadius=Math.max(2,baseRadius-2);else if(density>4)dotRadius=Math.max(2.5,baseRadius-1);dotRadius=Math.min(dotRadius,bandwidth/4);const pointPositions=[];groups.forEach(group=>{const groupData=data.filter(d=>d[categoryField]===group);const bandMid=yScale(group)+bandwidth/2;groupData.sort((a,b)=>Number(a[valueField])-Number(b[valueField]));const xPositions=groupData.map(d=>xScale(Number(d[valueField])));const offsets=dodgeBeeswarm(xPositions,dotRadius*2.2,bandwidth/2-dotRadius);groupData.forEach((d,j)=>{const globalIdx=data.indexOf(d);pointPositions.push({d,i:pointPositions.length,cx:xPositions[j],cy:bandMid+offsets[j],r:dotRadius})})});const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").filter((_,j)=>j===p.i).attr(\"r\",p.r*1.6).attr(\"opacity\",1);let html=`<strong>${p.d[categoryField]}</strong>`;html+=`<br/>${encoding.x?.title||valueField}: ${formatValue(Number(p.d[valueField]))}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity);activeIdx=-1}hideTooltip(tooltip)});g.selectAll(\".dot\").data(pointPositions).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",p=>p.cx).attr(\"cy\",p=>p.cy).attr(\"r\",p=>p.r).attr(\"data-r\",p=>p.r).attr(\"fill\",p=>colorScale(p.d[encoding.color?.field||categoryField])).attr(\"opacity\",opacity).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.8).attr(\"pointer-events\",\"none\");if(config.showMedianLine){groups.forEach(group=>{const groupValues=data.filter(d=>d[categoryField]===group).map(d=>Number(d[valueField])).sort((a,b)=>a-b);const mid=Math.floor(groupValues.length/2);const median=groupValues.length%2===0?(groupValues[mid-1]+groupValues[mid])/2:groupValues[mid];const medianX=xScale(median);g.append(\"line\").attr(\"x1\",medianX).attr(\"y1\",yScale(group)).attr(\"x2\",medianX).attr(\"y2\",yScale(group)+bandwidth).attr(\"stroke\",\"#f59e0b\").attr(\"stroke-width\",2).attr(\"stroke-dasharray\",\"4,3\").attr(\"opacity\",.6).attr(\"pointer-events\",\"none\")})}}function renderSingleBeeswarm(g,data,valueField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip){const density=data.length/(dims.innerWidth*dims.innerHeight/1e4);let dotRadius=baseRadius;if(density>5)dotRadius=Math.max(2,baseRadius-2);else if(density>2)dotRadius=Math.max(3,baseRadius-1);const sortedData=[...data].sort((a,b)=>Number(a[valueField])-Number(b[valueField]));const xPositions=sortedData.map(d=>xScale(Number(d[valueField])));const offsets=dodgeBeeswarm(xPositions,dotRadius*2.2,dims.innerHeight/2-dotRadius);const midY=dims.innerHeight/2;const pointPositions=sortedData.map((d,i)=>({d,i,cx:xPositions[i],cy:midY+offsets[i],r:dotRadius}));const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").filter((_,j)=>j===p.i).attr(\"r\",p.r*1.6).attr(\"opacity\",1);const html=`<strong>${encoding.x?.title||valueField}</strong>: ${formatValue(Number(p.d[valueField]))}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity);activeIdx=-1}hideTooltip(tooltip)});const colorField=encoding.color?.field;g.selectAll(\".dot\").data(pointPositions).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",p=>p.cx).attr(\"cy\",p=>p.cy).attr(\"r\",p=>p.r).attr(\"data-r\",p=>p.r).attr(\"fill\",p=>colorField?colorScale(p.d[colorField]):categorical[0]).attr(\"opacity\",opacity).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.8).attr(\"pointer-events\",\"none\")}return __toCommonJS(beeswarm_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
7
|
+
export const boxPlotBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var box_plot_render_exports={};__export(box_plot_render_exports,{renderChart:()=>renderBoxPlot});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function computeBoxStats(values,whiskerType){const sorted=[...values].sort((a,b)=>a-b);const n=sorted.length;const min=sorted[0];const max=sorted[n-1];const median=n%2===1?sorted[Math.floor(n/2)]:(sorted[n/2-1]+sorted[n/2])/2;const lowerHalf=sorted.slice(0,Math.floor(n/2));const upperHalf=sorted.slice(Math.ceil(n/2));const q1=lowerHalf.length%2===1?lowerHalf[Math.floor(lowerHalf.length/2)]:lowerHalf.length>0?(lowerHalf[lowerHalf.length/2-1]+lowerHalf[lowerHalf.length/2])/2:min;const q3=upperHalf.length%2===1?upperHalf[Math.floor(upperHalf.length/2)]:upperHalf.length>0?(upperHalf[upperHalf.length/2-1]+upperHalf[upperHalf.length/2])/2:max;const iqr=q3-q1;const mean=values.reduce((s,v)=>s+v,0)/n;let whiskerLow;let whiskerHigh;let outliers;if(whiskerType===\"minmax\"){whiskerLow=min;whiskerHigh=max;outliers=[]}else{const lowerFence=q1-1.5*iqr;const upperFence=q3+1.5*iqr;whiskerLow=sorted.find(v=>v>=lowerFence)??min;whiskerHigh=[...sorted].reverse().find(v=>v<=upperFence)??max;outliers=sorted.filter(v=>v<lowerFence||v>upperFence)}return{min,q1,median,q3,max,iqr,whiskerLow,whiskerHigh,mean,outliers,values:sorted}}function renderBoxPlot(container,spec){const{config,encoding,data}=spec;const valueField=config.valueField||encoding.y?.field||Object.keys(data[0]).find(k=>typeof data[0][k]===\"number\")||Object.keys(data[0])[1];const categoryField=config.categoryField||encoding.x?.field||Object.keys(data[0])[0];const whiskerType=config.whiskerType||\"iqr\";const showOutliers=config.showOutliers??true;const showMean=config.showMean??false;const horizontal=config.orientation===\"horizontal\";let groups=[...new Set(data.map(d=>d[categoryField]))];const groupStatsMap=new Map;for(const group of groups){const vals=data.filter(d=>d[categoryField]===group).map(d=>Number(d[valueField])).filter(v=>!isNaN(v));if(vals.length>=1){groupStatsMap.set(String(group),computeBoxStats(vals,whiskerType))}}if(config.sortBy===\"value\"){const order=config.sortOrder===\"ascending\"?1:-1;groups.sort((a,b)=>order*((groupStatsMap.get(String(a))?.median??0)-(groupStatsMap.get(String(b))?.median??0)))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;groups.sort((a,b)=>order*String(a).localeCompare(String(b),void 0,{sensitivity:\"base\",numeric:true}))}const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const labels=groups.map(String);let margins;if(horizontal){const maxLabelLen=Math.max(...labels.map(l=>l.length));const leftMargin=Math.min(Math.max(maxLabelLen*7,70),180);margins={left:leftMargin,bottom:40}}else{const containerWidth=container.clientWidth||800;const estimatedBandWidth=(containerWidth-140)/labels.length;const needsRotation=shouldRotateLabels(labels,estimatedBandWidth);margins={bottom:calculateBottomMargin(labels,needsRotation),left:70}}const{svg,g,dims}=createSvg(container,spec,margins);const tooltip=createTooltip(container);if(allValues.every(v=>v===0)){renderEmptyState(g,dims);return}const valuePadding=(d3.max(allValues)-d3.min(allValues))*.08||1;const bandScale=d3.scaleBand().domain(groups).range(horizontal?[0,dims.innerHeight]:[0,dims.innerWidth]).padding(.25);const valueScale=d3.scaleLinear().domain([d3.min(allValues)-valuePadding,d3.max(allValues)+valuePadding]).range(horizontal?[0,dims.innerWidth]:[dims.innerHeight,0]).nice();if(horizontal){const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(bandScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);const xTickCount=getAdaptiveTickCount(dims.innerWidth,60);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(valueScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis)}else{const containerWidth=container.clientWidth||800;const estimatedBandWidth=(containerWidth-140)/labels.length;const needsRotation=shouldRotateLabels(labels,estimatedBandWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(bandScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(valueScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis)}const colorScale=buildColorScale(encoding.color,data);const bandWidth=bandScale.bandwidth();const boxWidth=Math.min(bandWidth*.4,45);const groupDataArr=groups.map(group=>({group,stats:groupStatsMap.get(String(group))}));g.selectAll(\".box-hover-target\").data(groupDataArr).join(\"rect\").attr(\"class\",\"box-hover-target\").attr(\"x\",d=>horizontal?0:bandScale(d.group)).attr(\"y\",d=>horizontal?bandScale(d.group):0).attr(\"width\",horizontal?dims.innerWidth:bandWidth).attr(\"height\",horizontal?bandWidth:dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){const idx=groups.indexOf(d.group);g.selectAll(`.box-group-${idx}`).attr(\"opacity\",1);if(!d.stats)return;const s=d.stats;let html=`<strong>${d.group}</strong><br/>n = ${s.values.length}<br/>Median: ${formatValue(s.median)}<br/>Q1: ${formatValue(s.q1)}<br/>Q3: ${formatValue(s.q3)}<br/>IQR: ${formatValue(s.iqr)}`;if(showMean)html+=`<br/>Mean: ${formatValue(s.mean)}`;if(showOutliers&&s.outliers.length>0){html+=`<br/>Outliers: ${s.outliers.length}`}showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(_event,d){const idx=groups.indexOf(d.group);g.selectAll(`.box-group-${idx}`).attr(\"opacity\",.85);hideTooltip(tooltip)});groups.forEach((group,gi)=>{const stats=groupStatsMap.get(String(group));if(!stats)return;const bandCenter=bandScale(group)+bandWidth/2;const colorValue=encoding.color?.field?data.find(d=>d[categoryField]===group)?.[encoding.color.field]:group;const fillColor=colorScale(colorValue);const groupG=g.append(\"g\").attr(\"class\",`box-group-${gi}`).attr(\"opacity\",.85);if(horizontal){groupG.append(\"line\").attr(\"x1\",valueScale(stats.whiskerLow)).attr(\"x2\",valueScale(stats.whiskerHigh)).attr(\"y1\",bandCenter).attr(\"y2\",bandCenter).attr(\"stroke\",\"#6b7280\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");const capWidth=boxWidth*.5;[stats.whiskerLow,stats.whiskerHigh].forEach(val=>{groupG.append(\"line\").attr(\"x1\",valueScale(val)).attr(\"x2\",valueScale(val)).attr(\"y1\",bandCenter-capWidth/2).attr(\"y2\",bandCenter+capWidth/2).attr(\"stroke\",\"#6b7280\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")});const boxLeft=valueScale(stats.q1);const boxRight=valueScale(stats.q3);groupG.append(\"rect\").attr(\"x\",boxLeft).attr(\"y\",bandCenter-boxWidth/2).attr(\"width\",Math.max(1,boxRight-boxLeft)).attr(\"height\",boxWidth).attr(\"fill\",fillColor).attr(\"stroke\",\"none\").attr(\"rx\",3).attr(\"pointer-events\",\"none\");groupG.append(\"line\").attr(\"x1\",valueScale(stats.median)).attr(\"x2\",valueScale(stats.median)).attr(\"y1\",bandCenter-boxWidth/2).attr(\"y2\",bandCenter+boxWidth/2).attr(\"stroke\",\"#c8cdd5\").attr(\"stroke-width\",2).attr(\"stroke-linecap\",\"round\").attr(\"pointer-events\",\"none\");if(showMean){const mx=valueScale(stats.mean);const size=4;groupG.append(\"path\").attr(\"d\",`M${mx},${bandCenter-size} L${mx+size},${bandCenter} L${mx},${bandCenter+size} L${mx-size},${bandCenter} Z`).attr(\"fill\",\"#c8cdd5\").attr(\"stroke\",fillColor).attr(\"stroke-width\",1).attr(\"pointer-events\",\"none\")}if(showOutliers&&stats.outliers.length>0){groupG.selectAll(\".outlier\").data(stats.outliers).join(\"circle\").attr(\"class\",\"outlier\").attr(\"cx\",d=>valueScale(d)).attr(\"cy\",bandCenter).attr(\"r\",3).attr(\"fill\",\"none\").attr(\"stroke\",fillColor).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")}}else{groupG.append(\"line\").attr(\"x1\",bandCenter).attr(\"x2\",bandCenter).attr(\"y1\",valueScale(stats.whiskerHigh)).attr(\"y2\",valueScale(stats.whiskerLow)).attr(\"stroke\",\"#6b7280\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");const capWidth=boxWidth*.5;[stats.whiskerLow,stats.whiskerHigh].forEach(val=>{groupG.append(\"line\").attr(\"x1\",bandCenter-capWidth/2).attr(\"x2\",bandCenter+capWidth/2).attr(\"y1\",valueScale(val)).attr(\"y2\",valueScale(val)).attr(\"stroke\",\"#6b7280\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")});groupG.append(\"rect\").attr(\"x\",bandCenter-boxWidth/2).attr(\"y\",valueScale(stats.q3)).attr(\"width\",boxWidth).attr(\"height\",Math.max(1,valueScale(stats.q1)-valueScale(stats.q3))).attr(\"fill\",fillColor).attr(\"stroke\",\"none\").attr(\"rx\",3).attr(\"pointer-events\",\"none\");groupG.append(\"line\").attr(\"x1\",bandCenter-boxWidth/2).attr(\"x2\",bandCenter+boxWidth/2).attr(\"y1\",valueScale(stats.median)).attr(\"y2\",valueScale(stats.median)).attr(\"stroke\",\"#c8cdd5\").attr(\"stroke-width\",2).attr(\"stroke-linecap\",\"round\").attr(\"pointer-events\",\"none\");if(showMean){const my=valueScale(stats.mean);const size=4;groupG.append(\"path\").attr(\"d\",`M${bandCenter},${my-size} L${bandCenter+size},${my} L${bandCenter},${my+size} L${bandCenter-size},${my} Z`).attr(\"fill\",\"#c8cdd5\").attr(\"stroke\",fillColor).attr(\"stroke-width\",1).attr(\"pointer-events\",\"none\")}if(showOutliers&&stats.outliers.length>0){groupG.selectAll(\".outlier\").data(stats.outliers).join(\"circle\").attr(\"class\",\"outlier\").attr(\"cx\",bandCenter).attr(\"cy\",d=>valueScale(d)).attr(\"r\",3).attr(\"fill\",\"none\").attr(\"stroke\",fillColor).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")}}});addSortControls(svg,container,spec,dims,renderBoxPlot)}return __toCommonJS(box_plot_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
8
|
+
export const bulletBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var bullet_render_exports={};__export(bullet_render_exports,{renderChart:()=>renderBullet});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}var RANGE_COLORS=[\"#1a1f2e\",\"#252b3d\",\"#313850\"];function renderBullet(container,spec){const{config,encoding,data}=spec;const metricField=config.metricField;const actualField=config.actualField;const targetField=config.targetField;const rangeFields=config.rangeFields;if(!data||data.length===0)return;let sortedData=[...data];if(config.sortBy===\"value\"){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>order*(Number(a[actualField])-Number(b[actualField])))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>order*String(a[metricField]).localeCompare(String(b[metricField]),void 0,{sensitivity:\"base\",numeric:true}))}const labels=sortedData.map(d=>String(d[metricField]??\"\"));const leftMargin=calculateLeftMargin(labels);const containerHeight=container.clientHeight||500;const topMargin=40;const bottomMargin=40;const availableHeight=containerHeight-topMargin-bottomMargin;const maxPerRow=Math.floor(availableHeight/sortedData.length);const bulletHeight=Math.max(16,Math.min(48,maxPerRow-8));const bulletGap=Math.max(4,Math.min(16,maxPerRow-bulletHeight));const totalBulletHeight=bulletHeight+bulletGap;const usedHeight=sortedData.length*totalBulletHeight;const{svg,g,dims}=createSvg(container,spec,{left:leftMargin,right:40,bottom:bottomMargin,top:topMargin});const tooltip=createTooltip(container);const colorEncoding=encoding.color||{field:metricField,type:\"nominal\"};const colorScale=buildColorScale(colorEncoding,data);const metrics=sortedData.map((d,i)=>{const actual=Number(d[actualField])||0;const target=targetField&&d[targetField]!=null?Number(d[targetField]):null;const label=String(d[metricField]??`Metric ${i+1}`);let ranges;if(rangeFields&&rangeFields.length>0){ranges=rangeFields.map(f=>Number(d[f])).filter(v=>!isNaN(v)).sort((a,b)=>a-b)}else{const maxRef=Math.max(Math.abs(actual),Math.abs(target??0));const ceiling=maxRef*1.2||100;const sign=actual<0&&(target===null||target<=0)?-1:1;ranges=[sign*ceiling*.33,sign*ceiling*.66,sign*ceiling]}const allVals=[...ranges,actual,...target!==null?[target]:[]];const maxRange=Math.max(...allVals);const minRange=Math.min(0,...allVals);return{label,actual,target,ranges,maxRange,minRange,index:i,datum:d}});const isSmall=bulletHeight<28;metrics.forEach(metric=>{const yOffset=metric.index*totalBulletHeight;const bulletG=g.append(\"g\").attr(\"transform\",`translate(0,${yOffset})`);const domainMin=metric.minRange<0?metric.minRange*1.05:0;const domainMax=metric.maxRange>0?metric.maxRange*1.05:1;const xScale=d3.scaleLinear().domain([domainMin,domainMax]).range([0,dims.innerWidth]).nice();const ticks=xScale.ticks(getAdaptiveTickCount(dims.innerWidth,80));ticks.forEach(tick=>{const tx=xScale(tick);bulletG.append(\"line\").attr(\"x1\",tx).attr(\"y1\",0).attr(\"x2\",tx).attr(\"y2\",bulletHeight).attr(\"stroke\",\"#ffffff\").attr(\"stroke-opacity\",.06).attr(\"pointer-events\",\"none\");bulletG.append(\"text\").attr(\"x\",tx).attr(\"y\",bulletHeight+10).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",isSmall?\"7px\":\"8px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(tick))});const barCenter=bulletHeight/2;bulletG.append(\"rect\").attr(\"class\",\"hover-target\").attr(\"x\",0).attr(\"y\",0).attr(\"width\",dims.innerWidth).attr(\"height\",bulletHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){bulletG.select(\".actual-bar\").attr(\"opacity\",.85);let html=`<strong>${metric.label}</strong>`;html+=`<br/>Actual: ${formatValue(metric.actual)}`;if(metric.target!==null){html+=`<br/>Target: ${formatValue(metric.target)}`;const pct=(metric.actual/metric.target*100).toFixed(1);html+=`<br/>Achievement: ${pct}%`}if(config.rangeLabels&&metric.ranges.length>0){const rangeLabels=config.rangeLabels;metric.ranges.forEach((r,ri)=>{if(rangeLabels[ri]){html+=`<br/><span style=\"color:${TEXT_MUTED}\">${rangeLabels[ri]}: ${formatValue(r)}</span>`}})}showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){bulletG.select(\".actual-bar\").attr(\"opacity\",1);hideTooltip(tooltip)});const zeroX=xScale(0);const sortedRanges=[...metric.ranges].sort((a,b)=>b-a);sortedRanges.forEach((rangeVal,ri)=>{const colorIndex=Math.min(ri,RANGE_COLORS.length-1);const rx=xScale(rangeVal);const bandX=Math.min(zeroX,rx);const bandW=Math.abs(rx-zeroX);bulletG.append(\"rect\").attr(\"class\",\"range-band\").attr(\"x\",bandX).attr(\"y\",0).attr(\"width\",Math.max(0,bandW)).attr(\"height\",bulletHeight).attr(\"fill\",RANGE_COLORS[RANGE_COLORS.length-1-colorIndex]).attr(\"rx\",2).attr(\"pointer-events\",\"none\")});const actualBarHeight=Math.max(6,Math.min(14,bulletHeight*.3));const accentColor=colorScale(metric.datum[metricField]);const actualX=xScale(metric.actual);const barX=Math.min(zeroX,actualX);const barW=Math.max(2,Math.abs(actualX-zeroX));bulletG.append(\"rect\").attr(\"class\",\"actual-bar\").attr(\"x\",barX).attr(\"y\",barCenter-actualBarHeight/2).attr(\"width\",barW).attr(\"height\",actualBarHeight).attr(\"fill\",accentColor).attr(\"rx\",2).attr(\"pointer-events\",\"none\");if(metric.target!==null){const markerHeight=Math.max(10,Math.min(26,bulletHeight*.55));bulletG.append(\"line\").attr(\"class\",\"target-marker\").attr(\"x1\",xScale(metric.target)).attr(\"y1\",barCenter-markerHeight/2).attr(\"x2\",xScale(metric.target)).attr(\"y2\",barCenter+markerHeight/2).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",2.5).attr(\"pointer-events\",\"none\")}bulletG.append(\"text\").attr(\"class\",\"metric-label\").attr(\"x\",-10).attr(\"y\",barCenter+1).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",isSmall?\"10px\":\"12px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(truncateLabel(metric.label,22));if(!isSmall&&config.showLabels!==false){const labelX=metric.actual>=0?xScale(metric.actual)+8:xScale(metric.actual)-8;const labelAnchor=metric.actual>=0?\"start\":\"end\";if(metric.actual>=0?labelX<dims.innerWidth-40:labelX>40){bulletG.append(\"text\").attr(\"class\",\"value-label\").attr(\"x\",labelX).attr(\"y\",barCenter+1).attr(\"text-anchor\",labelAnchor).attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(metric.actual))}}});addSortControls(svg,container,spec,dims,renderBullet)}return __toCommonJS(bullet_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
9
|
+
export const bumpChartBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var bump_chart_render_exports={};__export(bump_chart_render_exports,{renderChart:()=>renderBumpChart});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderBumpChart(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field||\"entity\";const timeField=config.timeField||encoding.x?.field||\"period\";const valueField=config.valueField||encoding.y?.field||\"value\";const showLabels=config.showLabels!==false;const strokeWidth=config.strokeWidth??2.5;const dotRadius=config.dotRadius??5;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{left:40,right:100});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const tooltip=createTooltip(container);const periodSet=new Set;data.forEach(d=>periodSet.add(String(d[timeField])));const periods=[...periodSet];const entitySet=new Set;data.forEach(d=>entitySet.add(String(d[categoryField])));const entities=[...entitySet];const lookup={};entities.forEach(e=>{lookup[e]={}});data.forEach(d=>{const e=String(d[categoryField]);const p=String(d[timeField]);lookup[e][p]=Number(d[valueField])});const ranks={};entities.forEach(e=>{ranks[e]={}});periods.forEach(period=>{const entitiesWithValues=entities.filter(e=>lookup[e][period]!=null&&!isNaN(lookup[e][period])).map(e=>({entity:e,value:lookup[e][period]}));entitiesWithValues.sort((a,b)=>b.value-a.value);entitiesWithValues.forEach((item,idx)=>{ranks[item.entity][period]=idx+1})});const maxRank=entities.length;const xScale=d3.scalePoint().domain(periods).range([0,dims.innerWidth]).padding(.5);const yScale=d3.scaleLinear().domain([1,maxRank]).range([20,dims.innerHeight-20]);const colorScale=buildColorScale(encoding.color,data);for(let rank=1;rank<=maxRank;rank++){g.append(\"line\").attr(\"x1\",0).attr(\"y1\",yScale(rank)).attr(\"x2\",dims.innerWidth).attr(\"y2\",yScale(rank)).attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"3,3\");g.append(\"text\").attr(\"x\",-8).attr(\"y\",yScale(rank)).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(`#${rank}`)}periods.forEach(period=>{g.append(\"text\").attr(\"x\",xScale(period)).attr(\"y\",dims.innerHeight+20).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(String(period))});const isSinglePeriod=periods.length<=1;if(!isSinglePeriod){const line=d3.line().x(d=>xScale(d.period)).y(d=>yScale(d.rank)).curve(d3.curveBumpX);entities.forEach(entity=>{const points=periods.filter(p=>ranks[entity][p]!=null).map(p=>({period:p,rank:ranks[entity][p],value:lookup[entity][p]}));if(points.length<2)return;const color=colorScale(entity);g.append(\"path\").datum(points).attr(\"d\",line).attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"opacity\",.8);points.forEach(pt=>{g.append(\"circle\").attr(\"cx\",xScale(pt.period)).attr(\"cy\",yScale(pt.rank)).attr(\"r\",dotRadius).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",2).attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){d3.select(this).attr(\"r\",dotRadius+2);showTooltip(tooltip,`<strong>${entity}</strong><br/>Period: ${pt.period}<br/>Rank: #${pt.rank}<br/>Value: ${formatValue(pt.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"r\",dotRadius);hideTooltip(tooltip)})});if(showLabels){const lastPt=points[points.length-1];g.append(\"text\").attr(\"x\",xScale(lastPt.period)+dotRadius+6).attr(\"y\",yScale(lastPt.rank)).attr(\"dominant-baseline\",\"middle\").attr(\"fill\",color).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(truncateLabel(entity,14))}})}else{const singlePeriod=periods[0];const dotX=dims.innerWidth/2;entities.forEach(entity=>{const rank=ranks[entity][singlePeriod];if(rank==null)return;const value=lookup[entity][singlePeriod];const color=colorScale(entity);g.append(\"circle\").attr(\"cx\",dotX).attr(\"cy\",yScale(rank)).attr(\"r\",6).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",2).attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){d3.select(this).attr(\"r\",8);showTooltip(tooltip,`<strong>${entity}</strong><br/>Period: ${singlePeriod}<br/>Rank: #${rank}<br/>Value: ${formatValue(value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"r\",6);hideTooltip(tooltip)});g.append(\"text\").attr(\"x\",dotX+12).attr(\"y\",yScale(rank)).attr(\"dominant-baseline\",\"middle\").attr(\"fill\",color).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(`${entity.length>14?entity.slice(0,13)+\"\\u2026\":entity} (${formatValue(value)})`)})}if(!showLabels){const legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}}return __toCommonJS(bump_chart_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
10
|
+
export const calendarHeatmapBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var calendar_heatmap_render_exports={};__export(calendar_heatmap_render_exports,{renderChart:()=>renderCalendarHeatmap});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}var DAY_LABELS=[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"];var MONTH_NAMES=[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];var EMPTY_COLOR=\"#1b2028\";var EMPTY_STROKE=\"#252d3a\";function renderCalendarHeatmap(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.color?.field||encoding.y?.field;const showMonthLabels=config.showMonthLabels??true;const showDayLabels=config.showDayLabels??true;const dateValueMap=new Map;let minDate=null;let maxDate=null;for(const row of data){const dateStr=String(row[timeField]);const d=parseDate(dateStr);if(!d)continue;const key=formatDateKey(d);const val=Number(row[valueField])||0;dateValueMap.set(key,(dateValueMap.get(key)||0)+val);if(!minDate||d<minDate)minDate=new Date(d);if(!maxDate||d>maxDate)maxDate=new Date(d)}if(!minDate||!maxDate){container.innerHTML='<p style=\"color:#ef4444;padding:20px;\">No valid dates found</p>';return}if(isAllZeros(data,valueField)){container.innerHTML=`<div style=\"display:flex;align-items:center;justify-content:center;height:100%;color:${TEXT_MUTED};font-size:14px;font-family:Inter,system-ui,sans-serif\">All values are zero</div>`;return}const startSunday=new Date(minDate);startSunday.setDate(startSunday.getDate()-startSunday.getDay());const endSaturday=new Date(maxDate);endSaturday.setDate(endSaturday.getDate()+(6-endSaturday.getDay()));const totalDays=Math.round((endSaturday.getTime()-startSunday.getTime())/864e5)+1;const totalWeeks=Math.ceil(totalDays/7);container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";container.style.position=\"relative\";const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const titleHeight=spec.title?40:0;const legendHeight=36;const bottomPad=8;const maxCellSize=40;const preferredCellSize=config.cellSize??14;const cellGapDefault=config.cellGap??2;const dayLabelWidth=showDayLabels?32:0;const monthLabelHeight=showMonthLabels?20:0;const hAvailW=containerWidth-dayLabelWidth-24;const hAvailH=containerHeight-titleHeight-monthLabelHeight-legendHeight-bottomPad-16;const hCellW=Math.max(2,Math.floor(hAvailW/totalWeeks)-cellGapDefault);const hCellH=Math.max(2,Math.floor(hAvailH/7)-cellGapDefault);const hCellLimit=totalWeeks<=12?maxCellSize:preferredCellSize;const hCell=Math.min(hCellLimit,hCellW,hCellH);const vAvailW=containerWidth-24;const vAvailH=containerHeight-titleHeight-legendHeight-bottomPad-16;const vCellW=Math.max(2,Math.floor(vAvailW/7)-cellGapDefault);const vCellH=Math.max(2,Math.floor(vAvailH/totalWeeks)-cellGapDefault);const vCellLimit=totalWeeks<=12?maxCellSize:preferredCellSize;const vCell=Math.min(vCellLimit,vCellW,vCellH);const vertical=vCell>hCell&&hCell<preferredCellSize;const cellSize=Math.max(2,vertical?vCell:hCell);const cellGap=cellSize<=4?1:cellGapDefault;const cellStep=cellSize+cellGap;const gridCols=vertical?7:totalWeeks;const gridRows=vertical?totalWeeks:7;const gridWidth=gridCols*cellStep-cellGap;const gridHeight=gridRows*cellStep-cellGap;const labelSpace=vertical?0:dayLabelWidth;const totalGridArea=labelSpace+gridWidth;const gridOffsetX=Math.max(labelSpace,(containerWidth-totalGridArea)/2+labelSpace);const topLabelSpace=vertical?showDayLabels&&cellSize>=6?18:0:showMonthLabels?18:0;const svgWidth=containerWidth;const svgHeight=containerHeight-legendHeight-bottomPad;const contentHeight=titleHeight+topLabelSpace+gridHeight;const gridOffsetY=Math.max(titleHeight+topLabelSpace+4,(svgHeight-contentHeight)/2+titleHeight+topLabelSpace);const svg=d3.select(container).append(\"svg\").attr(\"width\",svgWidth).attr(\"height\",svgHeight);if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",svgWidth/2).attr(\"y\",26).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,svgWidth-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${gridOffsetX},${gridOffsetY})`);const colorEncoding=encoding.color;let colorScale;const allValues=Array.from(dateValueMap.values());const nonZeroValues=allValues.filter(v=>v!==0);const dataMin=nonZeroValues.length>0?Math.min(...nonZeroValues):0;const dataMax=nonZeroValues.length>0?Math.max(...nonZeroValues):1;const hasMixedSign=dataMin<0&&dataMax>0;const allNegative=dataMax<=0&&dataMin<0;const paletteMap={blue:sequential.blue,green:sequential.green,purple:sequential.purple,warm:sequential.warm};const paletteName=colorEncoding?.palette||\"blue\";if(hasMixedSign){const maxAbs=Math.max(Math.abs(dataMin),Math.abs(dataMax));const divPalette=diverging.blueRed;colorScale=d3.scaleLinear().domain([-maxAbs,-maxAbs*.5,0,maxAbs*.5,maxAbs]).range([divPalette[0],divPalette[2],divPalette[4],divPalette[6],divPalette[8]]).clamp(true)}else if(allNegative){const absMin=Math.abs(dataMax);const absMax=Math.abs(dataMin);const warmPalette=sequential.warm;colorScale=d3.scaleLinear().domain([dataMin,dataMin*.5,dataMax]).range([warmPalette[1],warmPalette[3],warmPalette[7]]).clamp(true)}else{const maxValue=dataMax||1;const rawPalette=paletteMap[paletteName];if(rawPalette){colorScale=d3.scaleLinear().domain([0,maxValue*.25,maxValue*.5,maxValue]).range([rawPalette[7],rawPalette[5],rawPalette[3],rawPalette[1]]).clamp(true)}else{colorScale=d3.scaleLinear().domain([0,maxValue*.25,maxValue*.5,maxValue]).range([\"#143893\",\"#2f63d9\",\"#6e9cf4\",\"#c5d9fc\"]).clamp(true)}}const tooltip=createTooltip(container);const dayData=[];const cursor=new Date(startSunday);for(let i=0;i<totalDays;i++){const key=formatDateKey(cursor);const weekCol=Math.floor(i/7);const dayRow=cursor.getDay();const value=dateValueMap.get(key)||0;dayData.push({date:new Date(cursor),key,weekCol,dayRow,value});cursor.setDate(cursor.getDate()+1)}const monthBoundaries=[];for(const dd of dayData){if(dd.date.getDate()===1&&dd.date>=minDate&&dd.date<=maxDate){monthBoundaries.push({weekCol:dd.weekCol,dayRow:dd.dayRow})}}if(showMonthLabels&&cellSize>=4&&!vertical){for(const mb of monthBoundaries){const pathParts=[];const x=mb.weekCol*cellStep-cellGap/2;const yTop=mb.dayRow*cellStep-cellGap/2;const yBottom=7*cellStep-cellGap/2;if(mb.dayRow>0){pathParts.push(`M ${x} ${yTop}`);pathParts.push(`L ${x} ${-cellGap/2}`)}g.append(\"line\").attr(\"x1\",x).attr(\"y1\",mb.dayRow>0?yTop:-cellGap/2).attr(\"x2\",x).attr(\"y2\",yBottom).attr(\"stroke\",\"#2a3344\").attr(\"stroke-width\",1).attr(\"shape-rendering\",\"crispEdges\");if(mb.dayRow>0){g.append(\"line\").attr(\"x1\",x).attr(\"y1\",yTop).attr(\"x2\",x+cellStep).attr(\"y2\",yTop).attr(\"stroke\",\"#2a3344\").attr(\"stroke-width\",1).attr(\"shape-rendering\",\"crispEdges\")}}}const cells=g.selectAll(\".cal-cell\").data(dayData).join(\"rect\").attr(\"class\",\"cal-cell\").attr(\"x\",d=>(vertical?d.dayRow:d.weekCol)*cellStep).attr(\"y\",d=>(vertical?d.weekCol:d.dayRow)*cellStep).attr(\"width\",cellSize).attr(\"height\",cellSize).attr(\"rx\",cellSize>=6?2:1).attr(\"fill\",d=>{if(d.date<minDate||d.date>maxDate)return\"transparent\";return d.value!==0?colorScale(d.value):EMPTY_COLOR}).attr(\"stroke\",d=>{if(d.date<minDate||d.date>maxDate)return\"transparent\";return d.value!==0?\"none\":EMPTY_STROKE}).attr(\"stroke-width\",.5).style(\"cursor\",d=>d.date>=minDate&&d.date<=maxDate?\"pointer\":\"default\");cells.on(\"mouseover\",function(event,d){if(d.date<minDate||d.date>maxDate)return;d3.select(this).attr(\"stroke\",\"#58a6ff\").attr(\"stroke-width\",1.5).raise();const dateStr=d.date.toLocaleDateString(\"en-US\",{weekday:\"short\",year:\"numeric\",month:\"short\",day:\"numeric\"});showTooltip(tooltip,`<strong>${dateStr}</strong><br/>${valueField}: ${d.value!==0?formatValue(d.value):\"No data\"}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(_event,d){if(d.date<minDate||d.date>maxDate)return;d3.select(this).attr(\"stroke\",d.value!==0?\"none\":EMPTY_STROKE).attr(\"stroke-width\",.5);hideTooltip(tooltip)});if(vertical){if(showDayLabels&&cellSize>=6){drawDayLabelsTop(g,cellStep,cellSize)}if(showMonthLabels&&cellSize>=4){drawMonthLabelsLeft(g,startSunday,totalWeeks,cellStep,minDate,maxDate)}}else{if(showMonthLabels){drawMonthLabelsTop(g,startSunday,totalWeeks,cellStep,cellSize,minDate,maxDate)}if(showDayLabels&&cellSize>=6){drawDayLabelsLeft(g,cellStep,cellSize)}}buildHtmlLegend(container,colorScale,dataMin,dataMax,hasMixedSign,allNegative,cellSize)}function parseDate(v){if(v instanceof Date)return isNaN(v.getTime())?null:v;const d=new Date(v);return isNaN(d.getTime())?null:d}function formatDateKey(d){const y=d.getFullYear();const m=String(d.getMonth()+1).padStart(2,\"0\");const day=String(d.getDate()).padStart(2,\"0\");return`${y}-${m}-${day}`}function drawMonthLabelsTop(g,startSunday,totalWeeks,cellStep,cellSize,minDate,maxDate){const months=getMonthBreaks(startSunday,totalWeeks,minDate,maxDate);const minSpacing=30;const filtered=[];let lastX=-Infinity;for(const m of months){const x=m.weekCol*cellStep;if(x-lastX>=minSpacing){filtered.push(m);lastX=x}}g.selectAll(\".month-label\").data(filtered).join(\"text\").attr(\"class\",\"month-label\").attr(\"x\",d=>d.weekCol*cellStep).attr(\"y\",-8).attr(\"fill\",TEXT_MUTED).attr(\"font-size\",cellSize>=8?\"10px\":\"8px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>d.name)}function drawDayLabelsLeft(g,cellStep,cellSize){const labelDays=[1,3,5];g.selectAll(\".day-label\").data(labelDays).join(\"text\").attr(\"class\",\"day-label\").attr(\"x\",-6).attr(\"y\",d=>d*cellStep+cellSize/2).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",cellSize>=10?\"9px\":\"7px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>cellSize>=10?DAY_LABELS[d]:DAY_LABELS[d].charAt(0))}function drawDayLabelsTop(g,cellStep,cellSize){g.selectAll(\".day-label\").data(DAY_LABELS.map((name,i)=>({name,i}))).join(\"text\").attr(\"class\",\"day-label\").attr(\"x\",d=>d.i*cellStep+cellSize/2).attr(\"y\",-5).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",cellSize>=10?\"9px\":\"7px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>cellSize>=10?d.name:d.name.charAt(0))}function drawMonthLabelsLeft(g,startSunday,totalWeeks,cellStep,minDate,maxDate){const months=getMonthBreaks(startSunday,totalWeeks,minDate,maxDate);g.selectAll(\".month-label\").data(months).join(\"text\").attr(\"class\",\"month-label\").attr(\"x\",-8).attr(\"y\",d=>d.weekCol*cellStep+cellStep/2).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>d.name)}function getMonthBreaks(startSunday,totalWeeks,minDate,maxDate){const months=[];let lastMonth=-1;const cursor=new Date(startSunday);for(let week=0;week<totalWeeks;week++){const month=cursor.getMonth();if(month!==lastMonth){const monthEnd=new Date(cursor.getFullYear(),month+1,0);const inRange=!minDate||!maxDate||monthEnd>=minDate&&cursor<=maxDate;if(inRange){months.push({name:MONTH_NAMES[month],weekCol:week})}lastMonth=month}cursor.setDate(cursor.getDate()+7)}return months}function buildHtmlLegend(container,colorScale,dataMin,dataMax,hasMixedSign,allNegative,cellSize){const legendDiv=document.createElement(\"div\");legendDiv.style.cssText=`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n padding: 10px 16px;\n font-family: Inter, system-ui, sans-serif;\n font-size: 11px;\n color: ${TEXT_MUTED};\n flex-shrink: 0;\n `;const steps=5;const swatchSize=Math.max(10,Math.min(cellSize,14));if(hasMixedSign){const maxAbs=Math.max(Math.abs(dataMin),Math.abs(dataMax));const startLabel=document.createElement(\"span\");startLabel.textContent=formatValue(-maxAbs);startLabel.style.marginRight=\"2px\";legendDiv.appendChild(startLabel);for(let i=0;i<steps;i++){const val=-maxAbs+2*maxAbs/(steps-1)*i;const swatch=document.createElement(\"span\");swatch.style.cssText=`\n display: inline-block;\n width: ${swatchSize}px;\n height: ${swatchSize}px;\n border-radius: 2px;\n background: ${colorScale(val)};\n `;legendDiv.appendChild(swatch)}const endLabel=document.createElement(\"span\");endLabel.textContent=formatValue(maxAbs);endLabel.style.marginLeft=\"2px\";legendDiv.appendChild(endLabel)}else{const rangeStart=allNegative?dataMin:0;const rangeEnd=allNegative?dataMax:dataMax||1;const startLabel=document.createElement(\"span\");startLabel.textContent=allNegative?formatValue(rangeStart):\"Less\";startLabel.style.marginRight=\"2px\";legendDiv.appendChild(startLabel);for(let i=0;i<steps;i++){const swatch=document.createElement(\"span\");const val=rangeStart+(rangeEnd-rangeStart)/(steps-1)*i;const color=i===0&&!allNegative?EMPTY_COLOR:colorScale(val);swatch.style.cssText=`\n display: inline-block;\n width: ${swatchSize}px;\n height: ${swatchSize}px;\n border-radius: 2px;\n background: ${color};\n border: 1px solid ${i===0&&!allNegative?EMPTY_STROKE:\"transparent\"};\n `;legendDiv.appendChild(swatch)}const endLabel=document.createElement(\"span\");endLabel.textContent=allNegative?formatValue(rangeEnd):\"More\";endLabel.style.marginLeft=\"2px\";legendDiv.appendChild(endLabel)}container.appendChild(legendDiv)}return __toCommonJS(calendar_heatmap_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
11
|
+
export const chordBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var chord_render_exports={};__export(chord_render_exports,{renderChart:()=>renderChord});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderChord(container,spec){const{config,encoding,data}=spec;const sourceField=config.sourceField||encoding.source?.field;const targetField=config.targetField||encoding.target?.field;const valueField=config.valueField||encoding.size?.field;const padAngle=config.padAngle??.02;const ribbonOpacity=config.ribbonOpacity??.6;const showValues=config.showValues===true;const entitySet=new Set;for(const row of data){entitySet.add(String(row[sourceField]));entitySet.add(String(row[targetField]))}const entities=[...entitySet];const n=entities.length;if(n<2){container.innerHTML='<p style=\"color:#ef4444;padding:20px;\">Chord diagram requires at least 2 entities</p>';return}const entityIndex=new Map;entities.forEach((name,i)=>entityIndex.set(name,i));const matrix=Array.from({length:n},()=>Array(n).fill(0));for(const row of data){const si=entityIndex.get(String(row[sourceField]));const ti=entityIndex.get(String(row[targetField]));const raw=Number(row[valueField]);const val=isNaN(raw)?1:raw;if(si!==void 0&&ti!==void 0){matrix[si][ti]+=val}}let matrixMax=0;for(let i=0;i<n;i++){for(let j=0;j<n;j++){if(matrix[i][j]>matrixMax)matrixMax=matrix[i][j]}}const minVisibleChord=matrixMax*.02;if(matrixMax>0){for(let i=0;i<n;i++){for(let j=0;j<n;j++){if(matrix[i][j]>0&&matrix[i][j]<minVisibleChord){matrix[i][j]=minVisibleChord}}}}const colorField=encoding.color?.field||sourceField;const colorData=entities.map(name=>({[colorField]:name}));const colorScale=buildColorScale({...encoding.color||{},field:colorField,type:encoding.color?.type||\"nominal\"},colorData);const containerWidth=container.clientWidth||600;const containerHeight=container.clientHeight||600;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);const showLegend=containerHeight>250&&containerWidth>300;if(showLegend){container.appendChild(createLegend(colorScale))}const width=chartWrapper.clientWidth||containerWidth;const height=chartWrapper.clientHeight||containerHeight-(showLegend?40:0);const autoShowLabels=config.showLabels!==false&&Math.min(width,height)>250;const labelMargin=autoShowLabels?Math.min(80,Math.max(40,10+n*5)):20;const radius=Math.min(width,height)/2-labelMargin;const arcWidth=Math.max(12,Math.min(24,radius*.12));const innerRadius=radius-arcWidth;const tooltip=createTooltip(container);const svg=d3.select(chartWrapper).append(\"svg\").attr(\"width\",width).attr(\"height\",height);if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const titleOffset=spec.title?20:0;const g=svg.append(\"g\").attr(\"transform\",`translate(${width/2},${height/2+titleOffset})`);const matrixSum=matrix.reduce((s,row)=>s+row.reduce((rs,v)=>rs+v,0),0);if(matrixSum===0){g.append(\"text\").attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"All values are zero\");return}const chordLayout=d3.chord().padAngle(padAngle).sortSubgroups(d3.descending);const chords=chordLayout(matrix);const ribbon=d3.ribbon().radius(innerRadius);const ribbons=g.selectAll(\".chord-ribbon\").data(chords).join(\"path\").attr(\"class\",\"chord-ribbon\").attr(\"d\",ribbon).attr(\"fill\",d=>colorScale(entities[d.source.index])).attr(\"opacity\",ribbonOpacity).attr(\"stroke\",\"none\").on(\"mouseover\",function(event,d){ribbons.attr(\"opacity\",rd=>rd===d?Math.min(ribbonOpacity+.25,.9):ribbonOpacity*.3);const sourceName=entities[d.source.index];const targetName=entities[d.target.index];const val=d.source.value;let html=`<strong>${sourceName} \\u2192 ${targetName}</strong><br/>Value: ${formatValue(val)}`;if(d.source.index!==d.target.index){const reverseVal=matrix[d.target.index][d.source.index];if(reverseVal>0){html+=`<br/>${targetName} \\u2192 ${sourceName}: ${formatValue(reverseVal)}`}}showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){ribbons.attr(\"opacity\",ribbonOpacity);hideTooltip(tooltip)});const arc=d3.arc().innerRadius(innerRadius).outerRadius(radius);const arcGroups=g.selectAll(\".chord-group\").data(chords.groups).join(\"g\").attr(\"class\",\"chord-group\");arcGroups.append(\"path\").attr(\"d\",arc).attr(\"fill\",d=>colorScale(entities[d.index])).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).on(\"mouseover\",function(event,d){d3.select(this).attr(\"opacity\",.85);ribbons.attr(\"opacity\",rd=>rd.source.index===d.index||rd.target.index===d.index?Math.min(ribbonOpacity+.25,.9):ribbonOpacity*.2);const total=d.value;showTooltip(tooltip,`<strong>${entities[d.index]}</strong><br/>Total flow: ${formatValue(total)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"opacity\",1);ribbons.attr(\"opacity\",ribbonOpacity);hideTooltip(tooltip)});if(autoShowLabels){const labelFontSize=n>10?9:n>6?10:11;const maxLabelLen=n>10?12:n>6?14:18;arcGroups.append(\"text\").each(function(d){d._midAngle=(d.startAngle+d.endAngle)/2}).attr(\"transform\",function(d){const angle=d._midAngle;const labelRadius=radius+8;const x=Math.sin(angle)*labelRadius;const y=-Math.cos(angle)*labelRadius;return`translate(${x},${y})`}).attr(\"text-anchor\",function(d){const s=Math.sin(d._midAngle);if(s>.3)return\"start\";if(s<-.3)return\"end\";return\"middle\"}).attr(\"dy\",function(d){const c=Math.cos(d._midAngle);if(c>.5)return\"-0.1em\";if(c<-.5)return\"0.9em\";return\"0.35em\"}).attr(\"fill\",TEXT_COLOR).attr(\"font-size\",`${labelFontSize}px`).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>{if(d.endAngle-d.startAngle<.1)return\"\";const name=entities[d.index];const label=name.length>maxLabelLen?name.slice(0,maxLabelLen-1)+\"\\u2026\":name;if(showValues)return`${label} (${formatValue(d.value)})`;return label})}}return __toCommonJS(chord_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
12
|
+
export const choroplethBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var choropleth_render_exports={};__export(choropleth_render_exports,{renderChart:()=>renderChoropleth});var src_exports={};__export(src_exports,{bbox:()=>bbox_default,feature:()=>feature_default,merge:()=>merge_default,mergeArcs:()=>mergeArcs,mesh:()=>mesh_default,meshArcs:()=>meshArcs,neighbors:()=>neighbors_default,quantize:()=>quantize_default,transform:()=>transform_default,untransform:()=>untransform_default});function identity_default(x){return x}function transform_default(transform){if(transform==null)return identity_default;var x0,y0,kx=transform.scale[0],ky=transform.scale[1],dx=transform.translate[0],dy=transform.translate[1];return function(input,i){if(!i)x0=y0=0;var j=2,n=input.length,output=new Array(n);output[0]=(x0+=input[0])*kx+dx;output[1]=(y0+=input[1])*ky+dy;while(j<n)output[j]=input[j],++j;return output}}function bbox_default(topology){var t=transform_default(topology.transform),key,x0=Infinity,y0=x0,x1=-x0,y1=-x0;function bboxPoint(p){p=t(p);if(p[0]<x0)x0=p[0];if(p[0]>x1)x1=p[0];if(p[1]<y0)y0=p[1];if(p[1]>y1)y1=p[1]}function bboxGeometry(o){switch(o.type){case\"GeometryCollection\":o.geometries.forEach(bboxGeometry);break;case\"Point\":bboxPoint(o.coordinates);break;case\"MultiPoint\":o.coordinates.forEach(bboxPoint);break}}topology.arcs.forEach(function(arc){var i=-1,n=arc.length,p;while(++i<n){p=t(arc[i],i);if(p[0]<x0)x0=p[0];if(p[0]>x1)x1=p[0];if(p[1]<y0)y0=p[1];if(p[1]>y1)y1=p[1]}});for(key in topology.objects){bboxGeometry(topology.objects[key])}return[x0,y0,x1,y1]}function reverse_default(array,n){var t,j=array.length,i=j-n;while(i<--j)t=array[i],array[i++]=array[j],array[j]=t}function feature_default(topology,o){if(typeof o===\"string\")o=topology.objects[o];return o.type===\"GeometryCollection\"?{type:\"FeatureCollection\",features:o.geometries.map(function(o2){return feature(topology,o2)})}:feature(topology,o)}function feature(topology,o){var id=o.id,bbox=o.bbox,properties=o.properties==null?{}:o.properties,geometry=object(topology,o);return id==null&&bbox==null?{type:\"Feature\",properties,geometry}:bbox==null?{type:\"Feature\",id,properties,geometry}:{type:\"Feature\",id,bbox,properties,geometry}}function object(topology,o){var transformPoint=transform_default(topology.transform),arcs=topology.arcs;function arc(i,points){if(points.length)points.pop();for(var a=arcs[i<0?~i:i],k=0,n=a.length;k<n;++k){points.push(transformPoint(a[k],k))}if(i<0)reverse_default(points,n)}function point(p){return transformPoint(p)}function line(arcs2){var points=[];for(var i=0,n=arcs2.length;i<n;++i)arc(arcs2[i],points);if(points.length<2)points.push(points[0]);return points}function ring(arcs2){var points=line(arcs2);while(points.length<4)points.push(points[0]);return points}function polygon(arcs2){return arcs2.map(ring)}function geometry(o2){var type=o2.type,coordinates;switch(type){case\"GeometryCollection\":return{type,geometries:o2.geometries.map(geometry)};case\"Point\":coordinates=point(o2.coordinates);break;case\"MultiPoint\":coordinates=o2.coordinates.map(point);break;case\"LineString\":coordinates=line(o2.arcs);break;case\"MultiLineString\":coordinates=o2.arcs.map(line);break;case\"Polygon\":coordinates=polygon(o2.arcs);break;case\"MultiPolygon\":coordinates=o2.arcs.map(polygon);break;default:return null}return{type,coordinates}}return geometry(o)}function stitch_default(topology,arcs){var stitchedArcs={},fragmentByStart={},fragmentByEnd={},fragments=[],emptyIndex=-1;arcs.forEach(function(i,j){var arc=topology.arcs[i<0?~i:i],t;if(arc.length<3&&!arc[1][0]&&!arc[1][1]){t=arcs[++emptyIndex],arcs[emptyIndex]=i,arcs[j]=t}});arcs.forEach(function(i){var e=ends(i),start=e[0],end=e[1],f,g;if(f=fragmentByEnd[start]){delete fragmentByEnd[f.end];f.push(i);f.end=end;if(g=fragmentByStart[end]){delete fragmentByStart[g.start];var fg=g===f?f:f.concat(g);fragmentByStart[fg.start=f.start]=fragmentByEnd[fg.end=g.end]=fg}else{fragmentByStart[f.start]=fragmentByEnd[f.end]=f}}else if(f=fragmentByStart[end]){delete fragmentByStart[f.start];f.unshift(i);f.start=start;if(g=fragmentByEnd[start]){delete fragmentByEnd[g.end];var gf=g===f?f:g.concat(f);fragmentByStart[gf.start=g.start]=fragmentByEnd[gf.end=f.end]=gf}else{fragmentByStart[f.start]=fragmentByEnd[f.end]=f}}else{f=[i];fragmentByStart[f.start=start]=fragmentByEnd[f.end=end]=f}});function ends(i){var arc=topology.arcs[i<0?~i:i],p0=arc[0],p1;if(topology.transform)p1=[0,0],arc.forEach(function(dp){p1[0]+=dp[0],p1[1]+=dp[1]});else p1=arc[arc.length-1];return i<0?[p1,p0]:[p0,p1]}function flush(fragmentByEnd2,fragmentByStart2){for(var k in fragmentByEnd2){var f=fragmentByEnd2[k];delete fragmentByStart2[f.start];delete f.start;delete f.end;f.forEach(function(i){stitchedArcs[i<0?~i:i]=1});fragments.push(f)}}flush(fragmentByEnd,fragmentByStart);flush(fragmentByStart,fragmentByEnd);arcs.forEach(function(i){if(!stitchedArcs[i<0?~i:i])fragments.push([i])});return fragments}function mesh_default(topology){return object(topology,meshArcs.apply(this,arguments))}function meshArcs(topology,object2,filter){var arcs,i,n;if(arguments.length>1)arcs=extractArcs(topology,object2,filter);else for(i=0,arcs=new Array(n=topology.arcs.length);i<n;++i)arcs[i]=i;return{type:\"MultiLineString\",arcs:stitch_default(topology,arcs)}}function extractArcs(topology,object2,filter){var arcs=[],geomsByArc=[],geom;function extract0(i){var j=i<0?~i:i;(geomsByArc[j]||(geomsByArc[j]=[])).push({i,g:geom})}function extract1(arcs2){arcs2.forEach(extract0)}function extract2(arcs2){arcs2.forEach(extract1)}function extract3(arcs2){arcs2.forEach(extract2)}function geometry(o){switch(geom=o,o.type){case\"GeometryCollection\":o.geometries.forEach(geometry);break;case\"LineString\":extract1(o.arcs);break;case\"MultiLineString\":case\"Polygon\":extract2(o.arcs);break;case\"MultiPolygon\":extract3(o.arcs);break}}geometry(object2);geomsByArc.forEach(filter==null?function(geoms){arcs.push(geoms[0].i)}:function(geoms){if(filter(geoms[0].g,geoms[geoms.length-1].g))arcs.push(geoms[0].i)});return arcs}function planarRingArea(ring){var i=-1,n=ring.length,a,b=ring[n-1],area=0;while(++i<n)a=b,b=ring[i],area+=a[0]*b[1]-a[1]*b[0];return Math.abs(area)}function merge_default(topology){return object(topology,mergeArcs.apply(this,arguments))}function mergeArcs(topology,objects){var polygonsByArc={},polygons=[],groups=[];objects.forEach(geometry);function geometry(o){switch(o.type){case\"GeometryCollection\":o.geometries.forEach(geometry);break;case\"Polygon\":extract(o.arcs);break;case\"MultiPolygon\":o.arcs.forEach(extract);break}}function extract(polygon){polygon.forEach(function(ring){ring.forEach(function(arc){(polygonsByArc[arc=arc<0?~arc:arc]||(polygonsByArc[arc]=[])).push(polygon)})});polygons.push(polygon)}function area(ring){return planarRingArea(object(topology,{type:\"Polygon\",arcs:[ring]}).coordinates[0])}polygons.forEach(function(polygon){if(!polygon._){var group=[],neighbors=[polygon];polygon._=1;groups.push(group);while(polygon=neighbors.pop()){group.push(polygon);polygon.forEach(function(ring){ring.forEach(function(arc){polygonsByArc[arc<0?~arc:arc].forEach(function(polygon2){if(!polygon2._){polygon2._=1;neighbors.push(polygon2)}})})})}}});polygons.forEach(function(polygon){delete polygon._});return{type:\"MultiPolygon\",arcs:groups.map(function(polygons2){var arcs=[],n;polygons2.forEach(function(polygon){polygon.forEach(function(ring){ring.forEach(function(arc){if(polygonsByArc[arc<0?~arc:arc].length<2){arcs.push(arc)}})})});arcs=stitch_default(topology,arcs);if((n=arcs.length)>1){for(var i=1,k=area(arcs[0]),ki,t;i<n;++i){if((ki=area(arcs[i]))>k){t=arcs[0],arcs[0]=arcs[i],arcs[i]=t,k=ki}}}return arcs}).filter(function(arcs){return arcs.length>0})}}function bisect_default(a,x){var lo=0,hi=a.length;while(lo<hi){var mid=lo+hi>>>1;if(a[mid]<x)lo=mid+1;else hi=mid}return lo}function neighbors_default(objects){var indexesByArc={},neighbors=objects.map(function(){return[]});function line(arcs,i2){arcs.forEach(function(a){if(a<0)a=~a;var o=indexesByArc[a];if(o)o.push(i2);else indexesByArc[a]=[i2]})}function polygon(arcs,i2){arcs.forEach(function(arc){line(arc,i2)})}function geometry(o,i2){if(o.type===\"GeometryCollection\")o.geometries.forEach(function(o2){geometry(o2,i2)});else if(o.type in geometryType)geometryType[o.type](o.arcs,i2)}var geometryType={LineString:line,MultiLineString:polygon,Polygon:polygon,MultiPolygon:function(arcs,i2){arcs.forEach(function(arc){polygon(arc,i2)})}};objects.forEach(geometry);for(var i in indexesByArc){for(var indexes=indexesByArc[i],m=indexes.length,j=0;j<m;++j){for(var k=j+1;k<m;++k){var ij=indexes[j],ik=indexes[k],n;if((n=neighbors[ij])[i=bisect_default(n,ik)]!==ik)n.splice(i,0,ik);if((n=neighbors[ik])[i=bisect_default(n,ij)]!==ij)n.splice(i,0,ij)}}}return neighbors}function untransform_default(transform){if(transform==null)return identity_default;var x0,y0,kx=transform.scale[0],ky=transform.scale[1],dx=transform.translate[0],dy=transform.translate[1];return function(input,i){if(!i)x0=y0=0;var j=2,n=input.length,output=new Array(n),x1=Math.round((input[0]-dx)/kx),y1=Math.round((input[1]-dy)/ky);output[0]=x1-x0,x0=x1;output[1]=y1-y0,y0=y1;while(j<n)output[j]=input[j],++j;return output}}function quantize_default(topology,transform){if(topology.transform)throw new Error(\"already quantized\");if(!transform||!transform.scale){if(!((n=Math.floor(transform))>=2))throw new Error(\"n must be \\u22652\");box=topology.bbox||bbox_default(topology);var x0=box[0],y0=box[1],x1=box[2],y1=box[3],n;transform={scale:[x1-x0?(x1-x0)/(n-1):1,y1-y0?(y1-y0)/(n-1):1],translate:[x0,y0]}}else{box=topology.bbox}var t=untransform_default(transform),box,key,inputs=topology.objects,outputs={};function quantizePoint(point){return t(point)}function quantizeGeometry(input){var output;switch(input.type){case\"GeometryCollection\":output={type:\"GeometryCollection\",geometries:input.geometries.map(quantizeGeometry)};break;case\"Point\":output={type:\"Point\",coordinates:quantizePoint(input.coordinates)};break;case\"MultiPoint\":output={type:\"MultiPoint\",coordinates:input.coordinates.map(quantizePoint)};break;default:return input}if(input.id!=null)output.id=input.id;if(input.bbox!=null)output.bbox=input.bbox;if(input.properties!=null)output.properties=input.properties;return output}function quantizeArc(input){var i=0,j=1,n2=input.length,p,output=new Array(n2);output[0]=t(input[0],0);while(++i<n2)if((p=t(input[i],i))[0]||p[1])output[j++]=p;if(j===1)output[j++]=[0,0];output.length=j;return output}for(key in inputs)outputs[key]=quantizeGeometry(inputs[key]);return{type:\"Topology\",bbox:box,transform,objects:outputs,arcs:topology.arcs.map(quantizeArc)}}var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function getInterpolator(scheme){const map={blues:d3.interpolateBlues,greens:d3.interpolateGreens,reds:d3.interpolateReds,oranges:d3.interpolateOranges,purples:d3.interpolatePurples};return map[scheme.toLowerCase()]||d3.interpolateBlues}function renderChoropleth(container,spec){const{config={},encoding,data}=spec;const geoField=config.geoField||encoding.geo&&encoding.geo.field;const valueField=config.valueField||encoding.color&&encoding.color.field;const projection=config.projection||\"naturalEarth1\";const mapType=config.mapType||\"world\";const colorScheme=config.colorScheme||\"blues\";const objectName=config.objectName;const nameProperty=config.nameProperty||\"name\";const customCenter=config.center;const customScale=config.scale;const parallels=config.parallels;const rotate=config.rotate;const topojsonData=config.topojsonData;if(!topojsonData){container.innerHTML='<div style=\"color:#ef4444;padding:20px\">TopoJSON data must be embedded at spec-generation time. No CDN fetches.</div>';return}const{svg,g,dims}=createSvg(container,spec,{top:50,right:20,bottom:40,left:20});const tooltip=createTooltip(container);const valueLookup={};data.forEach(d=>{const key=String(d[geoField]).toLowerCase().trim();valueLookup[key]=Number(d[valueField])});const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const valExtent=d3.extent(allValues);const hasMixedSign=valExtent[0]<0&&valExtent[1]>0;const allNegative=valExtent[1]<=0&&valExtent[0]<0;let colorScale;if(hasMixedSign){const maxAbs=Math.max(Math.abs(valExtent[0]),Math.abs(valExtent[1]));colorScale=d3.scaleDiverging(d3.interpolateRdBu).domain([maxAbs,0,-maxAbs])}else if(allNegative){colorScale=d3.scaleSequential(d3.interpolateReds).domain([valExtent[0],valExtent[1]])}else{const interpolator=getInterpolator(colorScheme);const rangeRatio=valExtent[0]>0?valExtent[1]/valExtent[0]:valExtent[1]>0?Infinity:1;colorScale=rangeRatio>100?d3.scaleQuantize().domain(valExtent).range(d3.quantize(interpolator,7)):d3.scaleSequential(interpolator).domain(valExtent)}var features;if(objectName){features=topojson.feature(topojsonData,topojsonData.objects[objectName])}else{var objects=topojsonData.objects;var objKey;if(objects.countries)objKey=\"countries\";else if(objects.states)objKey=\"states\";else objKey=Object.keys(objects)[0];features=topojson.feature(topojsonData,objects[objKey])}var geoProjection;if(projection===\"albersUsa\"){geoProjection=d3.geoAlbersUsa().fitSize([dims.innerWidth,dims.innerHeight],features)}else{var projName=\"geo\"+projection.charAt(0).toUpperCase()+projection.slice(1);var projFn=d3[projName]||d3.geoNaturalEarth1;geoProjection=projFn();if(rotate)geoProjection.rotate(rotate);if(parallels&&typeof geoProjection.parallels===\"function\")geoProjection.parallels(parallels);if(customScale){if(customCenter)geoProjection.center(customCenter);geoProjection.scale(customScale);geoProjection.translate([dims.innerWidth/2,dims.innerHeight/2])}else{geoProjection.fitSize([dims.innerWidth,dims.innerHeight],features)}}var path=d3.geoPath().projection(geoProjection);function lookupValue(feature2){var props=feature2.properties||{};var nameFields=[nameProperty,\"name\",\"NAME\",\"admin\",\"ADMIN\",\"geounit\"];var name=\"\";for(var i=0;i<nameFields.length;i++){if(props[nameFields[i]]){name=String(props[nameFields[i]]).toLowerCase().trim();break}}if(name&&valueLookup[name]!=null)return valueLookup[name];for(var key in valueLookup){if(name&&(name.indexOf(key)>=0||key.indexOf(name)>=0)){return valueLookup[key]}}return null}g.selectAll(\"path.region\").data(features.features).enter().append(\"path\").attr(\"class\",\"region\").attr(\"d\",path).attr(\"fill\",function(d){var val=lookupValue(d);return val!=null?colorScale(val):\"#1e2028\"}).attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",.5).on(\"mouseover\",function(event,d){var props=d.properties||{};var name=props[nameProperty]||props.name||props.NAME||props.admin||props.geounit||\"Unknown\";var val=lookupValue(d);d3.select(this).attr(\"stroke\",TEXT_COLOR).attr(\"stroke-width\",1.5);showTooltip(tooltip,\"<strong>\"+name+\"</strong>\"+(val!=null?\"<br/>\"+valueField+\": \"+formatValue(val):\"<br/><em>No data</em>\"),event)}).on(\"mousemove\",function(event){positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",.5);hideTooltip(tooltip)});var legendWidth=Math.min(200,dims.innerWidth*.3);var legendHeight=10;var legendX=dims.innerWidth-legendWidth-10;var legendY=dims.innerHeight-30;var legendScale=d3.scaleLinear().domain(valExtent).range([0,legendWidth]);var legendAxis=d3.axisBottom(legendScale).ticks(4).tickFormat(function(d){return formatValue(d)});var gradientId=\"choropleth-gradient-\"+Math.random().toString(36).slice(2,8);var defs=svg.append(\"defs\");var gradient=defs.append(\"linearGradient\").attr(\"id\",gradientId);gradient.append(\"stop\").attr(\"offset\",\"0%\").attr(\"stop-color\",colorScale(valExtent[0]));gradient.append(\"stop\").attr(\"offset\",\"50%\").attr(\"stop-color\",colorScale((valExtent[0]+valExtent[1])/2));gradient.append(\"stop\").attr(\"offset\",\"100%\").attr(\"stop-color\",colorScale(valExtent[1]));var legendG=g.append(\"g\").attr(\"transform\",\"translate(\"+legendX+\",\"+legendY+\")\");legendG.append(\"rect\").attr(\"width\",legendWidth).attr(\"height\",legendHeight).attr(\"rx\",3).style(\"fill\",\"url(#\"+gradientId+\")\");legendG.append(\"g\").attr(\"transform\",\"translate(0,\"+legendHeight+\")\").call(legendAxis).selectAll(\"text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");legendG.selectAll(\".domain, .tick line\").attr(\"stroke\",AXIS_COLOR)}globalThis.topojson=src_exports;return __toCommonJS(choropleth_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
13
|
+
export const circlePackBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var circle_pack_render_exports={};__export(circle_pack_render_exports,{renderChart:()=>renderCirclePack});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function contrastTextMuted(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"rgba(255,255,255,0.7)\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"rgba(26,26,46,0.6)\":\"rgba(255,255,255,0.7)\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderCirclePack(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field||encoding.label?.field;const valueField=config.valueField||encoding.size?.field;const parentField=config.parentField||null;const padding=config.padding??3;const width=container.clientWidth||800;const height=container.clientHeight||500;const titleHeight=spec.title?36:0;const contentPadding=8;const availableWidth=width-contentPadding*2;const availableHeight=height-titleHeight-contentPadding*2;const packSize=Math.min(availableWidth,availableHeight);const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const offsetX=(availableWidth-packSize)/2+contentPadding;const offsetY=titleHeight+(availableHeight-packSize)/2+contentPadding;const g=svg.append(\"g\").attr(\"transform\",`translate(${offsetX},${offsetY})`);const tooltip=createTooltip(container);const root=buildHierarchy(data,categoryField,valueField,parentField,config);if(root.value===0){root.each(node=>{if(!node.children)node.value=1});root.sum(d=>d.children?0:1)}const packLayout=d3.pack().size([packSize,packSize]).padding(padding);packLayout(root);const colorScale=buildColorScale(encoding.color,data);const isQuantitativeColor=encoding.color?.type===\"quantitative\";const colorField=encoding.color?.field;const leaves=root.leaves();const circles=g.selectAll(\".pack-circle\").data(leaves).join(\"circle\").attr(\"class\",\"pack-circle\").attr(\"cx\",d=>d.x).attr(\"cy\",d=>d.y).attr(\"r\",d=>Math.max(0,d.r)).attr(\"fill\",d=>{if(isQuantitativeColor){return colorScale(Number(d.data._data?.[colorField]??d.value))}return parentField&&d.parent?.data?.name&&d.parent.data.name!==\"root\"?colorScale(d.parent.data.name):colorScale(d.data.name)}).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).attr(\"cursor\",\"default\");circles.on(\"mouseover\",function(event,d){d3.select(this).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",2).style(\"filter\",\"brightness(1.15)\");const parentName=parentField&&d.parent?.data?.name&&d.parent.data.name!==\"root\"?d.parent.data.name+\" > \":\"\";showTooltip(tooltip,`<strong>${parentName}${d.data.name}</strong><br/>${valueField}: ${formatValue(d.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).style(\"filter\",null);hideTooltip(tooltip)});if(config.showLabels!==false){leaves.forEach((leaf,i)=>{if(leaf.r<15)return;const fillColor=isQuantitativeColor?colorScale(Number(leaf.data._data?.[colorField]??leaf.value)):parentField&&leaf.parent?.data?.name&&leaf.parent.data.name!==\"root\"?colorScale(leaf.parent.data.name):colorScale(leaf.data.name);const labelColor=contrastText(fillColor);const valueColor=contrastTextMuted(fillColor);const labelGroup=g.append(\"g\").attr(\"pointer-events\",\"none\");const fontSize=leaf.r>40?12:leaf.r>25?10:8;const name=String(leaf.data.name);const maxChars=Math.max(3,Math.floor(leaf.r/(fontSize*.35)));const truncated=name.length>maxChars?name.slice(0,maxChars-1)+\"\\u2026\":name;const showValue=leaf.r>=25&&config.showValues!==false;const labelY=showValue?leaf.y-fontSize*.4:leaf.y;labelGroup.append(\"text\").attr(\"x\",leaf.x).attr(\"y\",labelY).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",labelColor).attr(\"font-size\",`${fontSize}px`).attr(\"font-weight\",\"700\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(truncated);if(showValue){const valueFontSize=Math.max(8,fontSize-2);labelGroup.append(\"text\").attr(\"x\",leaf.x).attr(\"y\",leaf.y+fontSize*.6).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",valueColor).attr(\"font-size\",`${valueFontSize}px`).attr(\"font-weight\",\"400\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(formatValue(leaf.value))}})}}function buildHierarchy(data,categoryField,valueField,parentField,config){const allVals=data.map(d=>Number(d[valueField])||0).filter(v=>v>0);const maxVal=allVals.length>0?Math.max(...allVals):0;const minVisible=maxVal*.02;const clampVal=v=>v>0&&v<minVisible?minVisible:v;if(parentField){const parents=[...new Set(data.map(d=>d[parentField]))];const hierarchy2={name:\"root\",children:parents.map(p=>({name:p,children:data.filter(d=>d[parentField]===p).map(d=>({name:d[categoryField]||d[config.childField]||d[parentField],value:clampVal(Number(d[valueField])||0),_data:d}))}))};return d3.hierarchy(hierarchy2).sum(d=>d.value).sort((a,b)=>b.value-a.value)}const hierarchy={name:\"root\",children:data.map(d=>({name:d[categoryField],value:clampVal(Number(d[valueField])||0),_data:d}))};return d3.hierarchy(hierarchy).sum(d=>d.value).sort((a,b)=>b.value-a.value)}return __toCommonJS(circle_pack_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
14
|
+
export const connectedDotPlotBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var connected_dot_plot_render_exports={};__export(connected_dot_plot_render_exports,{renderChart:()=>renderConnectedDotPlot});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderConnectedDotPlot(container,spec){const{config,encoding,data}=spec;const startField=config.metric1Field||config.startField||\"start\";const endField=config.metric2Field||config.endField||\"end\";const categoryField=config.categoryField||encoding.y?.field||\"category\";const showLabels=config.showLabels!==false;const showDifference=config.showDifference===true;const startLabel=config.metric1Field||config.startLabel||startField;const endLabel=config.metric2Field||config.endLabel||endField;let sortedData=[...data];if(config.sortBy===\"value\"||config.sortBy===\"gap\"){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>{const diffA=Number(a[endField])-Number(a[startField]);const diffB=Number(b[endField])-Number(b[startField]);return order*(diffA-diffB)})}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>{return order*String(a[categoryField]).localeCompare(String(b[categoryField]),void 0,{sensitivity:\"base\",numeric:true})})}container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);const legendDiv=createLegend([{label:startLabel,color:categorical[0]},{label:endLabel,color:categorical[1]}],{shape:\"circle\"});container.appendChild(legendDiv);const categories=sortedData.map(d=>String(d[categoryField]));const leftMargin=calculateLeftMargin(categories);const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin});const tooltip=createTooltip(chartWrapper);if(isAllZeros(sortedData,startField)&&isAllZeros(sortedData,endField)){svg.style(\"background\",\"none\");renderEmptyState(g,dims);return}const yScale=d3.scaleBand().domain(categories).range([0,dims.innerHeight]).padding(.3);const allValues=sortedData.flatMap(d=>[Number(d[startField]),Number(d[endField])]);const minVal=d3.min(allValues);const maxVal=d3.max(allValues);const padding=(maxVal-minVal)*.08||1;const xScale=d3.scaleLinear().domain([minVal-padding,maxVal+padding]).range([0,dims.innerWidth]).nice();const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(6).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(10).tickFormat(d=>{if(d.length>30)return d.slice(0,29)+\"\\u2026\";return d}));styleAxis(yAxis);const colorScale=buildColorScale(encoding.color,sortedData);const startColor=categorical[0];const endColor=categorical[1];const bandwidth=yScale.bandwidth();const maxDotRadius=Math.floor(bandwidth/2);const LABEL_RADIUS=11;const SMALL_RADIUS=5;const isSmallMode=maxDotRadius<LABEL_RADIUS;const canShowLabels=showLabels&&!isSmallMode;const DOT_RADIUS=canShowLabels?Math.min(LABEL_RADIUS,maxDotRadius):Math.min(SMALL_RADIUS,maxDotRadius);g.selectAll(\".row-hover-target\").data(sortedData).join(\"rect\").attr(\"class\",\"row-hover-target\").attr(\"x\",0).attr(\"y\",d=>yScale(String(d[categoryField]))).attr(\"width\",dims.innerWidth).attr(\"height\",bandwidth).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){const cat=String(d[categoryField]);const startVal=Number(d[startField]);const endVal=Number(d[endField]);const diff=endVal-startVal;g.selectAll(`.dot-${css(cat)}`).attr(\"opacity\",.8).attr(\"r\",DOT_RADIUS+2);showTooltip(tooltip,`<strong>${cat}</strong><br/>${startLabel}: ${formatValue(startVal)}<br/>${endLabel}: ${formatValue(endVal)}<br/>Difference: ${diff>=0?\"+\":\"\"}${formatValue(diff)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(_event,d){const cat=String(d[categoryField]);g.selectAll(`.dot-${css(cat)}`).attr(\"opacity\",1).attr(\"r\",DOT_RADIUS);hideTooltip(tooltip)});sortedData.forEach(d=>{const cat=String(d[categoryField]);const startVal=Number(d[startField]);const endVal=Number(d[endField]);const yMid=yScale(cat)+bandwidth/2;const x1=xScale(startVal);const x2=xScale(endVal);const leftIsStart=x1<=x2;const leftX=leftIsStart?x1:x2;const rightX=leftIsStart?x2:x1;const leftColor=leftIsStart?startColor:endColor;const rightColor=leftIsStart?endColor:startColor;const leftVal=leftIsStart?startVal:endVal;const rightVal=leftIsStart?endVal:startVal;const dotClass=`dot-${css(cat)}`;g.append(\"line\").attr(\"x1\",x1).attr(\"y1\",yMid).attr(\"x2\",x2).attr(\"y2\",yMid).attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",2).attr(\"opacity\",.6).attr(\"pointer-events\",\"none\");drawDot(g,leftX,yMid,DOT_RADIUS,leftColor,dotClass);const dotsTooClose=Math.abs(rightX-leftX)<DOT_RADIUS*2.5;if(canShowLabels&&!dotsTooClose){drawLabel(g,leftX,yMid,leftVal,leftColor)}drawDot(g,rightX,yMid,DOT_RADIUS,rightColor,dotClass);if(canShowLabels){drawLabel(g,rightX,yMid,rightVal,rightColor)}if(showDifference){const diff=endVal-startVal;const midX=(x1+x2)/2;g.append(\"text\").attr(\"x\",midX).attr(\"y\",yMid).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(`${diff>=0?\"+\":\"\"}${formatValue(diff)}`)}});addSortControls(svg,container,spec,dims,renderConnectedDotPlot)}function css(cat){return cat.replace(/[^a-zA-Z0-9]/g,\"_\")}function drawDot(g,cx,cy,r,color,className){g.append(\"circle\").attr(\"class\",className).attr(\"cx\",cx).attr(\"cy\",cy).attr(\"r\",r).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")}function drawLabel(g,cx,cy,value,bgColor){g.append(\"text\").attr(\"x\",cx).attr(\"y\",cy).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",contrastText(bgColor)).attr(\"font-size\",\"8px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(value))}return __toCommonJS(connected_dot_plot_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
15
|
+
export const connectedScatterBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var connected_scatter_render_exports={};__export(connected_scatter_render_exports,{renderChart:()=>renderConnectedScatter});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderConnectedScatter(container,spec){const{config,encoding,data}=spec;const xField=config.xField||encoding.x?.field;const yField=config.yField||encoding.y?.field;const orderField=config.orderField;const colorField=config.colorField||encoding.color?.field||null;const showArrows=config.showArrows??false;const strokeWidth=config.strokeWidth??1.5;const baseDotRadius=config.dotRadius??4;const showLabels=config.showLabels??false;if(!xField||!yField)return;const hasLegend=colorField!==null;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{right:30});const tooltip=createTooltip(container);const parsed=data.map((d,i)=>({...d,_x:Number(d[xField]),_y:Number(d[yField]),_order:orderField?d[orderField]:i,_idx:i})).filter(d=>!isNaN(d._x)&&!isNaN(d._y));const sortByOrder=(a,b)=>{const aVal=a._order;const bVal=b._order;if(typeof aVal===\"number\"&&typeof bVal===\"number\")return aVal-bVal;const aNum=Number(aVal);const bNum=Number(bVal);if(!isNaN(aNum)&&!isNaN(bNum))return aNum-bNum;const aDate=new Date(aVal).getTime();const bDate=new Date(bVal).getTime();if(!isNaN(aDate)&&!isNaN(bDate))return aDate-bDate;return String(aVal).localeCompare(String(bVal))};const xExtent=d3.extent(parsed,d=>d._x);const yExtent=d3.extent(parsed,d=>d._y);const xPad=(xExtent[1]-xExtent[0])*.05||1;const yPad=(yExtent[1]-yExtent[0])*.05||1;const xScale=d3.scaleLinear().domain([xExtent[0]-xPad,xExtent[1]+xPad]).range([0,dims.innerWidth]).nice();const yScale=d3.scaleLinear().domain([yExtent[0]-yPad,yExtent[1]+yPad]).range([dims.innerHeight,0]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const colorScale=buildColorScale(encoding.color,data);const pointDensity=parsed.length/(dims.innerWidth*dims.innerHeight/1e4);let dotRadius=baseDotRadius;if(pointDensity>5)dotRadius=Math.max(2,baseDotRadius-2);else if(pointDensity>2)dotRadius=Math.max(3,baseDotRadius-1);if(showArrows){const defs=svg.append(\"defs\");if(hasLegend){const entities=[...new Set(parsed.map(d=>d[colorField]))];entities.forEach((entity,i)=>{defs.append(\"marker\").attr(\"id\",`arrow-${i}`).attr(\"viewBox\",\"0 0 10 10\").attr(\"refX\",8).attr(\"refY\",5).attr(\"markerWidth\",6).attr(\"markerHeight\",6).attr(\"orient\",\"auto-start-reverse\").append(\"path\").attr(\"d\",\"M 0 0 L 10 5 L 0 10 z\").attr(\"fill\",colorScale(entity))})}else{defs.append(\"marker\").attr(\"id\",\"arrow-0\").attr(\"viewBox\",\"0 0 10 10\").attr(\"refX\",8).attr(\"refY\",5).attr(\"markerWidth\",6).attr(\"markerHeight\",6).attr(\"orient\",\"auto-start-reverse\").append(\"path\").attr(\"d\",\"M 0 0 L 10 5 L 0 10 z\").attr(\"fill\",categorical[0])}}const line=d3.line().x(d=>xScale(d._x)).y(d=>yScale(d._y)).curve(d3.curveMonotoneX);const pointPositions=[];if(hasLegend){const entities=[...new Set(parsed.map(d=>d[colorField]))];entities.forEach((entity,entityIdx)=>{const entityData=parsed.filter(d=>d[colorField]===entity);entityData.sort(sortByOrder);const color=colorScale(entity);const path=g.append(\"path\").datum(entityData).attr(\"class\",\"trajectory-path\").attr(\"data-entity\",entity).attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"stroke-linejoin\",\"round\").attr(\"stroke-linecap\",\"round\").attr(\"pointer-events\",\"none\").attr(\"d\",line);if(showArrows){path.attr(\"marker-end\",`url(#arrow-${entityIdx})`)}g.selectAll(`.dot-${entityIdx}`).data(entityData).join(\"circle\").attr(\"class\",`dot dot-entity-${entityIdx}`).attr(\"data-entity\",entity).attr(\"cx\",d=>xScale(d._x)).attr(\"cy\",d=>yScale(d._y)).attr(\"r\",dotRadius).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");entityData.forEach((d,i)=>{pointPositions.push({d,cx:xScale(d._x),cy:yScale(d._y),entity,orderLabel:orderField?`${orderField}: ${d._order}`:`Step ${i+1}`,globalIdx:pointPositions.length})});if(showLabels){const usedPositions=[];const minDist=dotRadius*3;g.selectAll(`.label-${entityIdx}`).data(entityData).join(\"text\").attr(\"class\",`seq-label label-${entityIdx}`).attr(\"x\",d=>xScale(d._x)+dotRadius+3).attr(\"y\",d=>yScale(d._y)-dotRadius-2).attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text((d,i)=>{const px=xScale(d._x);const py=yScale(d._y);const tooClose=usedPositions.some(p=>Math.abs(p.x-px)<minDist&&Math.abs(p.y-py)<minDist);if(tooClose)return\"\";usedPositions.push({x:px,y:py});return i+1})}})}else{parsed.sort(sortByOrder);const color=categorical[0];const path=g.append(\"path\").datum(parsed).attr(\"class\",\"trajectory-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"stroke-linejoin\",\"round\").attr(\"stroke-linecap\",\"round\").attr(\"pointer-events\",\"none\").attr(\"d\",line);if(showArrows){path.attr(\"marker-end\",\"url(#arrow-0)\")}g.selectAll(\".dot\").data(parsed).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",d=>xScale(d._x)).attr(\"cy\",d=>yScale(d._y)).attr(\"r\",dotRadius).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");parsed.forEach((d,i)=>{pointPositions.push({d,cx:xScale(d._x),cy:yScale(d._y),entity:null,orderLabel:orderField?`${orderField}: ${d._order}`:`Step ${i+1}`,globalIdx:i})});if(showLabels){const usedPositions=[];const minDist=dotRadius*3;g.selectAll(\".seq-label\").data(parsed).join(\"text\").attr(\"class\",\"seq-label\").attr(\"x\",d=>xScale(d._x)+dotRadius+3).attr(\"y\",d=>yScale(d._y)-dotRadius-2).attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text((d,i)=>{const px=xScale(d._x);const py=yScale(d._y);const tooClose=usedPositions.some(p=>Math.abs(p.x-px)<minDist&&Math.abs(p.y-py)<minDist);if(tooClose)return\"\";usedPositions.push({x:px,y:py});return i+1})}}const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){g.selectAll(\".dot\").filter(function(){return d3.select(this).attr(\"data-active\")===\"true\"}).attr(\"r\",dotRadius).attr(\"data-active\",null)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").each(function(){const el=d3.select(this);const cx=parseFloat(el.attr(\"cx\"));const cy=parseFloat(el.attr(\"cy\"));if(Math.abs(cx-p.cx)<.5&&Math.abs(cy-p.cy)<.5){el.attr(\"r\",dotRadius*1.5).attr(\"data-active\",\"true\")}});let html=\"\";if(p.entity)html+=`<strong>${p.entity}</strong><br/>`;html+=`${p.orderLabel}<br/>`;html+=`<strong>${encoding.x?.title||xField}:</strong> ${formatValue(p.d._x)}<br/>`;html+=`<strong>${encoding.y?.title||yField}:</strong> ${formatValue(p.d._y)}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){g.selectAll(\".dot\").filter(function(){return d3.select(this).attr(\"data-active\")===\"true\"}).attr(\"r\",dotRadius).attr(\"data-active\",null);activeIdx=-1}hideTooltip(tooltip)});if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"line-dot\",callbacks:{onHover:category=>{g.selectAll(\".trajectory-path\").each(function(){const el=d3.select(this);el.attr(\"opacity\",el.attr(\"data-entity\")===category?1:.12)});g.selectAll(\".dot\").each(function(){const el=d3.select(this);el.attr(\"opacity\",el.attr(\"data-entity\")===category?1:.12)});g.selectAll(\".seq-label\").attr(\"opacity\",.15)},onLeave:()=>{g.selectAll(\".trajectory-path\").attr(\"opacity\",1);g.selectAll(\".dot\").attr(\"opacity\",1);g.selectAll(\".seq-label\").attr(\"opacity\",1)}}});container.appendChild(legendDiv)}}return __toCommonJS(connected_scatter_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
16
|
+
export const densityPlotBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var density_plot_render_exports={};__export(density_plot_render_exports,{renderChart:()=>renderDensityPlot});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function gaussianKernel(u){return 1/Math.sqrt(2*Math.PI)*Math.exp(-.5*u*u)}function stdDev(values){const n=values.length;if(n<2)return 1;const mean=values.reduce((s,v)=>s+v,0)/n;const variance=values.reduce((s,v)=>s+(v-mean)**2,0)/(n-1);return Math.sqrt(variance)}function silvermanBandwidth(values){const sd=stdDev(values);const n=values.length;if(sd===0)return 1;return 1.06*sd*Math.pow(n,-.2)}function computeKDE(values,samplePoints,bandwidth){const n=values.length;if(n===0)return samplePoints.map(x=>[x,0]);return samplePoints.map(x=>{const density=values.reduce((sum,xi)=>sum+gaussianKernel((x-xi)/bandwidth),0)/(n*bandwidth);return[x,density]})}function renderDensityPlot(container,spec){const{config,encoding,data}=spec;const valueField=config.valueField||encoding.x?.field||Object.keys(data[0]).find(k=>typeof data[0][k]===\"number\")||Object.keys(data[0])[0];const categoryField=config.categoryField||encoding.color?.field||null;const filled=config.filled??true;const showRug=config.showRug??false;const userBandwidth=typeof config.bandwidth===\"number\"?config.bandwidth:void 0;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const bottomMargin=showRug?65:50;const{svg,g,dims}=createSvg(chartWrapper,spec,{bottom:bottomMargin,left:60});const tooltip=createTooltip(container);const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v)&&isFinite(v));if(allValues.length===0){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"No numeric data available\");return}const xExtent=d3.extent(allValues);const xRange=xExtent[1]-xExtent[0];const xPad=xRange*.1||1;const xScale=d3.scaleLinear().domain([xExtent[0]-xPad,xExtent[1]+xPad]).range([0,dims.innerWidth]).nice();const sampleCount=200;const xDomain=xScale.domain();const step=(xDomain[1]-xDomain[0])/(sampleCount-1);const samplePoints=Array.from({length:sampleCount},(_,i)=>xDomain[0]+i*step);let groups=[];let groupDataMap=new Map;let groupDensities=new Map;let maxDensity=0;if(categoryField){groups=[...new Set(data.map(d=>String(d[categoryField])))];groups.forEach(group=>{const vals=data.filter(d=>String(d[categoryField])===group).map(d=>Number(d[valueField])).filter(v=>!isNaN(v)&&isFinite(v));groupDataMap.set(group,vals);const bw=userBandwidth||silvermanBandwidth(vals);const density=computeKDE(vals,samplePoints,bw);groupDensities.set(group,density);const localMax=d3.max(density,d=>d[1])||0;if(localMax>maxDensity)maxDensity=localMax})}else{groups=[\"_all\"];groupDataMap.set(\"_all\",allValues);const bw=userBandwidth||silvermanBandwidth(allValues);const density=computeKDE(allValues,samplePoints,bw);groupDensities.set(\"_all\",density);maxDensity=d3.max(density,d=>d[1])||0}if(maxDensity===0)maxDensity=1;const yScale=d3.scaleLinear().domain([0,maxDensity*1.08]).range([dims.innerHeight,0]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yTickCount=getAdaptiveTickCount(dims.innerHeight,50);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>{if(d===0)return\"0\";if(d>=1)return formatValue(d);const sig=d.toPrecision(2);return parseFloat(sig).toString()}));styleAxis(yAxis);const colorScale=categoryField?buildColorScale(encoding.color,data):()=>categorical[0];const area=d3.area().x(d=>xScale(d[0])).y0(dims.innerHeight).y1(d=>yScale(d[1])).curve(d3.curveBasis);const line=d3.line().x(d=>xScale(d[0])).y(d=>yScale(d[1])).curve(d3.curveBasis);const fillOpacity=groups.length>1?.3:.4;const densityGroup=g.append(\"g\").attr(\"class\",\"density-curves\");groups.forEach((group,gi)=>{const density=groupDensities.get(group);const color=categoryField?colorScale(group):categorical[0];if(filled){densityGroup.append(\"path\").datum(density).attr(\"class\",`density-area density-area-${gi}`).attr(\"d\",area).attr(\"fill\",color).attr(\"fill-opacity\",fillOpacity).attr(\"pointer-events\",\"none\")}densityGroup.append(\"path\").datum(density).attr(\"class\",`density-line density-line-${gi}`).attr(\"d\",line).attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",2).attr(\"stroke-opacity\",.9).attr(\"pointer-events\",\"none\")});if(showRug){const rugHeight=6;const rugY=dims.innerHeight;if(categoryField){groups.forEach(group=>{const vals=groupDataMap.get(group);const color=colorScale(group);g.selectAll(`.rug-tick-${group.replace(/\\s+/g,\"-\")}`).data(vals).join(\"line\").attr(\"class\",`rug-tick`).attr(\"x1\",d=>xScale(d)).attr(\"x2\",d=>xScale(d)).attr(\"y1\",rugY+2).attr(\"y2\",rugY+2+rugHeight).attr(\"stroke\",color).attr(\"stroke-width\",1).attr(\"stroke-opacity\",.5).attr(\"pointer-events\",\"none\")})}else{g.selectAll(\".rug-tick\").data(allValues).join(\"line\").attr(\"class\",\"rug-tick\").attr(\"x1\",d=>xScale(d)).attr(\"x2\",d=>xScale(d)).attr(\"y1\",rugY+2).attr(\"y2\",rugY+2+rugHeight).attr(\"stroke\",categorical[0]).attr(\"stroke-width\",1).attr(\"stroke-opacity\",.4).attr(\"pointer-events\",\"none\")}}const crosshair=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"opacity\",0).attr(\"pointer-events\",\"none\");const hoverDots=g.append(\"g\").attr(\"class\",\"hover-dots\");g.append(\"rect\").attr(\"class\",\"overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,g.node());const xVal=xScale.invert(mx);crosshair.attr(\"x1\",mx).attr(\"x2\",mx).attr(\"opacity\",.6);hoverDots.selectAll(\"circle\").remove();let tooltipHtml=\"\";if(categoryField){tooltipHtml+=`<strong>${encoding.x?.title||valueField}:</strong> ${formatValue(xVal)}`;groups.forEach(group=>{const density=groupDensities.get(group);const closest=density.reduce((best,pt)=>Math.abs(pt[0]-xVal)<Math.abs(best[0]-xVal)?pt:best);const color=colorScale(group);const yPos=yScale(closest[1]);hoverDots.append(\"circle\").attr(\"cx\",mx).attr(\"cy\",yPos).attr(\"r\",4).attr(\"fill\",color).attr(\"stroke\",\"#0f1117\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");tooltipHtml+=`<br/><span style=\"color:${color}\">\\u25CF</span> ${group}: ${closest[1].toFixed(4)}`})}else{const density=groupDensities.get(\"_all\");const closest=density.reduce((best,pt)=>Math.abs(pt[0]-xVal)<Math.abs(best[0]-xVal)?pt:best);const yPos=yScale(closest[1]);hoverDots.append(\"circle\").attr(\"cx\",mx).attr(\"cy\",yPos).attr(\"r\",4).attr(\"fill\",categorical[0]).attr(\"stroke\",\"#0f1117\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");tooltipHtml=`<strong>${encoding.x?.title||valueField}:</strong> ${formatValue(xVal)}`;tooltipHtml+=`<br/>Density: ${closest[1].toFixed(4)}`}showTooltip(tooltip,tooltipHtml,event)}).on(\"mouseleave\",function(){crosshair.attr(\"opacity\",0);hoverDots.selectAll(\"circle\").remove();hideTooltip(tooltip)});if(categoryField&&groups.length>1){const legendDiv=createLegend(colorScale,{shape:\"circle\",callbacks:{onHover:group=>{const gi=groups.indexOf(group);groups.forEach((_,i)=>{const areaOpacity=i===gi?Math.min(fillOpacity+.2,.7):.08;const lineOpacity=i===gi?1:.15;const lineWidth=i===gi?3:1.5;densityGroup.selectAll(`.density-area-${i}`).attr(\"fill-opacity\",areaOpacity);densityGroup.selectAll(`.density-line-${i}`).attr(\"stroke-opacity\",lineOpacity).attr(\"stroke-width\",lineWidth)})},onLeave:()=>{groups.forEach((_,i)=>{densityGroup.selectAll(`.density-area-${i}`).attr(\"fill-opacity\",fillOpacity);densityGroup.selectAll(`.density-line-${i}`).attr(\"stroke-opacity\",.9).attr(\"stroke-width\",2)})}}});container.appendChild(legendDiv)}}return __toCommonJS(density_plot_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
17
|
+
export const divergingBarBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var diverging_bar_render_exports={};__export(diverging_bar_render_exports,{renderChart:()=>renderDivergingBar});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderDivergingBar(container,spec){const{encoding,data,config}=spec;const orientation=config?.orientation===\"vertical\"?\"vertical\":\"horizontal\";const valueField=encoding.x?.field||Object.keys(data[0])[1];const categoryField=encoding.y?.field||Object.keys(data[0])[0];if(orientation===\"vertical\"){renderVertical(container,spec,categoryField,valueField)}else{renderHorizontal(container,spec,categoryField,valueField)}}function renderHorizontal(container,spec,xField,yField){const{encoding,data,config}=spec;const categories=data.map(d=>String(d[xField]));const leftMargin=calculateLeftMargin(categories);const{svg,g,dims}=createSvg(container,spec,{left:leftMargin,bottom:40});const tooltip=createTooltip(container);if(isAllZeros(data,yField)){renderEmptyState(g,dims);return}const yScale=d3.scaleBand().domain(categories).range([0,dims.innerHeight]).padding(.2);const values=data.map(d=>Number(d[yField]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)));const xScale=d3.scaleLinear().domain([-maxAbs,maxAbs]).range([0,dims.innerWidth]).nice();const midX=xScale(0);const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(10).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);g.append(\"line\").attr(\"x1\",midX).attr(\"y1\",0).attr(\"x2\",midX).attr(\"y2\",dims.innerHeight).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",1.5);const maxBarHeight=Math.min(80,dims.innerHeight*.3);const barHeight=Math.min(yScale.bandwidth(),maxBarHeight);const barYOffset=(yScale.bandwidth()-barHeight)/2;g.selectAll(\".bar-hover-target\").data(data).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"y\",d=>yScale(String(d[xField]))).attr(\"x\",0).attr(\"height\",yScale.bandwidth()).attr(\"width\",dims.innerWidth).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd[xField]===d[xField]).attr(\"opacity\",.8);const val=Number(d[yField]);showTooltip(tooltip,`<strong>${d[xField]}</strong><br/>${yField}: ${val>=0?\"+\":\"\"}${formatValue(val)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(data).join(\"rect\").attr(\"class\",\"bar\").attr(\"y\",d=>yScale(String(d[xField]))+barYOffset).attr(\"height\",barHeight).attr(\"x\",d=>{const val=Number(d[yField]);return val>=0?midX:xScale(val)}).attr(\"width\",d=>Math.max(2,Math.abs(xScale(Number(d[yField]))-midX))).attr(\"fill\",d=>Number(d[yField])>=0?\"#10b981\":\"#ef4444\").attr(\"rx\",3).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,barHeight,true);if(showLabels){g.selectAll(\".bar-label\").data(data).join(\"text\").attr(\"class\",\"bar-label\").attr(\"y\",d=>yScale(String(d[xField]))+yScale.bandwidth()/2).attr(\"x\",d=>{const val=Number(d[yField]);const barEnd=xScale(val);const barWidth=Math.abs(barEnd-midX);if(val>=0){return barWidth>50?barEnd-5:barEnd+5}else{return barWidth>50?barEnd+5:barEnd-5}}).attr(\"text-anchor\",d=>{const val=Number(d[yField]);const barWidth=Math.abs(xScale(val)-midX);if(val>=0)return barWidth>50?\"end\":\"start\";return barWidth>50?\"start\":\"end\"}).attr(\"dominant-baseline\",\"middle\").attr(\"fill\",d=>{const barWidth=Math.abs(xScale(Number(d[yField]))-midX);return barWidth>50?\"#ffffff\":TEXT_MUTED}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").style(\"opacity\",1).text(d=>{const val=Number(d[yField]);return(val>=0?\"+\":\"\")+formatValue(val)})}}function renderVertical(container,spec,xField,yField){const{encoding,data,config}=spec;const categories=data.map(d=>String(d[xField]));const containerWidth=container.clientWidth||800;const estimatedBarWidth=(containerWidth-140)/categories.length;const willRotate=shouldRotateLabels(categories,estimatedBarWidth);const bottomMargin=calculateBottomMargin(categories,willRotate);const{svg,g,dims}=createSvg(container,spec,{bottom:bottomMargin,left:70});const tooltip=createTooltip(container);if(isAllZeros(data,yField)){renderEmptyState(g,dims);return}const xScale=d3.scaleBand().domain(categories).range([0,dims.innerWidth]).padding(.2);const values=data.map(d=>Number(d[yField]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)));const yScale=d3.scaleLinear().domain([-maxAbs,maxAbs]).range([dims.innerHeight,0]).nice();const midY=yScale(0);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);const barWidth=xScale.bandwidth();const needsRotation=shouldRotateLabels(categories,barWidth);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);g.append(\"line\").attr(\"x1\",0).attr(\"y1\",midY).attr(\"x2\",dims.innerWidth).attr(\"y2\",midY).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",1.5);const maxBarWidth=Math.min(80,dims.innerWidth*.3);const clampedBarWidth=Math.min(xScale.bandwidth(),maxBarWidth);const barXOffset=(xScale.bandwidth()-clampedBarWidth)/2;g.selectAll(\".bar-hover-target\").data(data).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(String(d[xField]))).attr(\"y\",0).attr(\"width\",xScale.bandwidth()).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd[xField]===d[xField]).attr(\"opacity\",.8);const val=Number(d[yField]);showTooltip(tooltip,`<strong>${d[xField]}</strong><br/>${yField}: ${val>=0?\"+\":\"\"}${formatValue(val)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(data).join(\"rect\").attr(\"class\",\"bar\").attr(\"x\",d=>xScale(String(d[xField]))+barXOffset).attr(\"width\",clampedBarWidth).attr(\"y\",d=>{const val=Number(d[yField]);return val>=0?yScale(val):midY}).attr(\"height\",d=>Math.max(2,Math.abs(yScale(Number(d[yField]))-midY))).attr(\"fill\",d=>Number(d[yField])>=0?\"#10b981\":\"#ef4444\").attr(\"rx\",3).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,clampedBarWidth,false);if(showLabels){g.selectAll(\".bar-label\").data(data).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>xScale(String(d[xField]))+xScale.bandwidth()/2).attr(\"y\",d=>{const val=Number(d[yField]);const barHeight=Math.abs(yScale(val)-midY);if(val>=0){return barHeight<20?yScale(val)-6:yScale(val)+14}else{return barHeight<20?midY+barHeight+14:midY+barHeight-6}}).attr(\"text-anchor\",\"middle\").attr(\"fill\",d=>{const barHeight=Math.abs(yScale(Number(d[yField]))-midY);return barHeight<20?TEXT_MUTED:\"#ffffff\"}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").style(\"opacity\",1).text(d=>{const val=Number(d[yField]);return(val>=0?\"+\":\"\")+formatValue(val)})}}return __toCommonJS(diverging_bar_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
18
|
+
export const donutBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var donut_render_exports={};__export(donut_render_exports,{renderChart:()=>renderDonut});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderDonut(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const innerRadiusRatio=config.innerRadius??.55;const showLabels=config.showLabels!==false;const showPercentages=config.showPercentages!==false;const centerLabel=config.centerLabel||\"\";const startAngle=(config.startAngle??0)*(Math.PI/180);const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>200&&containerWidth>250;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";chartWrapper.style.position=\"relative\";container.appendChild(chartWrapper);const total=data.reduce((s,d)=>s+(Math.abs(Number(d[valueField]))||0),0);const rawValues=data.map(d=>Number(d[valueField])||0).filter(v=>v>0);const maxVal=rawValues.length>0?Math.max(...rawValues):0;const minVisible=maxVal*.02;const clampVal=v=>v>0&&v<minVisible?minVisible:v;const items=data.filter(d=>Number(d[valueField])>0).map(d=>({category:String(d[categoryField]),value:clampVal(Number(d[valueField])||0),percentage:total>0?(Number(d[valueField])||0)/total*100:0}));if(isAllZeros(data,valueField)){const emptyDiv=document.createElement(\"div\");emptyDiv.style.cssText=`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: ${TEXT_MUTED};\n font-size: 14px;\n font-family: Inter, system-ui, sans-serif;\n `;emptyDiv.textContent=\"All values are zero\";chartWrapper.appendChild(emptyDiv);return}const colorScale=buildColorScale(encoding.color,data);if(showLegend){const legendDiv=createLegend(items.map(item=>({label:String(item.category),color:colorScale(item.category),extra:`${item.percentage.toFixed(1)}%`})));container.appendChild(legendDiv)}const titleHeight=spec.title?32:0;const wrapperWidth=chartWrapper.clientWidth||containerWidth;const wrapperHeight=(chartWrapper.clientHeight||containerHeight)-(showLegend?40:0);const svg=d3.select(chartWrapper).append(\"svg\").attr(\"width\",wrapperWidth).attr(\"height\",wrapperHeight).style(\"background\",\"none\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",wrapperWidth/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,wrapperWidth-20)}const tooltip=createTooltip(container);const availableHeight=wrapperHeight-titleHeight-20;const availableWidth=wrapperWidth-40;const radius=Math.max(40,Math.min(availableWidth,availableHeight)/2);const innerRadius=radius*innerRadiusRatio;const cx=wrapperWidth/2;const cy=titleHeight+10+availableHeight/2;const pie=d3.pie().value(d=>d.value).sort(null).startAngle(startAngle).endAngle(startAngle+Math.PI*2).padAngle(.01);const arc=d3.arc().innerRadius(innerRadius).outerRadius(radius).cornerRadius(3);const arcHover=d3.arc().innerRadius(innerRadius).outerRadius(radius+6).cornerRadius(3);const arcs=pie(items);const g=svg.append(\"g\").attr(\"transform\",`translate(${cx},${cy})`);g.selectAll(\".donut-slice\").data(arcs).join(\"path\").attr(\"class\",\"donut-slice\").attr(\"d\",arc).attr(\"fill\",d=>colorScale(d.data.category)).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");g.selectAll(\".donut-hover\").data(arcs).join(\"path\").attr(\"class\",\"donut-hover\").attr(\"d\",arc).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".donut-slice\").attr(\"opacity\",s=>s.data.category===d.data.category?1:.3);d3.select(g.selectAll(\".donut-slice\").nodes()[d.index]).attr(\"d\",arcHover);showTooltip(tooltip,`<strong>${d.data.category}</strong><br/>${formatValue(d.data.value)}<br/>${d.data.percentage.toFixed(1)}%`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".donut-slice\").attr(\"opacity\",1).attr(\"d\",arc);hideTooltip(tooltip)});const labelMinRadius=80;if(showLabels&&items.length<=8&&radius>=labelMinRadius){const labelArc=d3.arc().innerRadius(radius*.75).outerRadius(radius*.75);g.selectAll(\".donut-label\").data(arcs).join(\"text\").attr(\"class\",\"donut-label\").attr(\"transform\",d=>`translate(${labelArc.centroid(d)})`).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",d=>contrastText(colorScale(d.data.category))).attr(\"font-size\",()=>{const size=Math.max(9,Math.min(12,radius/12));return size+\"px\"}).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"pointer-events\",\"none\").text(d=>{const angle=d.endAngle-d.startAngle;if(angle<.25)return\"\";if(showPercentages)return d.data.percentage.toFixed(0)+\"%\";return formatValue(d.data.value)})}if(centerLabel&&innerRadiusRatio>0){svg.append(\"text\").attr(\"x\",cx).attr(\"y\",cy).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",Math.max(12,Math.min(20,innerRadius*.4))+\"px\").attr(\"font-weight\",\"700\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(centerLabel)}}return __toCommonJS(donut_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
19
|
+
export const funnelBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var funnel_render_exports={};__export(funnel_render_exports,{renderChart:()=>renderFunnel});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderFunnel(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.y?.field||encoding.color?.field;const valueField=config.valueField||encoding.x?.field;const showConversionRates=config.showConversionRates!==false;const style=config.style||\"tapered\";if(!data||data.length===0){container.innerHTML='<p style=\"color:#ef4444;padding:20px;\">No data provided</p>';return}if(!categoryField||!valueField){container.innerHTML='<p style=\"color:#ef4444;padding:20px;\">Funnel requires categoryField and valueField</p>';return}const MAX_STAGES=12;let displayData=data;let truncated=false;if(data.length>MAX_STAGES){displayData=data.slice(0,MAX_STAGES);truncated=true}const stages=displayData.map((d,i)=>{const value=Number(d[valueField])||0;const prevValue=i>0?Number(displayData[i-1][valueField])||0:null;return{label:String(d[categoryField]),value,percentage:0,conversionFromPrev:prevValue!==null&&prevValue>0?value/prevValue*100:null}});const maxValue=d3.max(stages,s=>s.value)||1;stages.forEach(s=>{s.percentage=s.value/maxValue*100});const colorScale=buildColorScale(encoding.color,data);const sideMargin=140;const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex:1;min-height:0;\";container.style.cssText+=\"display:flex;flex-direction:column;\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{top:40,left:sideMargin,right:sideMargin,bottom:20});const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){renderEmptyState(g,dims);return}const barHeight=Math.max(16,dims.innerHeight/stages.length);const totalHeight=barHeight*stages.length;const MIN_STAGE_WIDTH=4;const _widthScaleBase=d3.scaleLinear().domain([0,maxValue]).range([0,dims.innerWidth]);const widthScale=v=>Math.max(_widthScaleBase(v),v>0?MIN_STAGE_WIDTH:0);const centerX=dims.innerWidth/2;const isSmall=barHeight<28;const labelFontSize=isSmall?\"10px\":\"12px\";const cornerRadius=6;stages.forEach((stage,i)=>{const yOffset=i*barHeight;g.append(\"rect\").attr(\"class\",\"funnel-hover-target\").attr(\"x\",-dims.margin.left).attr(\"y\",yOffset).attr(\"width\",dims.innerWidth+dims.margin.left+dims.margin.right).attr(\"height\",barHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){g.selectAll(\".funnel-stage\").attr(\"opacity\",(_,j)=>j===i?1:.3);const html=buildTooltipHtml(stage,i,stages);showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".funnel-stage\").attr(\"opacity\",1);hideTooltip(tooltip)})});if(stages.length===1){const stage=stages[0];const stageColor=colorScale(stage.label);const rectWidth=Math.min(dims.innerWidth*.6,widthScale(stage.value));const rectHeight=Math.min(barHeight,dims.innerHeight*.5);const yOffset=(dims.innerHeight-rectHeight)/2;g.append(\"rect\").attr(\"class\",\"funnel-stage\").attr(\"x\",centerX-rectWidth/2).attr(\"y\",yOffset).attr(\"width\",rectWidth).attr(\"height\",rectHeight).attr(\"fill\",stageColor).attr(\"stroke\",\"#1f2937\").attr(\"stroke-width\",1).attr(\"rx\",cornerRadius).attr(\"pointer-events\",\"none\")}else if(style===\"tapered\"){const path=d3.path();const stageWidths=stages.map(s=>widthScale(s.value));stages.forEach((stage,i)=>{const yTop=i*barHeight;const yBot=yTop+barHeight;const topHalf=stageWidths[i]/2;const botHalf=i<stages.length-1?stageWidths[i+1]/2:topHalf*.3;const stageColor=colorScale(stage.label);const isFirst=i===0;const isLast=i===stages.length-1;const r=cornerRadius;const trapPath=d3.path();if(isFirst){trapPath.moveTo(centerX-topHalf+r,yTop);trapPath.lineTo(centerX+topHalf-r,yTop);trapPath.quadraticCurveTo(centerX+topHalf,yTop,centerX+topHalf,yTop+r);trapPath.lineTo(centerX+botHalf,yBot);trapPath.lineTo(centerX-botHalf,yBot);trapPath.lineTo(centerX-topHalf,yTop+r);trapPath.quadraticCurveTo(centerX-topHalf,yTop,centerX-topHalf+r,yTop)}else if(isLast){trapPath.moveTo(centerX-topHalf,yTop);trapPath.lineTo(centerX+topHalf,yTop);trapPath.lineTo(centerX+botHalf,yBot-r);trapPath.quadraticCurveTo(centerX+botHalf,yBot,centerX+botHalf-r,yBot);trapPath.lineTo(centerX-botHalf+r,yBot);trapPath.quadraticCurveTo(centerX-botHalf,yBot,centerX-botHalf,yBot-r);trapPath.lineTo(centerX-topHalf,yTop)}else{trapPath.moveTo(centerX-topHalf,yTop);trapPath.lineTo(centerX+topHalf,yTop);trapPath.lineTo(centerX+botHalf,yBot);trapPath.lineTo(centerX-botHalf,yBot);trapPath.closePath()}g.append(\"path\").attr(\"class\",\"funnel-stage\").attr(\"d\",trapPath.toString()).attr(\"fill\",stageColor).attr(\"stroke\",\"#1f2937\").attr(\"stroke-width\",1).attr(\"pointer-events\",\"none\")})}else{stages.forEach((stage,i)=>{const yOffset=i*barHeight;const currentWidth=widthScale(stage.value);const halfWidth=currentWidth/2;const stageColor=colorScale(stage.label);g.append(\"rect\").attr(\"class\",\"funnel-stage\").attr(\"x\",centerX-halfWidth).attr(\"y\",yOffset).attr(\"width\",currentWidth).attr(\"height\",barHeight).attr(\"fill\",stageColor).attr(\"stroke\",\"#1f2937\").attr(\"stroke-width\",1).attr(\"rx\",i===0||i===stages.length-1?3:0).attr(\"pointer-events\",\"none\")})}const showValueInside=barHeight>=32;stages.forEach((stage,i)=>{const isSingleStage=stages.length===1;const singleRectHeight=isSingleStage?Math.min(barHeight,dims.innerHeight*.5):barHeight;const yOffset=isSingleStage?(dims.innerHeight-singleRectHeight)/2:i*barHeight;const labelY=yOffset+singleRectHeight/2;const stageColor=colorScale(stage.label);const stageWidth=widthScale(stage.value);const valueText=formatValue(stage.value);const pctText=stage.percentage<100?` (${stage.percentage.toFixed(1)}%)`:\"\";g.append(\"text\").attr(\"x\",dims.innerWidth+14).attr(\"y\",labelY).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",\"start\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",labelFontSize).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"500\").attr(\"pointer-events\",\"none\").text(truncateLabel(stage.label,18));g.append(\"text\").attr(\"x\",dims.innerWidth+14).attr(\"y\",labelY+(isSmall?11:13)).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",\"start\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",isSmall?\"9px\":\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(valueText+pctText);if(showValueInside&&stageWidth>60){g.append(\"text\").attr(\"x\",centerX).attr(\"y\",labelY).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",\"middle\").attr(\"fill\",contrastText(stageColor)).attr(\"font-size\",\"12px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(valueText)}if(truncated&&i===stages.length-1){g.append(\"text\").attr(\"x\",centerX).attr(\"y\",yOffset+singleRectHeight+14).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-style\",\"italic\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(`Showing ${stages.length} of ${data.length} stages`)}if(showConversionRates&&stage.conversionFromPrev!==null&&i>0){const borderY=yOffset;const deltaText=`${stage.conversionFromPrev.toFixed(1)}%`;const pillW=deltaText.length*6.5+12;const pillH=16;g.append(\"rect\").attr(\"x\",centerX-pillW/2).attr(\"y\",borderY-pillH/2).attr(\"width\",pillW).attr(\"height\",pillH).attr(\"rx\",4).attr(\"fill\",\"#333\").attr(\"pointer-events\",\"none\");g.append(\"text\").attr(\"x\",centerX).attr(\"y\",borderY).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(deltaText)}})}function buildTooltipHtml(stage,index,stages){let html=`<strong>${stage.label}</strong><br/>Value: ${formatValue(stage.value)}`;if(stage.percentage<100){html+=`<br/>Of top: ${stage.percentage.toFixed(1)}%`}if(stage.conversionFromPrev!==null){html+=`<br/>From prev: ${stage.conversionFromPrev.toFixed(1)}%`}if(index===0&&stages.length>1){const lastStage=stages[stages.length-1];const overallConversion=stage.value>0?lastStage.value/stage.value*100:0;html+=`<br/>Overall: ${overallConversion.toFixed(1)}% to end`}return html}return __toCommonJS(funnel_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
20
|
+
export const groupedBarBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var grouped_bar_render_exports={};__export(grouped_bar_render_exports,{renderChart:()=>renderGroupedBar});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderGroupedBar(container,spec){const{config,encoding,data}=spec;let isHorizontal=config.orientation===\"horizontal\";const categoryField=config.categoryField||encoding.x?.field;const seriesField=config.seriesField||encoding.color?.field;const valueField=config.valueField||encoding.y?.field;if(!categoryField||!valueField)return;let series;let pivoted;if(seriesField){series=[...new Set(data.map(d=>String(d[seriesField])))];pivoted={};for(const d of data){const cat=String(d[categoryField]);if(!pivoted[cat])pivoted[cat]={};pivoted[cat][String(d[seriesField])]=Number(d[valueField])||0}}else{const numericFields=Object.keys(data[0]||{}).filter(k=>k!==categoryField&&typeof data[0][k]===\"number\");series=numericFields.length>1?numericFields:[valueField];pivoted={};for(const d of data){const cat=String(d[categoryField]);pivoted[cat]={};for(const s of series){pivoted[cat][s]=Number(d[s])||0}}}let categories=[...new Set(data.map(d=>String(d[categoryField])))];if(config.sortBy===\"value\"){const order=config.sortOrder===\"ascending\"?1:-1;categories.sort((a,b)=>{const totalA=series.reduce((sum,s)=>sum+(pivoted[a]?.[s]??0),0);const totalB=series.reduce((sum,s)=>sum+(pivoted[b]?.[s]??0),0);return order*(totalA-totalB)})}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;categories.sort((a,b)=>order*a.localeCompare(b,void 0,{sensitivity:\"base\",numeric:true}))}if(!isHorizontal&&categories.length*series.length>20){isHorizontal=true}let minVal=0;let maxVal=0;for(const cat of categories){for(const s of series){const v=pivoted[cat]?.[s]??0;if(v<minVal)minVal=v;if(v>maxVal)maxVal=v}}if(minVal===0&&maxVal===0){container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";const chartWrapper2=document.createElement(\"div\");chartWrapper2.style.flex=\"1\";container.appendChild(chartWrapper2);const{svg,g,dims}=createSvg(chartWrapper2,spec);svg.style(\"background\",\"none\");renderEmptyState(g,dims);return}const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>250&&containerWidth>350;const colorScale=buildColorScale(encoding.color,data,seriesField||valueField);container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);let legendDiv=null;if(showLegend){legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}const tooltip=createTooltip(container);if(isHorizontal){const labels=categories;const leftMargin=calculateLeftMargin(labels);const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin,bottom:40,right:30,top:40});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const yScale=d3.scaleBand().domain(categories).range([0,dims.innerHeight]).padding(.2);const maxGroupHeight=Math.min(120,dims.innerHeight*.4);const groupHeight=Math.min(yScale.bandwidth(),maxGroupHeight);const groupYOffset=(yScale.bandwidth()-groupHeight)/2;const yInner=d3.scaleBand().domain(series).range([0,groupHeight]).padding(.05);const xScale=d3.scaleLinear().domain([Math.min(0,minVal),Math.max(0,maxVal)]).range([0,dims.innerWidth]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(10).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);g.selectAll(\".group-hover-target\").data(categories).join(\"rect\").attr(\"class\",\"group-hover-target\").attr(\"y\",cat=>yScale(cat)).attr(\"x\",0).attr(\"height\",yScale.bandwidth()).attr(\"width\",dims.innerWidth).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,cat){g.selectAll(`.bar[data-category=\"${CSS.escape(cat)}\"]`).attr(\"opacity\",.8);let html=`<strong>${cat}</strong>`;series.forEach(s=>{const val=pivoted[cat]?.[s]??0;const swatch=`<span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${colorScale(s)};margin-right:4px\"></span>`;html+=`<br/>${swatch}${s}: ${formatValue(val)}`});showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});for(const cat of categories){for(const s of series){const val=pivoted[cat]?.[s]??0;g.append(\"rect\").attr(\"class\",\"bar\").attr(\"data-category\",cat).attr(\"y\",(yScale(cat)??0)+groupYOffset+(yInner(s)??0)).attr(\"x\",val>=0?xScale(0):xScale(val)).attr(\"height\",yInner.bandwidth()).attr(\"width\",Math.max(2,Math.abs(xScale(val)-xScale(0)))).attr(\"fill\",colorScale(s)).attr(\"rx\",2).attr(\"pointer-events\",\"none\")}}addSortControls(svg,container,spec,dims,renderGroupedBar)}else{const estBarWidth=(containerWidth-130)/categories.length;const willRotate=shouldRotateLabels(categories,estBarWidth);const bottomMargin=calculateBottomMargin(categories,willRotate);const{svg,g,dims}=createSvg(chartWrapper,spec,{bottom:bottomMargin,left:70,right:30,top:40});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const xScale=d3.scaleBand().domain(categories).range([0,dims.innerWidth]).padding(.2);const maxGroupWidth=Math.min(120,dims.innerWidth*.4);const groupWidth=Math.min(xScale.bandwidth(),maxGroupWidth);const groupXOffset=(xScale.bandwidth()-groupWidth)/2;const xInner=d3.scaleBand().domain(series).range([0,groupWidth]).padding(.05);const yScale=d3.scaleLinear().domain([Math.min(0,minVal),Math.max(0,maxVal)]).range([dims.innerHeight,0]).nice();const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);if(willRotate){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);g.selectAll(\".group-hover-target\").data(categories).join(\"rect\").attr(\"class\",\"group-hover-target\").attr(\"x\",cat=>xScale(cat)).attr(\"y\",0).attr(\"width\",xScale.bandwidth()).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,cat){g.selectAll(`.bar[data-category=\"${CSS.escape(cat)}\"]`).attr(\"opacity\",.8);let html=`<strong>${cat}</strong>`;series.forEach(s=>{const val=pivoted[cat]?.[s]??0;const swatch=`<span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${colorScale(s)};margin-right:4px\"></span>`;html+=`<br/>${swatch}${s}: ${formatValue(val)}`});showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});for(const cat of categories){for(const s of series){const val=pivoted[cat]?.[s]??0;const barHeight=Math.max(2,Math.abs(yScale(0)-yScale(val)));g.append(\"rect\").attr(\"class\",\"bar\").attr(\"data-category\",cat).attr(\"x\",(xScale(cat)??0)+groupXOffset+(xInner(s)??0)).attr(\"y\",val>=0?yScale(val):yScale(0)).attr(\"width\",xInner.bandwidth()).attr(\"height\",barHeight).attr(\"fill\",colorScale(s)).attr(\"rx\",2).attr(\"pointer-events\",\"none\")}}const showLabels=shouldShowValueLabels(config,xInner.bandwidth(),false);if(showLabels){for(const cat of categories){for(const s of series){const val=pivoted[cat]?.[s]??0;const barHeight=Math.abs(yScale(0)-yScale(val));const barX=(xScale(cat)??0)+groupXOffset+(xInner(s)??0)+xInner.bandwidth()/2;const yPos=val>=0?yScale(val):yScale(0);const inside=barHeight>=20;g.append(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",barX).attr(\"y\",inside?yPos+14:yPos-6).attr(\"text-anchor\",\"middle\").attr(\"fill\",inside?\"#ffffff\":TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(val))}}}addSortControls(svg,container,spec,dims,renderGroupedBar)}}return __toCommonJS(grouped_bar_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
21
|
+
export const heatmapBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var heatmap_render_exports={};__export(heatmap_render_exports,{renderChart:()=>renderHeatmap});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderHeatmap(container,spec){const{config,encoding,data}=spec;const rowField=config.rowField||encoding.y?.field||Object.keys(data[0])[0];const colField=config.colField||encoding.x?.field||Object.keys(data[0])[1];const valueField=config.valueField||encoding.color?.field||Object.keys(data[0])[2];let rows=[...new Set(data.map(d=>d[rowField]))];let cols=[...new Set(data.map(d=>d[colField]))];if(config.sortRows===\"ascending\")rows.sort((a,b)=>String(a).localeCompare(String(b)));if(config.sortRows===\"descending\")rows.sort((a,b)=>String(b).localeCompare(String(a)));if(config.sortCols===\"ascending\")cols.sort((a,b)=>String(a).localeCompare(String(b)));if(config.sortCols===\"descending\")cols.sort((a,b)=>String(b).localeCompare(String(a)));const rowLabels=rows.map(r=>String(r));const colLabels=cols.map(c=>String(c));const leftMargin=calculateLeftMargin(rowLabels);const colBandEstimate=(container.clientWidth||800)/Math.max(cols.length,1);const rotateColLabels=shouldRotateLabels(colLabels,colBandEstimate);const bottomMargin=calculateBottomMargin(colLabels,rotateColLabels);container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin,bottom:bottomMargin});const tooltip=createTooltip(container);const xScale=d3.scaleBand().domain(cols).range([0,dims.innerWidth]).padding(0);const yScale=d3.scaleBand().domain(rows).range([0,dims.innerHeight]).padding(0);const values=data.map(d=>Number(d[valueField]));const extent=d3.extent(values);let colorScale;const palette=encoding.color?.palette;if(palette&&[\"blueRed\",\"greenPurple\",\"tealOrange\",\"redGreen\"].includes(palette)){const colors=diverging[palette];if(colors){const maxAbs=Math.max(Math.abs(extent[0]),Math.abs(extent[1]))||1;const mid=Math.floor(colors.length/2);colorScale=d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([colors[0],colors[mid],colors[colors.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}}if(!colorScale&&palette&&[\"blue\",\"green\",\"purple\",\"warm\"].includes(palette)){const colors=sequential[palette];if(colors){colorScale=d3.scaleLinear().domain(extent).range([colors[0],colors[colors.length-1]]).interpolate(d3.interpolateRgb)}}if(!colorScale){const hasMixedSign=extent[0]<0&&extent[1]>0;const allNegative=extent[1]<=0&&extent[0]<0;if(hasMixedSign){const colors=diverging.blueRed;const maxAbs=Math.max(Math.abs(extent[0]),Math.abs(extent[1]))||1;const mid=Math.floor(colors.length/2);colorScale=d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([colors[0],colors[mid],colors[colors.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}else if(allNegative){const warmStops=sequential.warm;colorScale=d3.scaleLinear().domain([extent[0],extent[1]]).range([warmStops[1],warmStops[7]]).interpolate(d3.interpolateRgb).clamp(true)}else{const goldStops=[\"#2a1f0e\",\"#4a3520\",\"#7a5c2e\",\"#b8860b\",\"#c9a84c\",\"#dbc67e\",\"#f0e4b5\"];const t=d3.scaleLinear().domain([0,goldStops.length-1]).range(extent);const stopDomain=goldStops.map((_,i)=>t(i));colorScale=d3.scaleLinear().domain(stopDomain).range(goldStops).interpolate(d3.interpolateRgb).clamp(true)}}const lookup=new Map;for(const d of data){lookup.set(`${d[rowField]}__${d[colField]}`,Number(d[valueField]))}const cellWidth=xScale.bandwidth();const cellHeight=yScale.bandwidth();const showValues=config.showValues??(cellWidth>=30&&cellHeight>=20);g.selectAll(\".heatmap-cell\").data(data).join(\"rect\").attr(\"class\",\"heatmap-cell\").attr(\"x\",d=>xScale(d[colField])).attr(\"y\",d=>yScale(d[rowField])).attr(\"width\",cellWidth).attr(\"height\",cellHeight).attr(\"fill\",d=>colorScale(Number(d[valueField]))).on(\"mouseenter\",function(event,d){d3.select(this).attr(\"opacity\",.8);const html=`<strong>${rowField}:</strong> ${d[rowField]}<br/><strong>${colField}:</strong> ${d[colField]}<br/><strong>${valueField}:</strong> ${formatValue(Number(d[valueField]))}`;showTooltip(tooltip,html,event)}).on(\"mousemove\",function(event){positionTooltip(tooltip,event)}).on(\"mouseleave\",function(){d3.select(this).attr(\"opacity\",1);hideTooltip(tooltip)});rows.forEach(row=>{g.append(\"line\").attr(\"x1\",0).attr(\"x2\",dims.innerWidth).attr(\"y1\",yScale(row)).attr(\"y2\",yScale(row)).attr(\"stroke\",\"#000\").attr(\"stroke-width\",.5).attr(\"pointer-events\",\"none\")});g.append(\"line\").attr(\"x1\",0).attr(\"x2\",dims.innerWidth).attr(\"y1\",dims.innerHeight).attr(\"y2\",dims.innerHeight).attr(\"stroke\",\"#000\").attr(\"stroke-width\",.5).attr(\"pointer-events\",\"none\");cols.forEach(col=>{g.append(\"line\").attr(\"x1\",xScale(col)).attr(\"x2\",xScale(col)).attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",\"#000\").attr(\"stroke-width\",.5).attr(\"pointer-events\",\"none\")});g.append(\"line\").attr(\"x1\",dims.innerWidth).attr(\"x2\",dims.innerWidth).attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",\"#000\").attr(\"stroke-width\",.5).attr(\"pointer-events\",\"none\");if(showValues){const fontSize=Math.min(11,Math.max(8,Math.min(cellWidth,cellHeight)*.35));g.selectAll(\".cell-label\").data(data).join(\"text\").attr(\"class\",\"cell-label\").attr(\"x\",d=>xScale(d[colField])+cellWidth/2).attr(\"y\",d=>yScale(d[rowField])+cellHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",d=>contrastText(colorScale(Number(d[valueField])))).attr(\"font-size\",`${fontSize}px`).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>formatValue(Number(d[valueField])))}const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(6));yAxis.select(\".domain\").remove();yAxis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(function(){return truncateLabel(d3.select(this).text(),20)});const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8));xAxis.select(\".domain\").remove();xAxis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(function(){return truncateLabel(d3.select(this).text(),16)});if(rotateColLabels){xAxis.selectAll(\".tick text\").attr(\"text-anchor\",\"end\").attr(\"transform\",\"rotate(-35)\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.3em\")}const legendDiv=document.createElement(\"div\");legendDiv.style.cssText=\"display: flex; align-items: center; justify-content: center; gap: 8px; padding: 8px 10px 4px; font-family: Inter, system-ui, sans-serif; font-size: 10px; color: #9ca3af;\";const minLabel=document.createElement(\"span\");minLabel.textContent=formatValue(extent[0]);const gradBar=document.createElement(\"div\");gradBar.style.cssText=\"width: 160px; height: 10px; border-radius: 3px;\";const stops=[];for(let i=0;i<=10;i++){const val=extent[0]+i/10*(extent[1]-extent[0]);stops.push(colorScale(val))}gradBar.style.background=`linear-gradient(to right, ${stops.join(\", \")})`;const maxLabel=document.createElement(\"span\");maxLabel.textContent=formatValue(extent[1]);legendDiv.appendChild(minLabel);legendDiv.appendChild(gradBar);legendDiv.appendChild(maxLabel);container.appendChild(legendDiv)}return __toCommonJS(heatmap_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
22
|
+
export const histogramBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var histogram_render_exports={};__export(histogram_render_exports,{renderChart:()=>renderHistogram});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function getSequentialPalette(name){const palettes={blue:[...sequential.blue],green:[...sequential.green],purple:[...sequential.purple],warm:[...sequential.warm]};return palettes[name]||null}function buildBinColorFn(colorEncoding,xDomain){if(!colorEncoding){return()=>categorical[0]}if(colorEncoding.highlight){const targetValues=colorEncoding.highlight.values.map(Number);const highlightColors=Array.isArray(colorEncoding.highlight.color)?colorEncoding.highlight.color:colorEncoding.highlight.color?[colorEncoding.highlight.color]:[categorical[0]];const mutedColor=colorEncoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=colorEncoding.highlight.mutedOpacity??1;const mutedFill=mutedOpacity<1?(()=>{const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`})():mutedColor;return(x0,x1)=>{for(let i=0;i<targetValues.length;i++){const v=targetValues[i];if(v>=x0&&v<x1){return highlightColors[i%highlightColors.length]}}return mutedFill}}if(colorEncoding.palette){const palette=getSequentialPalette(colorEncoding.palette);if(palette){const scale=d3.scaleLinear().domain([xDomain[0],xDomain[1]]).range([palette[0],palette[palette.length-1]]).interpolate(d3.interpolateRgb).clamp(true);return(x0,x1)=>scale((x0+x1)/2)}}return()=>categorical[0]}function renderHistogram(container,spec){const{config,encoding,data}=spec;const xField=encoding.x?.field||\"binMid\";const hasBins=data[0]?.binStart!==void 0;if(hasBins){renderPreBinnedHistogram(container,spec)}else{renderRawHistogram(container,spec,xField)}}function renderPreBinnedHistogram(container,spec){const{data,encoding,config}=spec;const{svg,g,dims}=createSvg(container,spec,{right:30});const tooltip=createTooltip(container);const xMin=d3.min(data,d=>d.binStart);const xMax=d3.max(data,d=>d.binEnd);const xScale=d3.scaleLinear().domain([xMin,xMax]).range([0,dims.innerWidth]);const yScale=d3.scaleLinear().domain([0,d3.max(data,d=>d.count)]).range([dims.innerHeight,0]).nice();const binColor=buildBinColorFn(encoding.color,[xMin,xMax]);const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const binWidth=xScale(data[0].binEnd)-xScale(data[0].binStart);g.selectAll(\".bar-hover-target\").data(data).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(d.binStart)).attr(\"y\",0).attr(\"width\",binWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd.binStart===d.binStart).attr(\"opacity\",.8);showTooltip(tooltip,`<strong>${d.binLabel||formatValue(d.binStart)+\" \\u2013 \"+formatValue(d.binEnd)}</strong><br/>Count: ${formatValue(d.count)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(data).join(\"rect\").attr(\"class\",\"bar\").attr(\"x\",d=>xScale(d.binStart)+1).attr(\"y\",d=>yScale(d.count)).attr(\"width\",Math.max(binWidth-2,1)).attr(\"height\",d=>dims.innerHeight-yScale(d.count)).attr(\"fill\",d=>binColor(d.binStart,d.binEnd)).attr(\"rx\",1).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,binWidth,false);if(showLabels){g.selectAll(\".bar-label\").data(data).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>xScale(d.binStart)+binWidth/2).attr(\"y\",d=>{const barHeight=dims.innerHeight-yScale(d.count);const yPos=yScale(d.count);return barHeight<20?yPos-6:yPos+14}).attr(\"text-anchor\",\"middle\").attr(\"fill\",d=>{const barHeight=dims.innerHeight-yScale(d.count);return barHeight<20?TEXT_MUTED:\"#ffffff\"}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>formatValue(d.count))}drawStatLines(g,xScale,dims.innerHeight,config)}function renderRawHistogram(container,spec,xField){const{data,encoding,config}=spec;const values=data.map(d=>Number(d[xField])).filter(v=>!isNaN(v));const binCount=config.binCount||Math.ceil(Math.log2(values.length)+1);const{svg,g,dims}=createSvg(container,spec,{right:30});const tooltip=createTooltip(container);if(values.every(v=>v===0)){renderEmptyState(g,dims);return}const xScale=d3.scaleLinear().domain(d3.extent(values)).range([0,dims.innerWidth]).nice();const histogram=d3.bin().domain(xScale.domain()).thresholds(binCount);const bins=histogram(values);const yScale=d3.scaleLinear().domain([0,d3.max(bins,b=>b.length)]).range([dims.innerHeight,0]).nice();const xDom=xScale.domain();const binColor=buildBinColorFn(encoding.color,xDom);const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);g.selectAll(\".bar-hover-target\").data(bins).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(d.x0)).attr(\"y\",0).attr(\"width\",d=>Math.max(xScale(d.x1)-xScale(d.x0),1)).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".bar\").filter(bd=>bd.x0===d.x0).attr(\"opacity\",.8);showTooltip(tooltip,`<strong>${formatValue(d.x0)} \\u2013 ${formatValue(d.x1)}</strong><br/>Count: ${formatValue(d.length)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".bar\").data(bins).join(\"rect\").attr(\"class\",\"bar\").attr(\"x\",d=>xScale(d.x0)+1).attr(\"y\",d=>yScale(d.length)).attr(\"width\",d=>Math.max(xScale(d.x1)-xScale(d.x0)-2,1)).attr(\"height\",d=>dims.innerHeight-yScale(d.length)).attr(\"fill\",d=>binColor(d.x0,d.x1)).attr(\"rx\",1).attr(\"pointer-events\",\"none\");const avgBinWidth=bins.length>0?Math.max(...bins.map(b=>xScale(b.x1)-xScale(b.x0))):0;const showLabels=shouldShowValueLabels(config,avgBinWidth,false);if(showLabels){g.selectAll(\".bar-label\").data(bins).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>(xScale(d.x0)+xScale(d.x1))/2).attr(\"y\",d=>{const barHeight=dims.innerHeight-yScale(d.length);const yPos=yScale(d.length);return barHeight<20?yPos-6:yPos+14}).attr(\"text-anchor\",\"middle\").attr(\"fill\",d=>{const barHeight=dims.innerHeight-yScale(d.length);return barHeight<20?TEXT_MUTED:\"#ffffff\"}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>d.length>0?formatValue(d.length):\"\")}const mean=config.mean??values.reduce((a,b)=>a+b,0)/values.length;const sorted=[...values].sort((a,b)=>a-b);const median=config.median??sorted[Math.floor(sorted.length/2)];drawStatLines(g,xScale,dims.innerHeight,{...config,mean,median})}function drawStatLines(g,xScale,innerHeight,config){if(config.showMean&&config.mean!=null){drawStatLine(g,xScale(config.mean),innerHeight,\"#f59e0b\",\"6,3\",`Mean: ${formatValue(config.mean)}`,14)}if(config.showMedian&&config.median!=null){drawStatLine(g,xScale(config.median),innerHeight,\"#10b981\",\"3,3\",`Median: ${formatValue(config.median)}`,30)}}function drawStatLine(g,x,height,color,dashArray,label,labelY){g.append(\"line\").attr(\"x1\",x).attr(\"y1\",0).attr(\"x2\",x).attr(\"y2\",height).attr(\"stroke\",color).attr(\"stroke-width\",2).attr(\"stroke-dasharray\",dashArray).attr(\"pointer-events\",\"none\");g.append(\"text\").attr(\"x\",x+6).attr(\"y\",labelY).attr(\"fill\",color).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(label)}return __toCommonJS(histogram_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
23
|
+
export const horizonChartBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var horizon_chart_render_exports={};__export(horizon_chart_render_exports,{renderChart:()=>renderHorizonChart});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}var POSITIVE_RAMP=[\"#c6dbef\",\"#6baed6\",\"#2171b5\",\"#08306b\"];var NEGATIVE_RAMP=[\"#fcbba1\",\"#fb6a4a\",\"#cb181d\",\"#67000d\"];function renderHorizonChart(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field||null;const numBands=Math.max(2,Math.min(4,config.bands??3));const mode=config.mode??\"mirror\";const rowGap=2;const parsedData=data.map(d=>({...d,_date:parseDate(d[timeField]),_value:Number(d[valueField])})).filter(d=>d._date!==null&&!isNaN(d._value));const seriesNames=seriesField?[...new Set(parsedData.map(d=>d[seriesField]))].sort():[\"all\"];const isSingleSeries=!seriesField||seriesNames.length<=1;const labelWidth=isSingleSeries?16:calculateLabelWidth(seriesNames);const topMargin=spec.title?36:12;const bottomMargin=30;const rightMargin=30;const W=container.clientWidth||800;const H=container.clientHeight||400;const chartW=W-labelWidth-rightMargin;const availH=H-topMargin-bottomMargin;const rowH=Math.max(10,(availH-(seriesNames.length-1)*rowGap)/seriesNames.length);container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const svg=d3.select(container).append(\"svg\").attr(\"width\",W).attr(\"height\",H).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",W/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,W-20)}const allDates=parsedData.map(d=>d._date);const xExtent=d3.extent(allDates);const xScale=d3.scaleTime().domain(xExtent).range([0,chartW]);const tooltip=createTooltip(container);if(parsedData.every(d=>d._value===0)){svg.append(\"text\").attr(\"x\",W/2).attr(\"y\",H/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"All values are zero\");return}const uid=Math.random().toString(36).slice(2,8);const posColors=pickBandColors(numBands,POSITIVE_RAMP);const negColors=pickBandColors(numBands,NEGATIVE_RAMP);const seriesDataMap=new Map;seriesNames.forEach(name=>{const sd=isSingleSeries?[...parsedData].sort((a,b)=>a._date.getTime()-b._date.getTime()):parsedData.filter(d=>d[seriesField]===name).sort((a,b)=>a._date.getTime()-b._date.getTime());seriesDataMap.set(name,sd)});const uniqueTimeValues=new Set(parsedData.map(d=>d._date.getTime()));const isSingleTimePoint=uniqueTimeValues.size<=1;const smartLabels=smartTruncateLabels(seriesNames.map(String),16);seriesNames.forEach((seriesName,idx)=>{const yOff=topMargin+idx*(rowH+rowGap);const sd=seriesDataMap.get(seriesName);if(sd.length===0)return;const values=sd.map(d=>d._value);const maxAbs=d3.max(values,v=>Math.abs(v));if(maxAbs===0)return;const rowG=svg.append(\"g\").attr(\"transform\",`translate(${labelWidth}, ${yOff})`);rowG.append(\"rect\").attr(\"width\",chartW).attr(\"height\",rowH).attr(\"fill\",\"#0d1017\");if(isSingleTimePoint){const val=sd[0]._value;const color=val>=0?posColors[posColors.length-1]:negColors[negColors.length-1];const barWidth=Math.min(chartW*.4,60);rowG.append(\"rect\").attr(\"x\",chartW/2-barWidth/2).attr(\"y\",rowH*.15).attr(\"width\",barWidth).attr(\"height\",rowH*.7).attr(\"fill\",color).attr(\"rx\",3).style(\"pointer-events\",\"none\");rowG.append(\"text\").attr(\"x\",chartW/2).attr(\"y\",rowH/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",\"#ffffff\").attr(\"font-size\",\"10px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").style(\"pointer-events\",\"none\").text(formatValue(val))}else{const bandSize=maxAbs/numBands;const clipId=`hz-clip-${uid}-${idx}`;rowG.append(\"defs\").append(\"clipPath\").attr(\"id\",clipId).append(\"rect\").attr(\"width\",chartW).attr(\"height\",rowH);const bandG=rowG.append(\"g\").attr(\"clip-path\",`url(#${clipId})`);const yBand=d3.scaleLinear().domain([0,bandSize]).range([rowH,0]);for(let b=0;b<numBands;b++){const bMin=b*bandSize;const posArea=d3.area().x(d=>xScale(d._date)).y0(rowH).y1(d=>{const v=d._value;if(v<=bMin)return rowH;return yBand(Math.min(v-bMin,bandSize))}).curve(d3.curveMonotoneX);bandG.append(\"path\").datum(sd).attr(\"fill\",posColors[b]).attr(\"d\",posArea).style(\"pointer-events\",\"none\");if(mode===\"mirror\"){const negArea=d3.area().x(d=>xScale(d._date)).y0(rowH).y1(d=>{const v=-d._value;if(v<=bMin)return rowH;return yBand(Math.min(v-bMin,bandSize))}).curve(d3.curveMonotoneX);bandG.append(\"path\").datum(sd).attr(\"fill\",negColors[b]).attr(\"d\",negArea).style(\"pointer-events\",\"none\")}else{const offArea=d3.area().x(d=>xScale(d._date)).y0(rowH).y1(d=>{const v=d._value+maxAbs;if(v<=bMin)return rowH;return yBand(Math.min(v-bMin,bandSize))}).curve(d3.curveMonotoneX);bandG.append(\"path\").datum(sd).attr(\"fill\",posColors[b]).attr(\"d\",offArea).style(\"pointer-events\",\"none\")}}}if(!isSingleSeries){svg.append(\"text\").attr(\"x\",labelWidth-8).attr(\"y\",yOff+rowH/2).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(smartLabels[idx])}});const xAxisY=topMargin+seriesNames.length*(rowH+rowGap);const axisG=svg.append(\"g\").attr(\"transform\",`translate(${labelWidth}, ${xAxisY})`);const tickCount=getAdaptiveTickCount(chartW);const xAxis=axisG.append(\"g\").attr(\"class\",\"x-axis\").call(d3.axisBottom(xScale).ticks(tickCount).tickSize(0).tickPadding(8));styleAxis(xAxis);addCrosshairInteraction(svg,seriesNames,seriesDataMap,xScale,labelWidth,topMargin,rowH,rowGap,chartW,timeField,valueField,seriesField,tooltip,isSingleSeries)}function parseDate(v){if(v instanceof Date)return v;const d=new Date(v);return isNaN(d.getTime())?null:d}function calculateLabelWidth(seriesNames){const maxLen=Math.max(...seriesNames.map(s=>String(s).length));const estimated=Math.min(maxLen,16)*7+16;return Math.max(60,Math.min(160,estimated))}function pickBandColors(numBands,ramp){if(numBands<=ramp.length){return ramp.slice(ramp.length-numBands)}const out=[];for(let i=0;i<numBands;i++){out.push(ramp[Math.round(i*(ramp.length-1)/(numBands-1))])}return out}function addCrosshairInteraction(svg,seriesNames,seriesDataMap,xScale,labelWidth,topMargin,rowHeight,rowGap,chartW,timeField,valueField,seriesField,tooltip,isSingleSeries){const totalRowsH=seriesNames.length*(rowHeight+rowGap);const crosshair=svg.append(\"line\").attr(\"y1\",topMargin).attr(\"y2\",topMargin+totalRowsH).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const allDates=[];const dateSet=new Set;seriesDataMap.forEach(sd=>{sd.forEach(d=>{const t=d._date.getTime();if(!dateSet.has(t)){dateSet.add(t);allDates.push(t)}})});allDates.sort((a,b)=>a-b);svg.append(\"rect\").attr(\"x\",labelWidth).attr(\"y\",topMargin).attr(\"width\",chartW).attr(\"height\",totalRowsH).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,this);const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(d=>d).left;let idx=bisect(allDates,xDate);if(idx>0&&idx<allDates.length){const d0=allDates[idx-1];const d1=allDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=allDates.length){idx=allDates.length-1}const nearestTime=allDates[idx];const nearestX=xScale(new Date(nearestTime))+labelWidth;crosshair.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);const dateStr=new Date(nearestTime).toLocaleDateString();let html=`<strong>${dateStr}</strong>`;const entries=[];seriesNames.forEach(name=>{const sd=seriesDataMap.get(name);let closest=null;let minDiff=Infinity;for(const d of sd){const diff=Math.abs(d._date.getTime()-nearestTime);if(diff<minDiff){minDiff=diff;closest=d}}if(closest){entries.push({name,value:closest._value})}});entries.sort((a,b)=>Math.abs(b.value)-Math.abs(a.value));const maxShow=isSingleSeries?1:8;entries.slice(0,maxShow).forEach(entry=>{const color=entry.value>=0?\"#6baed6\":\"#fb6a4a\";if(isSingleSeries){html+=`<br/>${valueField}: ${formatValue(entry.value)}`}else{html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${truncateLabel(entry.name,20)}: ${formatValue(entry.value)}`}});if(entries.length>maxShow){html+=`<br/><span style=\"color:${TEXT_MUTED};font-size:11px;\">+${entries.length-maxShow} more</span>`}showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshair.attr(\"opacity\",0);hideTooltip(tooltip)})}return __toCommonJS(horizon_chart_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
24
|
+
export const icicleBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var icicle_render_exports={};__export(icicle_render_exports,{renderChart:()=>renderIcicle});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderIcicle(container,spec){const{config,encoding,data}=spec;const levelFields=config.levelFields||[];const valueField=config.valueField||\"\";const orientation=config.orientation||\"horizontal\";const showValues=config.showValues!==false;const isHorizontal=orientation===\"horizontal\";const width=container.clientWidth||800;const height=container.clientHeight||500;const titleHeight=spec.title?36:0;const contentPad=8;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";container.style.fontFamily=\"Inter, system-ui, sans-serif\";if(spec.title){const titleDiv=document.createElement(\"div\");titleDiv.style.cssText=`\n text-align: center;\n color: ${TEXT_COLOR};\n font-size: 14px;\n font-weight: 600;\n line-height: 36px;\n height: 36px;\n flex-shrink: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 0 10px;\n `;titleDiv.textContent=spec.title;titleDiv.title=spec.title;container.appendChild(titleDiv)}if(valueField&&isAllZeros(data,valueField)){const emptyDiv=document.createElement(\"div\");emptyDiv.style.cssText=`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: ${TEXT_MUTED};\n font-size: 14px;\n `;emptyDiv.textContent=\"All values are zero\";container.appendChild(emptyDiv);return}const root=buildHierarchyFromFields(data,levelFields,valueField);const totalValue=root.value||1;const topLevelNames=root.children?root.children.map(c=>c.data.name):[];const colorScale=encoding.color?buildColorScale(encoding.color,data):d3.scaleOrdinal().domain(topLevelNames).range([\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"]);const showLegend=topLevelNames.length>1&&height>200;const legendHeight=showLegend?28:0;const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=`flex: 1; min-height: 0; position: relative;`;container.appendChild(chartWrapper);const chartWidth=width-contentPad*2;const chartHeight=height-titleHeight-legendHeight-contentPad*2;const svg=d3.select(chartWrapper).append(\"svg\").attr(\"width\",width).attr(\"height\",chartHeight+contentPad*2);const g=svg.append(\"g\").attr(\"transform\",`translate(${contentPad},${contentPad})`);const tooltip=createTooltip(container);const partPad=1;if(isHorizontal){d3.partition().size([chartHeight,chartWidth]).padding(partPad)(root)}else{d3.partition().size([chartWidth,chartHeight]).padding(partPad)(root)}const depthExtent=isHorizontal?chartWidth:chartHeight;const rootY1=root.y1;if(rootY1>0&&rootY1<depthExtent){const scale=depthExtent/(depthExtent-rootY1);for(const node of root.descendants()){if(node.depth===0)continue;node.y0=(node.y0-rootY1)*scale;node.y1=(node.y1-rootY1)*scale}}const descendants=root.descendants().filter(d=>d.depth>0);const rects=g.selectAll(\".icicle-rect\").data(descendants).join(\"rect\").attr(\"class\",\"icicle-rect\").attr(\"x\",d=>isHorizontal?d.y0:d.x0).attr(\"y\",d=>isHorizontal?d.x0:d.y0).attr(\"width\",d=>{const w=isHorizontal?d.y1-d.y0:d.x1-d.x0;return Math.max(0,w)}).attr(\"height\",d=>{const h=isHorizontal?d.x1-d.x0:d.y1-d.y0;return Math.max(0,h)}).attr(\"fill\",d=>getNodeColor(d,colorScale)).attr(\"rx\",2).attr(\"ry\",2).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.5).attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){rects.attr(\"opacity\",n=>{if(n===d)return 1;if(isAncestor(n,d)||isAncestor(d,n))return 1;return .3});d3.select(this).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",2);const path=getAncestorPath(d);const pct=(d.value/totalValue*100).toFixed(1);showTooltip(tooltip,`<strong>${path}</strong><br/>${valueField}: ${formatValue(d.value)}<br/>${pct}% of total`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){rects.attr(\"opacity\",1).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.5);hideTooltip(tooltip)}).on(\"click\",function(_event,d){zoomTo(d)});const labels=g.selectAll(\".icicle-label\").data(descendants).join(\"text\").attr(\"class\",\"icicle-label\").attr(\"pointer-events\",\"none\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"dominant-baseline\",\"central\").each(function(d){positionLabel(d3.select(this),d,isHorizontal,colorScale,showValues,valueField)});let currentRoot=root;function zoomTo(target){if(target===currentRoot&&target.parent){target=target.parent.depth===0?root:target.parent}currentRoot=target;const x0=isHorizontal?target.y0:target.x0;const x1=isHorizontal?target.y1:target.x1;const y0=isHorizontal?target.x0:target.y0;const y1=isHorizontal?target.x1:target.y1;const xScale=d3.scaleLinear().domain([x0,x1]).range([0,chartWidth]);const yScale=d3.scaleLinear().domain([y0,y1]).range([0,chartHeight]);rects.transition().duration(500).attr(\"x\",d=>{const v=isHorizontal?d.y0:d.x0;return xScale(v)}).attr(\"y\",d=>{const v=isHorizontal?d.x0:d.y0;return yScale(v)}).attr(\"width\",d=>{const v0=isHorizontal?d.y0:d.x0;const v1=isHorizontal?d.y1:d.x1;return Math.max(0,xScale(v1)-xScale(v0))}).attr(\"height\",d=>{const v0=isHorizontal?d.x0:d.y0;const v1=isHorizontal?d.x1:d.y1;return Math.max(0,yScale(v1)-yScale(v0))}).attr(\"opacity\",d=>{if(!isDescendantOrSelf(d,target))return 0;return 1});labels.transition().duration(500).attr(\"opacity\",0).on(\"end\",function(d){const el=d3.select(this);if(!isDescendantOrSelf(d,target)){el.attr(\"visibility\",\"hidden\");return}const rectW=isHorizontal?xScale(d.y1)-xScale(d.y0):xScale(d.x1)-xScale(d.x0);const rectH=isHorizontal?yScale(d.x1)-yScale(d.x0):yScale(d.y1)-yScale(d.y0);const px=isHorizontal?xScale(d.y0):xScale(d.x0);const py=isHorizontal?yScale(d.x0):yScale(d.y0);positionLabelAt(el,d,px,py,rectW,rectH,isHorizontal,colorScale,showValues,valueField);el.transition().duration(200).attr(\"opacity\",1)})}if(showLegend){const legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}}function positionLabelAt(el,d,px,py,rectW,rectH,isHorizontal,colorScale,showValues,valueField){const textPadding=6;const availW=rectW-textPadding*2;const availH=rectH-textPadding*2;if(availW<20||availH<14){el.attr(\"visibility\",\"hidden\");return}el.attr(\"visibility\",\"visible\");const fillColor=getNodeColor(d,colorScale);const textColor=contrastText(fillColor);const fontSize=Math.max(9,Math.min(12,availH*.35,availW*.08));if(isHorizontal){el.attr(\"x\",px+textPadding).attr(\"y\",py+rectH/2).attr(\"text-anchor\",\"start\")}else{el.attr(\"x\",px+rectW/2).attr(\"y\",py+rectH/2).attr(\"text-anchor\",\"middle\")}el.attr(\"fill\",textColor).attr(\"font-size\",fontSize+\"px\").attr(\"font-weight\",\"600\");const name=String(d.data.name);const maxChars=Math.max(3,Math.floor(availW/(fontSize*.6)));if(showValues&&availW>60&&availH>22){const valStr=formatValue(d.value);const combinedMax=Math.max(3,Math.floor(availW/(fontSize*.6))-valStr.length-3);el.text(truncateLabel(name,combinedMax)+\" \"+valStr)}else{el.text(truncateLabel(name,maxChars))}}function positionLabel(el,d,isHorizontal,colorScale,showValues,valueField){const rectW=isHorizontal?d.y1-d.y0:d.x1-d.x0;const rectH=isHorizontal?d.x1-d.x0:d.y1-d.y0;const px=isHorizontal?d.y0:d.x0;const py=isHorizontal?d.x0:d.y0;positionLabelAt(el,d,px,py,rectW,rectH,isHorizontal,colorScale,showValues,valueField)}function buildHierarchyFromFields(data,levelFields,valueField){if(!levelFields.length){return d3.hierarchy({name:\"root\",children:[]}).sum(d=>d.value||0)}const allVals=data.map(d=>Number(d[valueField])||0).filter(v=>v>0);const maxVal=allVals.length>0?Math.max(...allVals):0;const minVisible=maxVal*.02;const clampVal=v=>v>0&&v<minVisible?minVisible:v;if(levelFields.length===1){const field=levelFields[0];const hierarchy2={name:\"root\",children:data.map(d=>({name:String(d[field]??\"Unknown\"),value:clampVal(Math.max(0,Number(d[valueField])||0)),_data:d}))};return d3.hierarchy(hierarchy2).sum(d=>d.value).sort((a,b)=>b.value-a.value)}function buildLevel(items,depth){if(depth>=levelFields.length){return items.map(d=>({name:String(d[levelFields[levelFields.length-1]]??\"Unknown\"),value:clampVal(Math.max(0,Number(d[valueField])||0)),_data:d}))}const field=levelFields[depth];const groups=new Map;for(const item of items){const key=String(item[field]??\"Unknown\");if(!groups.has(key))groups.set(key,[]);groups.get(key).push(item)}if(depth===levelFields.length-1){return items.map(d=>({name:String(d[field]??\"Unknown\"),value:clampVal(Math.max(0,Number(d[valueField])||0)),_data:d}))}const children=[];for(const[key,groupItems]of groups){children.push({name:key,children:buildLevel(groupItems,depth+1)})}return children}const hierarchy={name:\"root\",children:buildLevel(data,0)};return d3.hierarchy(hierarchy).sum(d=>d.value).sort((a,b)=>b.value-a.value)}function getTopAncestor(d){let node=d;while(node.parent&&node.parent.parent){node=node.parent}return node}function getNodeColor(d,colorScale){const ancestor=getTopAncestor(d);const baseColor=colorScale(ancestor.data.name);if(d.depth>1){const lightenFactor=Math.min(d.depth*.1,.35);return d3.interpolateRgb(baseColor,\"#ffffff\")(lightenFactor)}return baseColor}function getAncestorPath(d){const parts=[];let node=d;while(node&&node.depth>0){parts.unshift(node.data.name);node=node.parent}return parts.join(\" \\u203A \")}function isAncestor(candidate,node){let current=node.parent;while(current){if(current===candidate)return true;current=current.parent}return false}function isDescendantOrSelf(node,ancestor){if(node===ancestor)return true;let current=node.parent;while(current){if(current===ancestor)return true;current=current.parent}return false}return __toCommonJS(icicle_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
25
|
+
export const lineBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var line_render_exports={};__export(line_render_exports,{renderChart:()=>renderLine});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderLine(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field||null;const interpolation=config.interpolation||\"monotone\";const showPoints=interpolation===\"step\"?false:config.showPoints??data.length<=50;const showArea=config.showArea??false;const strokeWidth=config.strokeWidth??2;const parsedData=data.map(d=>({...d,_date:parseDate(d[timeField]),_value:Number(d[valueField])})).filter(d=>d._date!==null&&!isNaN(d._value));const colorScale=buildColorScale(encoding.color,data);const seriesNames=seriesField?[...new Set(parsedData.map(d=>d[seriesField]))]:[];const isMultiSeries=seriesNames.length>1;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);if(isMultiSeries){const legendDiv=createLegend(colorScale,{shape:\"line\"});container.appendChild(legendDiv)}const{svg,g,dims}=createSvg(chartWrapper,spec,{right:30,top:40});svg.style(\"background\",\"none\");const tooltip=createTooltip(chartWrapper);if(parsedData.every(d=>d._value===0)){renderEmptyState(g,dims);return}const xExtent=d3.extent(parsedData,d=>d._date);const xScale=d3.scaleTime().domain(xExtent).range([0,dims.innerWidth]).nice();const yExtent=d3.extent(parsedData,d=>d._value);const yMin=showArea?0:yExtent[0]*.9;const yScale=d3.scaleLinear().domain([yMin,yExtent[1]*1.05]).range([dims.innerHeight,0]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(0).tickPadding(8));styleAxis(xAxis);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const curveMap={linear:d3.curveLinear,monotone:d3.curveMonotoneX,basis:d3.curveBasis,step:d3.curveStepAfter,cardinal:d3.curveCardinal,catmullRom:d3.curveCatmullRom};const curve=curveMap[config.interpolation||\"monotone\"]||d3.curveMonotoneX;const lineGen=d3.line().x(d=>xScale(d._date)).y(d=>yScale(d._value)).curve(curve);const areaGen=d3.area().x(d=>xScale(d._date)).y0(dims.innerHeight).y1(d=>yScale(d._value)).curve(curve);const uniqueDates=new Set(parsedData.map(d=>d._date.getTime()));const isSinglePoint=uniqueDates.size<=1;if(isSinglePoint){const color=isMultiSeries?void 0:categorical[0];parsedData.forEach(d=>{const c=isMultiSeries?colorScale(d[seriesField]):color;g.append(\"circle\").attr(\"cx\",xScale(d._date)).attr(\"cy\",yScale(d._value)).attr(\"r\",6).attr(\"fill\",c).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2);g.append(\"text\").attr(\"x\",xScale(d._date)).attr(\"y\",yScale(d._value)-14).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(formatValue(d._value))})}else if(isMultiSeries){drawMultiSeries(g,parsedData,seriesField,seriesNames,colorScale,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth)}else{drawSingleSeries(g,parsedData,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth)}if(!isSinglePoint){addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,isMultiSeries)}}function parseDate(v){if(v instanceof Date)return v;const d=new Date(v);return isNaN(d.getTime())?null:d}function drawMultiSeries(g,parsedData,seriesField,seriesNames,colorScale,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth){seriesNames.forEach(name=>{const seriesData=parsedData.filter(d=>d[seriesField]===name).sort((a,b)=>a._date.getTime()-b._date.getTime());const color=colorScale(name);if(showArea){g.append(\"path\").datum(seriesData).attr(\"fill\",color).attr(\"opacity\",.1).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\")}g.append(\"path\").datum(seriesData).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\");if(showPoints){g.selectAll(`.point-${String(name).replace(/\\W/g,\"\")}`).data(seriesData).join(\"circle\").attr(\"class\",`point-${String(name).replace(/\\W/g,\"\")}`).attr(\"cx\",d=>xScale(d._date)).attr(\"cy\",d=>yScale(d._value)).attr(\"r\",1.25).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")}})}function drawSingleSeries(g,parsedData,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth){const sortedData=[...parsedData].sort((a,b)=>a._date.getTime()-b._date.getTime());const color=categorical[0];if(showArea){g.append(\"path\").datum(sortedData).attr(\"fill\",color).attr(\"opacity\",.1).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\")}g.append(\"path\").datum(sortedData).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\");if(showPoints){g.selectAll(\".point\").data(sortedData).join(\"circle\").attr(\"class\",\"point\").attr(\"cx\",d=>xScale(d._date)).attr(\"cy\",d=>yScale(d._value)).attr(\"r\",1.25).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.75).attr(\"pointer-events\",\"none\")}}function addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,isMultiSeries){const dateMap=new Map;parsedData.forEach(d=>{const key=d._date.getTime();if(!dateMap.has(key))dateMap.set(key,[]);dateMap.get(key).push(d)});const sortedDates=[...dateMap.keys()].sort((a,b)=>a-b);const crosshairLine=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const highlightDots=g.append(\"g\").attr(\"class\",\"highlight-dots\").attr(\"pointer-events\",\"none\");g.append(\"rect\").attr(\"class\",\"hover-area\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,this);const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(d=>d).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestTime=sortedDates[idx];const nearestX=xScale(new Date(nearestTime));const points=dateMap.get(nearestTime)||[];crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();points.forEach(d=>{const color=isMultiSeries?colorScale(d[seriesField]):categorical[0];highlightDots.append(\"circle\").attr(\"cx\",nearestX).attr(\"cy\",yScale(d._value)).attr(\"r\",5).attr(\"fill\",color).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2)});g.selectAll(\".line-path\").attr(\"opacity\",.4);const dateLabel=points[0]?.[timeField]??new Date(nearestTime).toLocaleDateString();let html=`<strong>${dateLabel}</strong>`;if(isMultiSeries){const sorted=[...points].sort((a,b)=>b._value-a._value);sorted.forEach(d=>{const color=colorScale(d[seriesField]);html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${d[seriesField]}: ${formatValue(d._value)}`})}else{html+=`<br/>${valueField}: ${formatValue(points[0]?._value)}`}showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();g.selectAll(\".line-path\").attr(\"opacity\",1);hideTooltip(tooltip)})}return __toCommonJS(line_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
26
|
+
export const lollipopBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var lollipop_render_exports={};__export(lollipop_render_exports,{renderChart:()=>renderLollipop});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderLollipop(container,spec){const{config,encoding,data}=spec;const isHorizontal=config.orientation!==\"vertical\";const categoryField=config.categoryField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;if(!categoryField||!valueField)return;let sortedData=[...data];if(config.sortBy===\"value\"||config.sorted&&!config.sortBy){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>order*(Number(a[valueField])-Number(b[valueField])))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;sortedData.sort((a,b)=>{const aVal=String(a[categoryField]);const bVal=String(b[categoryField]);return order*aVal.localeCompare(bVal,void 0,{sensitivity:\"base\",numeric:true})})}const dotRadius=config.dotRadius??14;let marginOverrides;if(isHorizontal){const labels=sortedData.map(d=>String(d[categoryField]));const leftMargin=calculateLeftMargin(labels);marginOverrides={left:leftMargin,bottom:40,right:40}}else{const labels=sortedData.map(d=>String(d[categoryField]));const containerWidth=container.clientWidth||800;const estimatedSpacing=(containerWidth-100)/labels.length;const willRotate=shouldRotateLabels(labels,estimatedSpacing);const bottomMargin=calculateBottomMargin(labels,willRotate);marginOverrides={bottom:bottomMargin,left:70,right:30}}const{svg,g,dims}=createSvg(container,spec,marginOverrides);const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){renderEmptyState(g,dims);return}if(isHorizontal){renderHorizontal(g,sortedData,data,encoding,config,dims,tooltip,categoryField,valueField,dotRadius)}else{renderVertical(g,sortedData,data,encoding,config,dims,tooltip,categoryField,valueField,dotRadius)}const hasCategoricalLabels=sortedData.some(d=>{const value=d[categoryField];return typeof value===\"string\"&&isNaN(Number(value))});if(hasCategoricalLabels){addSortControls(svg,container,spec,dims,renderLollipop)}}function renderHorizontal(g,data,originalData,encoding,config,dims,tooltip,categoryField,valueField,dotRadius){const categories=data.map(d=>String(d[categoryField]));const yScale=d3.scalePoint().domain(categories).range([0,dims.innerHeight]).padding(.5);const values=data.map(d=>Number(d[valueField]));const minVal=Math.min(0,d3.min(values));const maxVal=Math.max(0,d3.max(values));const xScale=d3.scaleLinear().domain([minVal,maxVal]).range([0,dims.innerWidth]).nice();const colorScale=buildColorScale(encoding.color,originalData,valueField);const baselineX=xScale(0);const spacing=categories.length>1?yScale.step():dims.innerHeight;const r=Math.min(dotRadius,spacing/2-1);const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(10).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);g.selectAll(\".lollipop-hover\").data(data).join(\"rect\").attr(\"class\",\"lollipop-hover\").attr(\"x\",0).attr(\"y\",d=>yScale(String(d[categoryField]))-spacing/2).attr(\"width\",dims.innerWidth).attr(\"height\",spacing).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){const cat=String(d[categoryField]);const hoverSize=r*1.3;g.selectAll(\".lollipop-dot\").attr(\"opacity\",dd=>String(dd[categoryField])===cat?1:.25);g.selectAll(\".lollipop-dot\").filter(dd=>String(dd[categoryField])===cat).attr(\"width\",hoverSize*2).attr(\"height\",hoverSize*2).attr(\"x\",dd=>xScale(Number(dd[valueField]))-hoverSize).attr(\"y\",dd=>yScale(String(dd[categoryField]))-hoverSize);g.selectAll(\".lollipop-stem\").attr(\"opacity\",dd=>String(dd[categoryField])===cat?1:.25);showTooltip(tooltip,`<strong>${d[categoryField]}</strong><br/>${valueField}: ${formatValue(Number(d[valueField]))}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".lollipop-dot\").attr(\"opacity\",1).attr(\"width\",r*2).attr(\"height\",r*2).attr(\"x\",dd=>xScale(Number(dd[valueField]))-r).attr(\"y\",dd=>yScale(String(dd[categoryField]))-r);g.selectAll(\".lollipop-stem\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".lollipop-stem\").data(data).join(\"line\").attr(\"class\",\"lollipop-stem\").attr(\"x1\",baselineX).attr(\"x2\",d=>{const val=Number(d[valueField]);return xScale(val)+(val>=0?-r:r)}).attr(\"y1\",d=>yScale(String(d[categoryField]))).attr(\"y2\",d=>yScale(String(d[categoryField]))).attr(\"stroke\",d=>colorScale(d[encoding.color?.field||categoryField])).attr(\"stroke-width\",2).attr(\"pointer-events\",\"none\");g.selectAll(\".lollipop-dot\").data(data).join(\"rect\").attr(\"class\",\"lollipop-dot\").attr(\"x\",d=>xScale(Number(d[valueField]))-r).attr(\"y\",d=>yScale(String(d[categoryField]))-r).attr(\"width\",r*2).attr(\"height\",r*2).attr(\"rx\",2).attr(\"fill\",d=>colorScale(d[encoding.color?.field||categoryField])).attr(\"stroke\",\"#0f1117\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");if(r>=12){g.selectAll(\".lollipop-label\").data(data).join(\"text\").attr(\"class\",\"lollipop-label\").attr(\"x\",d=>xScale(Number(d[valueField]))).attr(\"y\",d=>yScale(String(d[categoryField]))).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",d=>contrastText(colorScale(d[encoding.color?.field||categoryField]))).attr(\"font-size\",`${Math.min(10,r-3)}px`).attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>{const dotX=xScale(Number(d[valueField]));if(dotX<r+5)return\"\";return formatValue(Number(d[valueField]))})}}function renderVertical(g,data,originalData,encoding,config,dims,tooltip,categoryField,valueField,dotRadius){const categories=data.map(d=>String(d[categoryField]));const xScale=d3.scalePoint().domain(categories).range([0,dims.innerWidth]).padding(.5);const values=data.map(d=>Number(d[valueField]));const minVal=Math.min(0,d3.min(values));const maxVal=Math.max(0,d3.max(values));const yScale=d3.scaleLinear().domain([minVal,maxVal]).range([dims.innerHeight,0]).nice();const colorScale=buildColorScale(encoding.color,originalData,valueField);const baselineY=yScale(0);const spacing=categories.length>1?xScale.step():dims.innerWidth;const r=Math.min(dotRadius,spacing/2-1);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,12)));styleAxis(xAxis);const needsRotation=shouldRotateLabels(categories,spacing);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);g.selectAll(\".lollipop-hover\").data(data).join(\"rect\").attr(\"class\",\"lollipop-hover\").attr(\"x\",d=>xScale(String(d[categoryField]))-spacing/2).attr(\"y\",0).attr(\"width\",spacing).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){const cat=String(d[categoryField]);const hoverSize=r*1.3;g.selectAll(\".lollipop-dot\").attr(\"opacity\",dd=>String(dd[categoryField])===cat?1:.25);g.selectAll(\".lollipop-dot\").filter(dd=>String(dd[categoryField])===cat).attr(\"width\",hoverSize*2).attr(\"height\",hoverSize*2).attr(\"x\",dd=>xScale(String(dd[categoryField]))-hoverSize).attr(\"y\",dd=>yScale(Number(dd[valueField]))-hoverSize);g.selectAll(\".lollipop-stem\").attr(\"opacity\",dd=>String(dd[categoryField])===cat?1:.25);showTooltip(tooltip,`<strong>${d[categoryField]}</strong><br/>${valueField}: ${formatValue(Number(d[valueField]))}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".lollipop-dot\").attr(\"opacity\",1).attr(\"width\",r*2).attr(\"height\",r*2).attr(\"x\",dd=>xScale(String(dd[categoryField]))-r).attr(\"y\",dd=>yScale(Number(dd[valueField]))-r);g.selectAll(\".lollipop-stem\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".lollipop-stem\").data(data).join(\"line\").attr(\"class\",\"lollipop-stem\").attr(\"x1\",d=>xScale(String(d[categoryField]))).attr(\"x2\",d=>xScale(String(d[categoryField]))).attr(\"y1\",baselineY).attr(\"y2\",d=>{const val=Number(d[valueField]);return yScale(val)+(val>=0?r:-r)}).attr(\"stroke\",d=>colorScale(d[encoding.color?.field||categoryField])).attr(\"stroke-width\",2).attr(\"pointer-events\",\"none\");g.selectAll(\".lollipop-dot\").data(data).join(\"rect\").attr(\"class\",\"lollipop-dot\").attr(\"x\",d=>xScale(String(d[categoryField]))-r).attr(\"y\",d=>yScale(Number(d[valueField]))-r).attr(\"width\",r*2).attr(\"height\",r*2).attr(\"rx\",2).attr(\"fill\",d=>colorScale(d[encoding.color?.field||categoryField])).attr(\"stroke\",\"#0f1117\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");if(r>=12){g.selectAll(\".lollipop-label\").data(data).join(\"text\").attr(\"class\",\"lollipop-label\").attr(\"x\",d=>xScale(String(d[categoryField]))).attr(\"y\",d=>yScale(Number(d[valueField]))).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",d=>contrastText(colorScale(d[encoding.color?.field||categoryField]))).attr(\"font-size\",`${Math.min(10,r-3)}px`).attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>formatValue(Number(d[valueField])))}}return __toCommonJS(lollipop_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
27
|
+
export const marimekkoBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var marimekko_render_exports={};__export(marimekko_render_exports,{renderChart:()=>renderMarimekko});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderMarimekko(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.x?.field;const seriesField=config.seriesField||encoding.color?.field;const valueField=config.valueField||encoding.y?.field;const showLabels=config.showLabels!==false;const showPercentages=config.showPercentages!==false;const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>200&&containerWidth>250;const colorScale=buildColorScale(encoding.color,data);const secondaryKeys=[...new Set(data.map(d=>String(d[seriesField])))];let primaryKeys=[...new Set(data.map(d=>String(d[categoryField])))];const columnTotals={};primaryKeys.forEach(pk=>{columnTotals[pk]=0;data.forEach(d=>{if(String(d[categoryField])===pk){columnTotals[pk]+=Math.abs(Number(d[valueField]))||0}})});if(config.sortBy===\"value\"){const order=config.sortOrder===\"ascending\"?1:-1;primaryKeys.sort((a,b)=>order*(columnTotals[a]-columnTotals[b]))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;primaryKeys.sort((a,b)=>order*a.localeCompare(b,void 0,{sensitivity:\"base\",numeric:true}))}container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);let legendDiv=null;if(showLegend){legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}const{svg,g,dims}=createSvg(chartWrapper,spec,{bottom:50,left:20,right:30,top:40});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){renderEmptyState(g,dims);return}const grandTotal=data.reduce((s,d)=>s+(Math.abs(Number(d[valueField]))||0),0);if(grandTotal===0||primaryKeys.length===0||secondaryKeys.length===0){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"13px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"No data to display\");return}const gap=Math.max(1,Math.min(3,dims.innerWidth/primaryKeys.length*.03));const totalGaps=gap*(primaryKeys.length-1);const availableWidth=dims.innerWidth-totalGaps;const columns=[];let currentX=0;primaryKeys.forEach((pk,i)=>{const colTotal=columnTotals[pk];const colWidth=grandTotal>0?colTotal/grandTotal*availableWidth:availableWidth/primaryKeys.length;const segments=[];let currentY=0;secondaryKeys.forEach(sk=>{const row=data.find(d=>String(d[categoryField])===pk&&String(d[seriesField])===sk);const val=row?Math.abs(Number(row[valueField]))||0:0;if(val===0){segments.push({primaryKey:pk,secondaryKey:sk,value:0,x:currentX,y:currentY,width:colWidth,height:0,pctOfColumn:0,pctOfTotal:0});return}const segHeight=colTotal>0?val/colTotal*dims.innerHeight:0;segments.push({primaryKey:pk,secondaryKey:sk,value:val,x:currentX,y:currentY,width:colWidth,height:segHeight,pctOfColumn:colTotal>0?val/colTotal*100:0,pctOfTotal:grandTotal>0?val/grandTotal*100:0});currentY+=segHeight});columns.push({primaryKey:pk,total:colTotal,x:currentX,width:colWidth,segments});currentX+=colWidth+(i<primaryKeys.length-1?gap:0)});const allSegments=columns.flatMap(col=>col.segments.filter(s=>s.height>0));g.selectAll(\".col-hover-target\").data(columns).join(\"rect\").attr(\"class\",\"col-hover-target\").attr(\"x\",d=>d.x).attr(\"y\",0).attr(\"width\",d=>Math.max(0,d.width)).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".mekko-segment\").attr(\"opacity\",s=>s.primaryKey===d.primaryKey?1:.3);const colPct=grandTotal>0?(d.total/grandTotal*100).toFixed(1):\"0.0\";let html=`<strong>${d.primaryKey}</strong>`;html+=`<br/><span style=\"color:${TEXT_MUTED};font-size:11px\">Column total: ${formatValue(d.total)} (${colPct}%)</span>`;d.segments.filter(s=>s.value>0).forEach(seg=>{const swatch=`<span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${colorScale(seg.secondaryKey)};margin-right:4px\"></span>`;html+=`<br/>${swatch}${seg.secondaryKey}: ${formatValue(seg.value)} (${seg.pctOfColumn.toFixed(0)}%)`});showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".mekko-segment\").attr(\"opacity\",1);hideTooltip(tooltip)});g.selectAll(\".mekko-segment\").data(allSegments).join(\"rect\").attr(\"class\",\"mekko-segment\").attr(\"x\",d=>d.x).attr(\"y\",d=>d.y).attr(\"width\",d=>Math.max(0,d.width)).attr(\"height\",d=>Math.max(0,d.height)).attr(\"fill\",d=>colorScale(d.secondaryKey)).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).attr(\"pointer-events\",\"none\");const isSmall=dims.innerWidth<350||dims.innerHeight<300;if((showLabels||showPercentages)&&!isSmall){g.selectAll(\".mekko-label\").data(allSegments).join(\"text\").attr(\"class\",\"mekko-label\").attr(\"x\",d=>d.x+d.width/2).attr(\"y\",d=>d.y+d.height/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",d=>contrastText(colorScale(d.secondaryKey))).attr(\"font-size\",d=>{const minDim=Math.min(d.width,d.height);return Math.max(9,Math.min(12,minDim/4))+\"px\"}).attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>{if(d.width<45||d.height<22)return\"\";const parts=[];const maxChars=Math.max(3,Math.floor(d.width/8));if(showLabels&&d.width>=65&&d.height>=30){parts.push(truncateLabel(d.secondaryKey,Math.min(maxChars,Math.floor(d.width/7))))}if(showPercentages&&d.width>=45&&d.height>=22){parts.push(d.pctOfColumn.toFixed(0)+\"%\")}const text=parts.join(\" \");if(text.length*6.5>d.width-4)return parts.length>1?parts[parts.length-1]:\"\";return text})}const axisG=g.append(\"g\");columns.forEach(col=>{const centerX=col.x+col.width/2;const charWidth=7;const maxChars=Math.max(3,Math.floor(col.width/charWidth));const label=truncateLabel(col.primaryKey,maxChars);const needsRotation=col.width<40&&col.primaryKey.length>3;const labelG=axisG.append(\"text\").attr(\"x\",centerX).attr(\"y\",dims.innerHeight+16).attr(\"text-anchor\",needsRotation?\"end\":\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");if(needsRotation){labelG.attr(\"transform\",`rotate(-35, ${centerX}, ${dims.innerHeight+16})`).attr(\"dx\",\"-0.3em\").attr(\"dy\",\"0.15em\")}labelG.text(label);if(col.primaryKey.length>maxChars){labelG.append(\"title\").text(col.primaryKey)}const colPct=grandTotal>0?(col.total/grandTotal*100).toFixed(0)+\"%\":\"\";if(col.width>=30){axisG.append(\"text\").attr(\"x\",centerX).attr(\"y\",dims.innerHeight+(needsRotation?28:30)).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"opacity\",.6).text(colPct)}});axisG.append(\"line\").attr(\"x1\",0).attr(\"y1\",dims.innerHeight).attr(\"x2\",dims.innerWidth).attr(\"y2\",dims.innerHeight).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);addSortControls(svg,container,spec,dims,renderMarimekko)}return __toCommonJS(marimekko_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
28
|
+
export const metricBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var metric_render_exports={};__export(metric_render_exports,{renderChart:()=>renderMetric});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function formatMetricValue(value,format,abbreviate,prefix,suffix){let formatted;switch(format){case\"currency\":formatted=abbreviate?formatValue(value):value.toLocaleString();return`${prefix||\"$\"}${formatted}${suffix}`;case\"percent\":formatted=abbreviate&&Math.abs(value)>=1e3?formatValue(value):value.toFixed(1);return`${prefix}${formatted}%${suffix}`;case\"integer\":formatted=abbreviate?formatValue(value):Math.round(value).toLocaleString();return`${prefix}${formatted}${suffix}`;case\"decimal\":formatted=abbreviate&&Math.abs(value)>=1e3?formatValue(value):value.toFixed(2);return`${prefix}${formatted}${suffix}`;default:if(abbreviate&&Math.abs(value)>=1e3){formatted=formatValue(value)}else if(Number.isInteger(value)){formatted=value.toLocaleString()}else{formatted=value%1!==0?value.toFixed(1):value.toLocaleString()}return`${prefix}${formatted}${suffix}`}}function computeDelta(current,previous){if(previous===0)return{pct:\"N/A\",direction:\"flat\"};const change=(current-previous)/Math.abs(previous)*100;if(Math.abs(change)<.05)return{pct:\"0%\",direction:\"flat\"};const direction=change>0?\"up\":\"down\";return{pct:`${Math.abs(change).toFixed(1)}%`,direction}}function gridColumns(count,configColumns){if(typeof configColumns===\"number\"&&configColumns>0){return`repeat(${configColumns}, 1fr)`}if(count===1)return\"1fr\";if(count===2)return\"repeat(2, 1fr)\";if(count<=3)return`repeat(${count}, 1fr)`;if(count===4)return\"repeat(2, 1fr)\";if(count<=6)return\"repeat(3, 1fr)\";if(count<=9)return\"repeat(3, 1fr)\";return\"repeat(4, 1fr)\"}function adaptiveValueSize(count,containerWidth,containerHeight){const area=containerWidth*containerHeight;let base;if(area<15e4)base=28;else if(area<3e5)base=36;else if(area<5e5)base=48;else base=60;if(count<=1)return base;if(count<=2)return Math.round(base*.9);if(count<=4)return Math.round(base*.75);if(count<=6)return Math.round(base*.65);return Math.round(base*.55)}function adaptiveLabelSize(valueFontSize){return Math.max(10,Math.round(valueFontSize*.22))}function renderMetric(container,spec){const{config,data}=spec;const labelField=config.labelField||\"label\";const valueField=config.valueField||\"value\";const previousValueField=config.previousValueField||null;const abbreviate=config.abbreviate!==false;const format=config.format||\"auto\";const prefix=config.prefix||\"\";const suffix=config.suffix||\"\";const configColumns=config.columns;const width=container.clientWidth||800;const height=container.clientHeight||500;const count=data.length;const valueFontSize=adaptiveValueSize(count,width,height);const labelFontSize=adaptiveLabelSize(valueFontSize);const wrapper=document.createElement(\"div\");wrapper.style.cssText=`\n width: ${width}px;\n height: ${height}px;\n background: ${DARK_BG};\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n font-family: Inter, system-ui, sans-serif;\n overflow: hidden;\n `;if(spec.title){const titleEl=document.createElement(\"div\");titleEl.style.cssText=`\n text-align: center;\n color: ${TEXT_COLOR};\n font-size: 14px;\n font-weight: 600;\n padding: 16px 16px 0;\n flex-shrink: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n `;titleEl.textContent=spec.title;titleEl.title=spec.title;wrapper.appendChild(titleEl)}const grid=document.createElement(\"div\");grid.style.cssText=`\n flex: 1;\n display: grid;\n grid-template-columns: ${gridColumns(count,configColumns)};\n gap: 8px;\n padding: 24px;\n align-items: center;\n justify-items: center;\n `;for(const row of data){const label=String(row[labelField]??\"\");const rawValue=Number(row[valueField]);const value=isNaN(rawValue)?0:rawValue;const hasPrev=previousValueField&&row[previousValueField]!=null;const prevValue=hasPrev?Number(row[previousValueField]):null;const card=document.createElement(\"div\");card.style.cssText=`\n text-align: center;\n padding: 8px 12px;\n width: 100%;\n min-width: 0;\n overflow: hidden;\n `;const numberEl=document.createElement(\"div\");numberEl.style.cssText=`\n color: ${TEXT_COLOR};\n font-size: ${valueFontSize}px;\n font-weight: 300;\n line-height: 1.1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n `;numberEl.textContent=formatMetricValue(value,format,abbreviate,prefix,suffix);card.appendChild(numberEl);const labelEl=document.createElement(\"div\");labelEl.style.cssText=`\n color: ${TEXT_MUTED};\n font-size: ${labelFontSize}px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 1.5px;\n margin-top: 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n `;labelEl.textContent=label;if(label.length>30)labelEl.title=label;card.appendChild(labelEl);if(prevValue!==null&&!isNaN(prevValue)){const delta=computeDelta(value,prevValue);const deltaEl=document.createElement(\"div\");const deltaColor=delta.direction===\"up\"?\"#10b981\":delta.direction===\"down\"?\"#ef4444\":TEXT_MUTED;const arrow=delta.direction===\"up\"?\"\\u25B2\":delta.direction===\"down\"?\"\\u25BC\":\"\\u25B6\";deltaEl.style.cssText=`\n color: ${deltaColor};\n font-size: ${Math.max(10,Math.round(valueFontSize*.2))}px;\n font-weight: 600;\n margin-top: 4px;\n `;deltaEl.textContent=`${arrow} ${delta.pct}`;card.appendChild(deltaEl)}grid.appendChild(card)}wrapper.appendChild(grid);container.appendChild(wrapper)}return __toCommonJS(metric_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
29
|
+
export const parallelCoordinatesBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var parallel_coordinates_render_exports={};__export(parallel_coordinates_render_exports,{renderChart:()=>renderParallelCoordinates});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderParallelCoordinates(container,spec){const{config,encoding,data}=spec;const dimensions=config.dimensions||[];const colorField=config.colorField||encoding.color?.field||null;const labelField=config.labelField||null;const lineOpacity=config.lineOpacity??.5;const strokeWidth=config.strokeWidth??1.5;const showAxisLabels=config.showAxisLabels!==false;if(dimensions.length===0||data.length===0)return;const hasLegend=colorField!==null;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{top:50,bottom:30,left:60,right:30});const tooltip=createTooltip(container);const allZero=dimensions.every(dim=>data.every(d=>Number(d[dim])===0));if(allZero){svg.style(\"background\",\"none\");renderEmptyState(g,dims);return}const scales={};for(const dim of dimensions){const extent=d3.extent(data,d=>Number(d[dim]));const pad=extent[0]===extent[1]?1:0;scales[dim]=d3.scaleLinear().domain([extent[0]-pad,extent[1]+pad]).range([dims.innerHeight,0]).nice()}const xScale=d3.scalePoint().domain(dimensions).range([0,dims.innerWidth]);const colorEncoding=colorField?{...encoding.color||{},field:colorField,type:encoding.color?.type||\"nominal\"}:encoding.color;const colorScale=buildColorScale(colorEncoding,data);const tickCount=getAdaptiveTickCount(dims.innerHeight,40);const axisSpacing=dimensions.length>1?dims.innerWidth/(dimensions.length-1):dims.innerWidth;const showTickLabels=showAxisLabels&&axisSpacing>=50;dimensions.forEach((dim,dimIdx)=>{const x=xScale(dim);const yScale=scales[dim];const axisG=g.append(\"g\").attr(\"class\",\"pc-axis\").attr(\"transform\",`translate(${x}, 0)`).call(d3.axisLeft(yScale).ticks(tickCount).tickSize(0).tickPadding(6).tickFormat(d=>formatValue(d)));styleAxis(axisG);if(!showTickLabels){axisG.selectAll(\".tick text\").remove()}g.append(\"text\").attr(\"x\",x).attr(\"y\",-12).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(truncateLabel(dim,14))});const pathForRow=row=>{return dimensions.map((dim,i)=>{const x=xScale(dim);const y=scales[dim](Number(row[dim]));return(i===0?\"M\":\"L\")+` ${x} ${y}`}).join(\" \")};const lines=g.selectAll(\".pc-line\").data(data).join(\"path\").attr(\"class\",\"pc-line\").attr(\"d\",d=>pathForRow(d)).attr(\"fill\",\"none\").attr(\"stroke\",d=>colorField?colorScale(d[colorField]):categorical[0]).attr(\"stroke-width\",strokeWidth).attr(\"stroke-opacity\",lineOpacity).attr(\"stroke-linejoin\",\"round\").style(\"cursor\",\"pointer\");lines.on(\"mouseover\",function(event,d){g.selectAll(\".pc-line\").attr(\"stroke-opacity\",.08).attr(\"stroke-width\",strokeWidth*.5);d3.select(this).attr(\"stroke-opacity\",1).attr(\"stroke-width\",strokeWidth*2.5).raise();let html=\"\";if(labelField&&d[labelField]){html+=`<strong>${d[labelField]}</strong>`;if(colorField&&colorField!==labelField){html+=` <span style=\"color:#9ca3af\">${d[colorField]}</span>`}html+=\"<br/>\"}else if(colorField){html+=`<strong>${d[colorField]}</strong><br/>`}html+=dimensions.map(dim=>{const val=Number(d[dim]);return`${dim}: ${isNaN(val)?d[dim]:formatValue(val)}`}).join(\"<br/>\");showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".pc-line\").attr(\"stroke-opacity\",lineOpacity).attr(\"stroke-width\",strokeWidth);hideTooltip(tooltip)});if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"line\",callbacks:{onHover:category=>{g.selectAll(\".pc-line\").each(function(d){const isMatch=d[colorField]===category;d3.select(this).attr(\"stroke-opacity\",isMatch?Math.min(lineOpacity*2,1):.05).attr(\"stroke-width\",isMatch?strokeWidth*1.5:strokeWidth*.5)})},onLeave:()=>{g.selectAll(\".pc-line\").attr(\"stroke-opacity\",lineOpacity).attr(\"stroke-width\",strokeWidth)}}});container.appendChild(legendDiv)}}return __toCommonJS(parallel_coordinates_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
30
|
+
export const proportionalSymbolBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var proportional_symbol_render_exports={};__export(proportional_symbol_render_exports,{renderChart:()=>renderProportionalSymbol});var src_exports={};__export(src_exports,{bbox:()=>bbox_default,feature:()=>feature_default,merge:()=>merge_default,mergeArcs:()=>mergeArcs,mesh:()=>mesh_default,meshArcs:()=>meshArcs,neighbors:()=>neighbors_default,quantize:()=>quantize_default,transform:()=>transform_default,untransform:()=>untransform_default});function identity_default(x){return x}function transform_default(transform){if(transform==null)return identity_default;var x0,y0,kx=transform.scale[0],ky=transform.scale[1],dx=transform.translate[0],dy=transform.translate[1];return function(input,i){if(!i)x0=y0=0;var j=2,n=input.length,output=new Array(n);output[0]=(x0+=input[0])*kx+dx;output[1]=(y0+=input[1])*ky+dy;while(j<n)output[j]=input[j],++j;return output}}function bbox_default(topology){var t=transform_default(topology.transform),key,x0=Infinity,y0=x0,x1=-x0,y1=-x0;function bboxPoint(p){p=t(p);if(p[0]<x0)x0=p[0];if(p[0]>x1)x1=p[0];if(p[1]<y0)y0=p[1];if(p[1]>y1)y1=p[1]}function bboxGeometry(o){switch(o.type){case\"GeometryCollection\":o.geometries.forEach(bboxGeometry);break;case\"Point\":bboxPoint(o.coordinates);break;case\"MultiPoint\":o.coordinates.forEach(bboxPoint);break}}topology.arcs.forEach(function(arc){var i=-1,n=arc.length,p;while(++i<n){p=t(arc[i],i);if(p[0]<x0)x0=p[0];if(p[0]>x1)x1=p[0];if(p[1]<y0)y0=p[1];if(p[1]>y1)y1=p[1]}});for(key in topology.objects){bboxGeometry(topology.objects[key])}return[x0,y0,x1,y1]}function reverse_default(array,n){var t,j=array.length,i=j-n;while(i<--j)t=array[i],array[i++]=array[j],array[j]=t}function feature_default(topology,o){if(typeof o===\"string\")o=topology.objects[o];return o.type===\"GeometryCollection\"?{type:\"FeatureCollection\",features:o.geometries.map(function(o2){return feature(topology,o2)})}:feature(topology,o)}function feature(topology,o){var id=o.id,bbox=o.bbox,properties=o.properties==null?{}:o.properties,geometry=object(topology,o);return id==null&&bbox==null?{type:\"Feature\",properties,geometry}:bbox==null?{type:\"Feature\",id,properties,geometry}:{type:\"Feature\",id,bbox,properties,geometry}}function object(topology,o){var transformPoint=transform_default(topology.transform),arcs=topology.arcs;function arc(i,points){if(points.length)points.pop();for(var a=arcs[i<0?~i:i],k=0,n=a.length;k<n;++k){points.push(transformPoint(a[k],k))}if(i<0)reverse_default(points,n)}function point(p){return transformPoint(p)}function line(arcs2){var points=[];for(var i=0,n=arcs2.length;i<n;++i)arc(arcs2[i],points);if(points.length<2)points.push(points[0]);return points}function ring(arcs2){var points=line(arcs2);while(points.length<4)points.push(points[0]);return points}function polygon(arcs2){return arcs2.map(ring)}function geometry(o2){var type=o2.type,coordinates;switch(type){case\"GeometryCollection\":return{type,geometries:o2.geometries.map(geometry)};case\"Point\":coordinates=point(o2.coordinates);break;case\"MultiPoint\":coordinates=o2.coordinates.map(point);break;case\"LineString\":coordinates=line(o2.arcs);break;case\"MultiLineString\":coordinates=o2.arcs.map(line);break;case\"Polygon\":coordinates=polygon(o2.arcs);break;case\"MultiPolygon\":coordinates=o2.arcs.map(polygon);break;default:return null}return{type,coordinates}}return geometry(o)}function stitch_default(topology,arcs){var stitchedArcs={},fragmentByStart={},fragmentByEnd={},fragments=[],emptyIndex=-1;arcs.forEach(function(i,j){var arc=topology.arcs[i<0?~i:i],t;if(arc.length<3&&!arc[1][0]&&!arc[1][1]){t=arcs[++emptyIndex],arcs[emptyIndex]=i,arcs[j]=t}});arcs.forEach(function(i){var e=ends(i),start=e[0],end=e[1],f,g;if(f=fragmentByEnd[start]){delete fragmentByEnd[f.end];f.push(i);f.end=end;if(g=fragmentByStart[end]){delete fragmentByStart[g.start];var fg=g===f?f:f.concat(g);fragmentByStart[fg.start=f.start]=fragmentByEnd[fg.end=g.end]=fg}else{fragmentByStart[f.start]=fragmentByEnd[f.end]=f}}else if(f=fragmentByStart[end]){delete fragmentByStart[f.start];f.unshift(i);f.start=start;if(g=fragmentByEnd[start]){delete fragmentByEnd[g.end];var gf=g===f?f:g.concat(f);fragmentByStart[gf.start=g.start]=fragmentByEnd[gf.end=f.end]=gf}else{fragmentByStart[f.start]=fragmentByEnd[f.end]=f}}else{f=[i];fragmentByStart[f.start=start]=fragmentByEnd[f.end=end]=f}});function ends(i){var arc=topology.arcs[i<0?~i:i],p0=arc[0],p1;if(topology.transform)p1=[0,0],arc.forEach(function(dp){p1[0]+=dp[0],p1[1]+=dp[1]});else p1=arc[arc.length-1];return i<0?[p1,p0]:[p0,p1]}function flush(fragmentByEnd2,fragmentByStart2){for(var k in fragmentByEnd2){var f=fragmentByEnd2[k];delete fragmentByStart2[f.start];delete f.start;delete f.end;f.forEach(function(i){stitchedArcs[i<0?~i:i]=1});fragments.push(f)}}flush(fragmentByEnd,fragmentByStart);flush(fragmentByStart,fragmentByEnd);arcs.forEach(function(i){if(!stitchedArcs[i<0?~i:i])fragments.push([i])});return fragments}function mesh_default(topology){return object(topology,meshArcs.apply(this,arguments))}function meshArcs(topology,object2,filter){var arcs,i,n;if(arguments.length>1)arcs=extractArcs(topology,object2,filter);else for(i=0,arcs=new Array(n=topology.arcs.length);i<n;++i)arcs[i]=i;return{type:\"MultiLineString\",arcs:stitch_default(topology,arcs)}}function extractArcs(topology,object2,filter){var arcs=[],geomsByArc=[],geom;function extract0(i){var j=i<0?~i:i;(geomsByArc[j]||(geomsByArc[j]=[])).push({i,g:geom})}function extract1(arcs2){arcs2.forEach(extract0)}function extract2(arcs2){arcs2.forEach(extract1)}function extract3(arcs2){arcs2.forEach(extract2)}function geometry(o){switch(geom=o,o.type){case\"GeometryCollection\":o.geometries.forEach(geometry);break;case\"LineString\":extract1(o.arcs);break;case\"MultiLineString\":case\"Polygon\":extract2(o.arcs);break;case\"MultiPolygon\":extract3(o.arcs);break}}geometry(object2);geomsByArc.forEach(filter==null?function(geoms){arcs.push(geoms[0].i)}:function(geoms){if(filter(geoms[0].g,geoms[geoms.length-1].g))arcs.push(geoms[0].i)});return arcs}function planarRingArea(ring){var i=-1,n=ring.length,a,b=ring[n-1],area=0;while(++i<n)a=b,b=ring[i],area+=a[0]*b[1]-a[1]*b[0];return Math.abs(area)}function merge_default(topology){return object(topology,mergeArcs.apply(this,arguments))}function mergeArcs(topology,objects){var polygonsByArc={},polygons=[],groups=[];objects.forEach(geometry);function geometry(o){switch(o.type){case\"GeometryCollection\":o.geometries.forEach(geometry);break;case\"Polygon\":extract(o.arcs);break;case\"MultiPolygon\":o.arcs.forEach(extract);break}}function extract(polygon){polygon.forEach(function(ring){ring.forEach(function(arc){(polygonsByArc[arc=arc<0?~arc:arc]||(polygonsByArc[arc]=[])).push(polygon)})});polygons.push(polygon)}function area(ring){return planarRingArea(object(topology,{type:\"Polygon\",arcs:[ring]}).coordinates[0])}polygons.forEach(function(polygon){if(!polygon._){var group=[],neighbors=[polygon];polygon._=1;groups.push(group);while(polygon=neighbors.pop()){group.push(polygon);polygon.forEach(function(ring){ring.forEach(function(arc){polygonsByArc[arc<0?~arc:arc].forEach(function(polygon2){if(!polygon2._){polygon2._=1;neighbors.push(polygon2)}})})})}}});polygons.forEach(function(polygon){delete polygon._});return{type:\"MultiPolygon\",arcs:groups.map(function(polygons2){var arcs=[],n;polygons2.forEach(function(polygon){polygon.forEach(function(ring){ring.forEach(function(arc){if(polygonsByArc[arc<0?~arc:arc].length<2){arcs.push(arc)}})})});arcs=stitch_default(topology,arcs);if((n=arcs.length)>1){for(var i=1,k=area(arcs[0]),ki,t;i<n;++i){if((ki=area(arcs[i]))>k){t=arcs[0],arcs[0]=arcs[i],arcs[i]=t,k=ki}}}return arcs}).filter(function(arcs){return arcs.length>0})}}function bisect_default(a,x){var lo=0,hi=a.length;while(lo<hi){var mid=lo+hi>>>1;if(a[mid]<x)lo=mid+1;else hi=mid}return lo}function neighbors_default(objects){var indexesByArc={},neighbors=objects.map(function(){return[]});function line(arcs,i2){arcs.forEach(function(a){if(a<0)a=~a;var o=indexesByArc[a];if(o)o.push(i2);else indexesByArc[a]=[i2]})}function polygon(arcs,i2){arcs.forEach(function(arc){line(arc,i2)})}function geometry(o,i2){if(o.type===\"GeometryCollection\")o.geometries.forEach(function(o2){geometry(o2,i2)});else if(o.type in geometryType)geometryType[o.type](o.arcs,i2)}var geometryType={LineString:line,MultiLineString:polygon,Polygon:polygon,MultiPolygon:function(arcs,i2){arcs.forEach(function(arc){polygon(arc,i2)})}};objects.forEach(geometry);for(var i in indexesByArc){for(var indexes=indexesByArc[i],m=indexes.length,j=0;j<m;++j){for(var k=j+1;k<m;++k){var ij=indexes[j],ik=indexes[k],n;if((n=neighbors[ij])[i=bisect_default(n,ik)]!==ik)n.splice(i,0,ik);if((n=neighbors[ik])[i=bisect_default(n,ij)]!==ij)n.splice(i,0,ij)}}}return neighbors}function untransform_default(transform){if(transform==null)return identity_default;var x0,y0,kx=transform.scale[0],ky=transform.scale[1],dx=transform.translate[0],dy=transform.translate[1];return function(input,i){if(!i)x0=y0=0;var j=2,n=input.length,output=new Array(n),x1=Math.round((input[0]-dx)/kx),y1=Math.round((input[1]-dy)/ky);output[0]=x1-x0,x0=x1;output[1]=y1-y0,y0=y1;while(j<n)output[j]=input[j],++j;return output}}function quantize_default(topology,transform){if(topology.transform)throw new Error(\"already quantized\");if(!transform||!transform.scale){if(!((n=Math.floor(transform))>=2))throw new Error(\"n must be \\u22652\");box=topology.bbox||bbox_default(topology);var x0=box[0],y0=box[1],x1=box[2],y1=box[3],n;transform={scale:[x1-x0?(x1-x0)/(n-1):1,y1-y0?(y1-y0)/(n-1):1],translate:[x0,y0]}}else{box=topology.bbox}var t=untransform_default(transform),box,key,inputs=topology.objects,outputs={};function quantizePoint(point){return t(point)}function quantizeGeometry(input){var output;switch(input.type){case\"GeometryCollection\":output={type:\"GeometryCollection\",geometries:input.geometries.map(quantizeGeometry)};break;case\"Point\":output={type:\"Point\",coordinates:quantizePoint(input.coordinates)};break;case\"MultiPoint\":output={type:\"MultiPoint\",coordinates:input.coordinates.map(quantizePoint)};break;default:return input}if(input.id!=null)output.id=input.id;if(input.bbox!=null)output.bbox=input.bbox;if(input.properties!=null)output.properties=input.properties;return output}function quantizeArc(input){var i=0,j=1,n2=input.length,p,output=new Array(n2);output[0]=t(input[0],0);while(++i<n2)if((p=t(input[i],i))[0]||p[1])output[j++]=p;if(j===1)output[j++]=[0,0];output.length=j;return output}for(key in inputs)outputs[key]=quantizeGeometry(inputs[key]);return{type:\"Topology\",bbox:box,transform,objects:outputs,arcs:topology.arcs.map(quantizeArc)}}var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}var WORLD_CITY_COORDS={\"new york\":[-74.006,40.7128],\"london\":[-.1278,51.5074],\"tokyo\":[139.6917,35.6895],\"paris\":[2.3522,48.8566],\"beijing\":[116.4074,39.9042],\"sydney\":[151.2093,-33.8688],\"mumbai\":[72.8777,19.076],\"sao paulo\":[-46.6333,-23.5505],\"moscow\":[37.6173,55.7558],\"dubai\":[55.2708,25.2048],\"singapore\":[103.8198,1.3521],\"hong kong\":[114.1694,22.3193],\"los angeles\":[-118.2437,34.0522],\"chicago\":[-87.6298,41.8781],\"berlin\":[13.405,52.52],\"shanghai\":[121.4737,31.2304],\"mexico city\":[-99.1332,19.4326],\"cairo\":[31.2357,30.0444],\"lagos\":[3.3792,6.5244],\"istanbul\":[28.9784,41.0082],\"buenos aires\":[-58.3816,-34.6037],\"jakarta\":[106.845,-6.2088],\"seoul\":[126.978,37.5665],\"toronto\":[-79.3832,43.6532],\"san francisco\":[-122.4194,37.7749],\"rio de janeiro\":[-43.1729,-22.9068],\"cape town\":[18.4241,-33.9249],\"nairobi\":[36.8219,-1.2921],\"bangkok\":[100.5018,13.7563],\"delhi\":[77.1025,28.7041],\"manila\":[120.9842,14.5995],\"lima\":[-77.0428,-12.0464],\"bogota\":[-74.0721,4.711],\"johannesburg\":[28.0473,-26.2041],\"tehran\":[51.389,35.6892],\"karachi\":[67.0011,24.8607],\"dhaka\":[90.4125,23.8103],\"ho chi minh city\":[106.6297,10.8231],\"kuala lumpur\":[101.6869,3.139],\"santiago\":[-70.6693,-33.4489]};var US_CITY_COORDS={\"albany\":[-73.7562,42.6526],\"annapolis\":[-76.4922,38.9784],\"atlanta\":[-84.388,33.749],\"augusta\":[-69.7795,44.3106],\"austin\":[-97.7431,30.2672],\"baton rouge\":[-91.1871,30.4515],\"bismarck\":[-100.779,46.8083],\"boise\":[-116.2023,43.615],\"boston\":[-71.0589,42.3601],\"carson city\":[-119.7674,39.1638],\"charleston\":[-81.6326,38.3498],\"cheyenne\":[-104.8202,41.14],\"columbia\":[-81.0348,34.0007],\"columbus\":[-82.9988,39.9612],\"concord\":[-71.5376,43.2081],\"denver\":[-104.9903,39.7392],\"des moines\":[-93.6091,41.5868],\"dover\":[-75.5243,39.1582],\"frankfort\":[-84.8733,38.2009],\"harrisburg\":[-76.8867,40.2732],\"hartford\":[-72.6823,41.7658],\"helena\":[-112.036,46.5891],\"honolulu\":[-157.8583,21.3069],\"indianapolis\":[-86.1581,39.7684],\"jackson\":[-90.1848,32.2988],\"jefferson city\":[-92.1735,38.5768],\"juneau\":[-134.4197,58.3005],\"lansing\":[-84.5555,42.7325],\"lincoln\":[-96.7026,40.8136],\"little rock\":[-92.2896,34.7465],\"madison\":[-89.4012,43.0731],\"montgomery\":[-86.2999,32.3668],\"montpelier\":[-72.5754,44.2601],\"nashville\":[-86.7816,36.1627],\"oklahoma city\":[-97.5164,35.4676],\"olympia\":[-122.9007,47.0379],\"phoenix\":[-112.074,33.4484],\"pierre\":[-100.3511,44.3683],\"providence\":[-71.4128,41.824],\"raleigh\":[-78.6382,35.7796],\"richmond\":[-77.436,37.5407],\"sacramento\":[-121.4944,38.5816],\"saint paul\":[-93.09,44.9537],\"salem\":[-123.0351,44.9429],\"salt lake city\":[-111.891,40.7608],\"santa fe\":[-105.9378,35.687],\"springfield\":[-89.6501,39.7817],\"tallahassee\":[-84.2807,30.4383],\"topeka\":[-95.6752,39.0473],\"trenton\":[-74.7429,40.2206],\"new york\":[-74.006,40.7128],\"los angeles\":[-118.2437,34.0522],\"chicago\":[-87.6298,41.8781],\"houston\":[-95.3698,29.7604],\"philadelphia\":[-75.1652,39.9526],\"san antonio\":[-98.4936,29.4241],\"san diego\":[-117.1611,32.7157],\"dallas\":[-96.797,32.7767],\"san francisco\":[-122.4194,37.7749],\"seattle\":[-122.3321,47.6062],\"miami\":[-80.1918,25.7617],\"detroit\":[-83.0458,42.3314],\"minneapolis\":[-93.265,44.9778],\"tampa\":[-82.4572,27.9506],\"portland\":[-122.6765,45.5152],\"las vegas\":[-115.1398,36.1699],\"baltimore\":[-76.6122,39.2904],\"milwaukee\":[-87.9065,43.0389],\"albuquerque\":[-106.6504,35.0844],\"tucson\":[-110.9747,32.2226],\"pittsburgh\":[-79.9959,40.4406],\"cincinnati\":[-84.512,39.1031],\"kansas city\":[-94.5786,39.0997],\"st. louis\":[-90.1994,38.627],\"saint louis\":[-90.1994,38.627],\"new orleans\":[-90.0715,29.9511],\"cleveland\":[-81.6944,41.4993],\"orlando\":[-81.3789,28.5383],\"charlotte\":[-80.8431,35.2271],\"san jose\":[-121.8863,37.3382],\"memphis\":[-90.049,35.1495],\"louisville\":[-85.7585,38.2527],\"buffalo\":[-78.8784,42.8864],\"anchorage\":[-149.9003,61.2181]};function renderProportionalSymbol(container,spec){const{config={},encoding,data}=spec;const locationField=config.locationField||encoding.geo&&encoding.geo.field;const valueField=config.valueField||encoding.size&&encoding.size.field;const latField=config.latField||null;const lonField=config.lonField||null;const sizeRange=encoding.size&&encoding.size.range||config.sizeRange||[4,40];const opacity=config.opacity??.7;const mapType=config.mapType||\"world\";const objectName=config.objectName;const customCenter=config.center;const customScale=config.scale;const parallels=config.parallels;const rotate=config.rotate;const projection=config.projection||\"naturalEarth1\";const topojsonData=config.topojsonData;if(!topojsonData){container.innerHTML='<div style=\"color:#ef4444;padding:20px\">TopoJSON data must be embedded at spec-generation time. No CDN fetches.</div>';return}const{svg,g,dims}=createSvg(container,spec,{top:50,right:20,bottom:40,left:20});const tooltip=createTooltip(container);const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const valExtent=d3.extent(allValues);const sizeScale=d3.scaleSqrt().domain(valExtent).range(sizeRange);const colorScale=buildColorScale(encoding.color,data);const cityCoords=mapType===\"us\"?{...WORLD_CITY_COORDS,...US_CITY_COORDS}:{...WORLD_CITY_COORDS};function renderMap(topoData){var features;if(objectName){features=topojson.feature(topoData,topoData.objects[objectName])}else{var objects=topoData.objects;var objKey;if(objects.countries)objKey=\"countries\";else if(objects.states)objKey=\"states\";else objKey=Object.keys(objects)[0];features=topojson.feature(topoData,objects[objKey])}var geoProjection;if(projection===\"albersUsa\"){geoProjection=d3.geoAlbersUsa().fitSize([dims.innerWidth,dims.innerHeight],features)}else{var projName=\"geo\"+projection.charAt(0).toUpperCase()+projection.slice(1);var projFn=d3[projName]||d3.geoNaturalEarth1;geoProjection=projFn();if(rotate)geoProjection.rotate(rotate);if(parallels&&typeof geoProjection.parallels===\"function\")geoProjection.parallels(parallels);if(customScale){if(customCenter)geoProjection.center(customCenter);geoProjection.scale(customScale);geoProjection.translate([dims.innerWidth/2,dims.innerHeight/2])}else{geoProjection.fitSize([dims.innerWidth,dims.innerHeight],features)}}const path=d3.geoPath().projection(geoProjection);g.selectAll(\"path.base\").data(features.features).enter().append(\"path\").attr(\"class\",\"base\").attr(\"d\",path).attr(\"fill\",\"#1a1b25\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",.5);const showLabels=config.showLabels===true;const labelField=config.labelField||locationField;const showRoutes=config.showRoutes===true;const routeGroupField=config.routeGroupField||null;const routeStyle=config.routeStyle||{};const circleData=[];data.forEach(function(d){const val=Number(d[valueField]);if(isNaN(val))return;let coords=null;let lonLat=null;if(latField&&lonField&&d[latField]!=null&&d[lonField]!=null){lonLat=[Number(d[lonField]),Number(d[latField])];const projected=geoProjection(lonLat);if(projected){coords=projected}}else if(locationField){const name=String(d[locationField]).toLowerCase().trim();const known=cityCoords[name];if(known){lonLat=known;const projected=geoProjection(known);if(projected){coords=projected}}}if(!coords||!lonLat)return;circleData.push({x:coords[0],y:coords[1],lon:lonLat[0],lat:lonLat[1],value:val,datum:d})});if(showRoutes&&circleData.length>=2){const routeColor=routeStyle.color||categorical[0];const routeWidth=routeStyle.width??1.5;const routeOpacity=routeStyle.opacity??.6;const routeDash=routeStyle.dash||\"4,3\";if(routeGroupField){const groups=new Map;circleData.forEach(function(cd){});const orderedCircleMap=new Map;circleData.forEach(function(cd){orderedCircleMap.set(cd.datum,cd)});data.forEach(function(d){const cd=orderedCircleMap.get(d);if(!cd)return;const groupVal=String(d[routeGroupField]);if(!groups.has(groupVal))groups.set(groupVal,[]);groups.get(groupVal).push(cd)});let groupIdx=0;groups.forEach(function(points,_groupName){if(points.length<2){groupIdx++;return}const lineCoords=points.map(function(p){return[p.lon,p.lat]});const lineGeo={type:\"LineString\",coordinates:lineCoords};const groupColor=categorical[groupIdx%categorical.length];g.append(\"path\").datum(lineGeo).attr(\"class\",\"route-line\").attr(\"d\",path).attr(\"fill\",\"none\").attr(\"stroke\",groupColor).attr(\"stroke-width\",routeWidth).attr(\"stroke-opacity\",routeOpacity).attr(\"stroke-dasharray\",routeDash).attr(\"stroke-linecap\",\"round\");groupIdx++})}else{const orderedPoints=[];const circleByDatum=new Map;circleData.forEach(function(cd){circleByDatum.set(cd.datum,cd)});data.forEach(function(d){const cd=circleByDatum.get(d);if(cd)orderedPoints.push(cd)});const lineCoords=orderedPoints.map(function(p){return[p.lon,p.lat]});const lineGeo={type:\"LineString\",coordinates:lineCoords};g.append(\"path\").datum(lineGeo).attr(\"class\",\"route-line\").attr(\"d\",path).attr(\"fill\",\"none\").attr(\"stroke\",routeColor).attr(\"stroke-width\",routeWidth).attr(\"stroke-opacity\",routeOpacity).attr(\"stroke-dasharray\",routeDash).attr(\"stroke-linecap\",\"round\")}}circleData.sort((a,b)=>b.value-a.value);g.selectAll(\"circle.symbol\").data(circleData).enter().append(\"circle\").attr(\"class\",\"symbol\").attr(\"cx\",d=>d.x).attr(\"cy\",d=>d.y).attr(\"r\",0).attr(\"fill\",d=>{if(encoding.color&&encoding.color.field){return typeof colorScale===\"function\"?colorScale(d.datum[encoding.color.field]):categorical[0]}return categorical[0]}).attr(\"fill-opacity\",opacity).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",.5).attr(\"stroke-opacity\",.5).on(\"mouseover\",function(event,d){d3.select(this).attr(\"fill-opacity\",1).attr(\"stroke-width\",1.5);let html=\"<strong>\"+d.datum[locationField]+\"</strong>\";html+=\"<br/>\"+valueField+\": \"+formatValue(d.value);if(encoding.color&&encoding.color.field&&encoding.color.field!==locationField){html+=\"<br/>\"+encoding.color.field+\": \"+d.datum[encoding.color.field]}showTooltip(tooltip,html,event)}).on(\"mousemove\",function(event){positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"fill-opacity\",opacity).attr(\"stroke-width\",.5);hideTooltip(tooltip)}).transition().duration(600).delay((_d,i)=>i*20).attr(\"r\",d=>sizeScale(d.value));if(showLabels){g.selectAll(\"text.label\").data(circleData).enter().append(\"text\").attr(\"class\",\"label\").attr(\"x\",d=>{const r=sizeScale(d.value);return d.x>dims.innerWidth*.85?d.x-r-4:d.x+r+4}).attr(\"y\",d=>d.y+3).attr(\"text-anchor\",d=>d.x>dims.innerWidth*.85?\"end\":\"start\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",d=>{const r=sizeScale(d.value);return Math.max(9,Math.min(12,r*.8))+\"px\"}).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").attr(\"opacity\",d=>sizeScale(d.value)<3?0:1).text(d=>truncateLabel(String(d.datum[labelField]||\"\"),18))}const legendSizes=[valExtent[0],(valExtent[0]+valExtent[1])/2,valExtent[1]];const rawMaxR=sizeScale(valExtent[1]);const maxR=Math.min(rawMaxR,dims.innerHeight*.06,22);const legendScale=maxR/rawMaxR;const legendPadding=8;const legendCircleWidth=maxR*2;const legendTextWidth=40;const legendWidth=legendCircleWidth+legendTextWidth+legendPadding*2+8;const legendHeight=maxR*2+legendPadding*2;const legendX=4;const legendY=dims.innerHeight-legendHeight-4;const legendG=g.append(\"g\").attr(\"transform\",\"translate(\"+legendX+\",\"+legendY+\")\");legendG.append(\"rect\").attr(\"x\",0).attr(\"y\",0).attr(\"width\",legendWidth).attr(\"height\",legendHeight).attr(\"rx\",4).attr(\"fill\",DARK_BG).attr(\"fill-opacity\",.75).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-opacity\",.3);const circleBaseX=legendPadding+maxR;const circleBaseY=legendPadding+maxR*2;const labelPositions=[];const minLabelGap=12;legendSizes.forEach(function(val){const r=sizeScale(val)*legendScale;const cy=circleBaseY-r;legendG.append(\"circle\").attr(\"cx\",circleBaseX).attr(\"cy\",cy).attr(\"r\",r).attr(\"fill\",\"none\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);let labelY=cy+3;for(const prev of labelPositions){if(Math.abs(labelY-prev)<minLabelGap){labelY=prev-minLabelGap}}labelPositions.push(labelY);legendG.append(\"text\").attr(\"x\",circleBaseX+maxR+8).attr(\"y\",labelY).attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(formatValue(val))})}renderMap(topojsonData)}globalThis.topojson=src_exports;return __toCommonJS(proportional_symbol_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
31
|
+
export const radarBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var radar_render_exports={};__export(radar_render_exports,{renderChart:()=>renderRadar});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderRadar(container,spec){const{config,data}=spec;const categoryField=config.categoryField||\"entity\";const dimensions=config.dimensions||[];const showLabels=config.showLabels!==false;const showGrid=config.showGrid!==false;const gridLevels=config.gridLevels||5;const fillOpacity=config.fillOpacity??.2;const strokeWidth=config.strokeWidth??2;const dotRadius=config.dotRadius??4;if(dimensions.length===0)return;const hasLegend=data.length>1;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const containerWidth=container.clientWidth||500;const containerHeight=container.clientHeight||500;const isSmall=Math.min(containerWidth,containerHeight)<320;const labelMargin=isSmall?40:55;const{svg,g,dims}=createSvg(chartWrapper,spec,{top:spec.title?55:40,right:labelMargin,bottom:40,left:labelMargin});const tooltip=createTooltip(container);const radius=Math.min(dims.innerWidth,dims.innerHeight)/2;const cx=dims.innerWidth/2;const cy=dims.innerHeight/2;const center=g.append(\"g\").attr(\"transform\",`translate(${cx}, ${cy})`);const angleSlice=Math.PI*2/dimensions.length;let minVal=0;let maxVal=0;for(const row of data){for(const dim of dimensions){const v=Number(row[dim])||0;if(v<minVal)minVal=v;if(v>maxVal)maxVal=v}}if(maxVal===0&&minVal===0)maxVal=1;const rScale=d3.scaleLinear().domain([minVal,maxVal]).range([0,radius]);if(showGrid){for(let level=1;level<=gridLevels;level++){const r=radius/gridLevels*level;const points=dimensions.map((_,i)=>{const angle=angleSlice*i-Math.PI/2;return[r*Math.cos(angle),r*Math.sin(angle)]});center.append(\"polygon\").attr(\"points\",points.map(p=>p.join(\",\")).join(\" \")).attr(\"fill\",\"none\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5);const labelVal=minVal+(maxVal-minVal)/gridLevels*level;center.append(\"text\").attr(\"x\",4).attr(\"y\",-r).attr(\"fill\",TEXT_MUTED).attr(\"font-size\",isSmall?\"8px\":\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"opacity\",.6).text(formatValue(Math.round(labelVal*100)/100))}}if(minVal<0){const zeroR=rScale(0);const zeroPoints=dimensions.map((_,i)=>{const angle=angleSlice*i-Math.PI/2;return[zeroR*Math.cos(angle),zeroR*Math.sin(angle)]});center.append(\"polygon\").attr(\"points\",zeroPoints.map(p=>p.join(\",\")).join(\" \")).attr(\"fill\",\"none\").attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"opacity\",.5)}const maxLabelLen=isSmall?10:16;dimensions.forEach((dim,i)=>{const angle=angleSlice*i-Math.PI/2;const lineX=radius*Math.cos(angle);const lineY=radius*Math.sin(angle);center.append(\"line\").attr(\"x1\",0).attr(\"y1\",0).attr(\"x2\",lineX).attr(\"y2\",lineY).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);if(showLabels){const labelR=radius+(isSmall?10:14);const lx=labelR*Math.cos(angle);const ly=labelR*Math.sin(angle);const anchor=Math.abs(lx)<1?\"middle\":lx>0?\"start\":\"end\";center.append(\"text\").attr(\"x\",lx).attr(\"y\",ly).attr(\"text-anchor\",anchor).attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",isSmall?\"9px\":\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(truncateLabel(dim,maxLabelLen))}});const entityNames=data.map(d=>String(d[categoryField]));const colorEncoding=data.length>1?{field:categoryField,type:\"nominal\"}:void 0;const colorScale=buildColorScale(colorEncoding,data);function getPolygonPoints(row){return dimensions.map((dim,i)=>{const val=Number(row[dim])||0;const angle=angleSlice*i-Math.PI/2;const r=rScale(val);return[r*Math.cos(angle),r*Math.sin(angle)]})}const effectiveDotRadius=isSmall?Math.min(dotRadius,3):dotRadius;let activeEntity=null;function highlightEntity(entity){activeEntity=entity;if(entity===null){center.selectAll(\".radar-polygon\").attr(\"fill-opacity\",fillOpacity).attr(\"stroke-width\",strokeWidth);center.selectAll(\".radar-dot\").attr(\"opacity\",1)}else{center.selectAll(\".radar-polygon\").each(function(){const el=d3.select(this);const isMatch=el.attr(\"data-entity\")===entity;el.attr(\"fill-opacity\",isMatch?Math.min(fillOpacity+.15,.5):fillOpacity*.3).attr(\"stroke-width\",isMatch?strokeWidth+1:strokeWidth*.5)});center.selectAll(\".radar-dot\").each(function(){const el=d3.select(this);const isMatch=el.attr(\"data-entity\")===entity;el.attr(\"opacity\",isMatch?1:.15)})}}data.forEach((row,entityIdx)=>{const entity=String(row[categoryField]);const color=colorScale(entity);const points=getPolygonPoints(row);const pointsStr=points.map(p=>p.join(\",\")).join(\" \");center.append(\"polygon\").attr(\"class\",\"radar-polygon\").attr(\"data-entity\",entity).attr(\"points\",pointsStr).attr(\"fill\",color).attr(\"fill-opacity\",fillOpacity).attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"stroke-linejoin\",\"round\").style(\"cursor\",\"pointer\").on(\"mouseover\",event=>{highlightEntity(entity);const dimValues=dimensions.map(dim=>{const val=Number(row[dim])||0;return`${truncateLabel(dim,14)}: ${formatValue(val)}`}).join(\"<br/>\");showTooltip(tooltip,`<strong>${entity}</strong><br/>${dimValues}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",()=>{highlightEntity(null);hideTooltip(tooltip)});if(effectiveDotRadius>0){points.forEach((p,i)=>{const dim=dimensions[i];const val=Number(row[dim])||0;center.append(\"circle\").attr(\"class\",\"radar-dot\").attr(\"data-entity\",entity).attr(\"cx\",p[0]).attr(\"cy\",p[1]).attr(\"r\",effectiveDotRadius).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).style(\"cursor\",\"pointer\").on(\"mouseover\",event=>{highlightEntity(entity);d3.select(event.currentTarget).attr(\"r\",effectiveDotRadius*1.5);showTooltip(tooltip,`<strong>${entity}</strong><br/>${dim}: ${formatValue(val)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",event=>{highlightEntity(null);d3.select(event.currentTarget).attr(\"r\",effectiveDotRadius);hideTooltip(tooltip)})})}});if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"circle\",callbacks:{onHover:entity=>highlightEntity(entity),onLeave:()=>highlightEntity(null)}});container.appendChild(legendDiv)}}return __toCommonJS(radar_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
32
|
+
export const ridgelineBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var ridgeline_render_exports={};__export(ridgeline_render_exports,{renderChart:()=>renderRidgeline});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function gaussianKernel(u){return 1/Math.sqrt(2*Math.PI)*Math.exp(-.5*u*u)}function stdDev(values){const n=values.length;if(n<2)return 1;const mean=values.reduce((s,v)=>s+v,0)/n;const variance=values.reduce((s,v)=>s+(v-mean)**2,0)/(n-1);return Math.sqrt(variance)}function kde(values,samplePoints,bandwidth){const n=values.length;return samplePoints.map(x=>{const density=values.reduce((sum,xi)=>sum+gaussianKernel((x-xi)/bandwidth),0)/(n*bandwidth);return{value:x,density}})}function silvermanBandwidth(values){const sd=stdDev(values);const n=values.length;const bw=1.06*sd*Math.pow(n,-.2);if(bw>0)return bw;const range=Math.max(...values)-Math.min(...values);return range>0?range*.1:1}function median(sorted){const n=sorted.length;if(n===0)return 0;return n%2===1?sorted[Math.floor(n/2)]:(sorted[n/2-1]+sorted[n/2])/2}function renderRidgeline(container,spec){const{config,encoding,data}=spec;const valueField=config.valueField||encoding.x?.field||Object.keys(data[0]).find(k=>typeof data[0][k]===\"number\")||Object.keys(data[0])[1];const categoryField=config.categoryField||encoding.y?.field||Object.keys(data[0])[0];const overlap=config.overlap??.5;const fillOpacity=config.fillOpacity??.7;const strokeWidth=config.strokeWidth??1.5;const userBandwidth=typeof config.bandwidth===\"number\"?config.bandwidth:void 0;const groups=[...new Set(data.map(d=>d[categoryField]))];const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const colorScale=buildColorScale(encoding.color,data);const containerWidth=container.clientWidth||800;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);const showBottomLegend=groups.length>1&&containerWidth<600;if(showBottomLegend){const legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}const groupLabels=groups.map(String);const leftMargin=showBottomLegend?20:calculateLeftMargin(groupLabels);const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin,bottom:50,right:30,top:40});const tooltip=createTooltip(container);const valuePadding=(d3.max(allValues)-d3.min(allValues))*.05||1;const xScale=d3.scaleLinear().domain([d3.min(allValues)-valuePadding,d3.max(allValues)+valuePadding]).range([0,dims.innerWidth]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const effectiveRows=groups.length*(1-overlap)+overlap;const rawRowHeight=dims.innerHeight/effectiveRows;const rowHeight=groups.length===1?Math.min(rawRowHeight,dims.innerHeight*.4):rawRowHeight;const xDomain=xScale.domain();const sampleCount=80;const step=(xDomain[1]-xDomain[0])/(sampleCount-1);const samplePoints=Array.from({length:sampleCount},(_,i)=>xDomain[0]+i*step);const groupKDEs=[];let globalMaxDensity=0;groups.forEach(group=>{const groupValues=data.filter(d=>d[categoryField]===group).map(d=>Number(d[valueField])).filter(v=>!isNaN(v)).sort((a,b)=>a-b);if(groupValues.length===0){groupKDEs.push({group,density:samplePoints.map(v=>({value:v,density:0})),values:groupValues});return}const bandwidth=userBandwidth||silvermanBandwidth(groupValues);const densityPoints=kde(groupValues,samplePoints,bandwidth);const maxDensity=d3.max(densityPoints,d=>d.density)||0;if(maxDensity>globalMaxDensity)globalMaxDensity=maxDensity;groupKDEs.push({group,density:densityPoints,values:groupValues})});if(globalMaxDensity===0)globalMaxDensity=1;for(let i=0;i<groups.length;i++){const{group,values:groupValues}=groupKDEs[i];const yBaseline=dims.innerHeight-i*rowHeight*(1-overlap);const yTop=yBaseline-rowHeight;g.append(\"rect\").attr(\"class\",\"ridge-hover-target\").attr(\"x\",0).attr(\"y\",yTop).attr(\"width\",dims.innerWidth).attr(\"height\",rowHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){g.selectAll(`.ridge-${i}`).attr(\"fill-opacity\",Math.min(fillOpacity+.2,1)).attr(\"stroke-width\",strokeWidth+1);const med=groupValues.length>0?median(groupValues):0;const min=groupValues.length>0?groupValues[0]:0;const max=groupValues.length>0?groupValues[groupValues.length-1]:0;showTooltip(tooltip,`<strong>${group}</strong><br/>Count: ${groupValues.length}<br/>Median: ${formatValue(med)}<br/>Min: ${formatValue(min)}<br/>Max: ${formatValue(max)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(`.ridge-${i}`).attr(\"fill-opacity\",fillOpacity).attr(\"stroke-width\",strokeWidth);hideTooltip(tooltip)})}const singleGroupOffset=groups.length===1?(dims.innerHeight-rowHeight)/2:0;for(let i=groups.length-1;i>=0;i--){const{group,density}=groupKDEs[i];const yBaseline=dims.innerHeight-i*rowHeight*(1-overlap)-singleGroupOffset;const heightScale=d=>d/globalMaxDensity*rowHeight;const colorValue=encoding.color?.field?data.find(d=>d[categoryField]===group)?.[encoding.color.field]:group;const fillColor=colorScale(colorValue);const areaGen=d3.area().x(d=>xScale(d.value)).y0(yBaseline).y1(d=>yBaseline-heightScale(d.density)).curve(d3.curveBasis);g.append(\"path\").datum(density).attr(\"d\",areaGen).attr(\"fill\",DARK_BG).attr(\"stroke\",\"none\").attr(\"pointer-events\",\"none\");g.append(\"path\").datum(density).attr(\"class\",`ridge ridge-${i}`).attr(\"d\",areaGen).attr(\"fill\",fillColor).attr(\"fill-opacity\",fillOpacity).attr(\"stroke\",fillColor).attr(\"stroke-width\",strokeWidth).attr(\"stroke-opacity\",.9).attr(\"pointer-events\",\"none\");if(!showBottomLegend){g.append(\"text\").attr(\"x\",-10).attr(\"y\",yBaseline).attr(\"text-anchor\",\"end\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(truncateLabel(String(group),18))}}}return __toCommonJS(ridgeline_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
33
|
+
export const sankeyBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var sankey_render_exports={};__export(sankey_render_exports,{renderChart:()=>renderSankey});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function computeSankeyLayout(nodeNames,linkData,width,height,nodeWidth,nodePadding){const nodeMap=new Map;nodeNames.forEach(name=>{nodeMap.set(name,{name,x0:0,x1:0,y0:0,y1:0,value:0,sourceLinks:[],targetLinks:[],layer:0})});const links=linkData.map(l=>{const source=nodeMap.get(l.source);const target=nodeMap.get(l.target);if(!source||!target)return null;const link={source,target,value:l.value,width:0,y0:0,y1:0};source.sourceLinks.push(link);target.targetLinks.push(link);return link}).filter(Boolean);const nodes=[...nodeMap.values()];computeNodeValues(nodes);assignLayers(nodes);positionNodes(nodes,width,height,nodeWidth,nodePadding);computeLinkPositions(nodes,links);return{nodes,links}}function computeNodeValues(nodes){nodes.forEach(node=>{const outSum=node.sourceLinks.reduce((s,l)=>s+l.value,0);const inSum=node.targetLinks.reduce((s,l)=>s+l.value,0);node.value=Math.max(outSum,inSum)})}function assignLayers(nodes){const sources=nodes.filter(n=>n.targetLinks.length===0);const visited=new Set;const queue=sources.map(n=>({node:n,layer:0}));while(queue.length>0){const{node,layer}=queue.shift();if(visited.has(node.name))continue;visited.add(node.name);node.layer=layer;node.sourceLinks.forEach(link=>{if(!visited.has(link.target.name)){queue.push({node:link.target,layer:layer+1})}})}nodes.forEach(n=>{if(!visited.has(n.name)){n.layer=0;visited.add(n.name)}})}function positionNodes(nodes,width,height,nodeWidth,nodePadding){const maxLayer=d3.max(nodes,n=>n.layer)||0;const layerGap=maxLayer>0?(width-nodeWidth)/maxLayer:0;nodes.forEach(node=>{node.x0=node.layer*layerGap;node.x1=node.x0+nodeWidth});const layers=[];for(let i=0;i<=maxLayer;i++){layers[i]=nodes.filter(n=>n.layer===i)}layers.forEach(layerNodes=>{layerNodes.sort((a,b)=>b.value-a.value);const totalValue=layerNodes.reduce((s,n)=>s+n.value,0);const totalPadding=(layerNodes.length-1)*nodePadding;const availableHeight=height-totalPadding;const scale=totalValue>0?availableHeight/totalValue:1;const MIN_NODE_HEIGHT=3;let y=0;layerNodes.forEach(node=>{node.y0=y;node.y1=y+Math.max(node.value*scale,MIN_NODE_HEIGHT);y=node.y1+nodePadding});const excess=y-nodePadding-height;if(excess>0&&layerNodes.length>0){const compressionFactor=height/(y-nodePadding);let cy=0;layerNodes.forEach(node=>{const h=(node.y1-node.y0)*compressionFactor;node.y0=cy;node.y1=cy+h;cy+=h+nodePadding*compressionFactor})}})}function computeLinkPositions(nodes,links){const MIN_LINK_WIDTH=2;links.forEach(link=>{const sourceTotal=link.source.value||1;const sourceHeight=link.source.y1-link.source.y0;link.width=Math.max(link.value/sourceTotal*sourceHeight,MIN_LINK_WIDTH)});nodes.forEach(node=>{let sy=node.y0;node.sourceLinks.sort((a,b)=>a.target.y0-b.target.y0);node.sourceLinks.forEach(link=>{link.y0=sy;sy+=link.width});let ty=node.y0;node.targetLinks.sort((a,b)=>a.source.y0-b.source.y0);node.targetLinks.forEach(link=>{const targetTotal=node.value||1;const targetHeight=node.y1-node.y0;const w=Math.max(link.value/targetTotal*targetHeight,MIN_LINK_WIDTH);link.y1=ty;link.width=Math.min(link.width,w)||link.width;ty+=w})})}function renderSankey(container,spec){const{config,encoding,data}=spec;const sourceField=config.sourceField||encoding.source?.field;const targetField=config.targetField||encoding.target?.field;const valueField=config.valueField||encoding.size?.field;const nodeWidth=config.nodeWidth??20;const nodePadding=config.nodePadding??10;const linkOpacity=config.linkOpacity??.4;const{svg,g,dims}=createSvg(container,spec,{top:40,left:20,right:20,bottom:20});const tooltip=createTooltip(container);if(valueField&&isAllZeros(data,valueField)){renderEmptyState(g,dims);return}let nodeNames;let linkData;if(config.nodes&&config.links){nodeNames=config.nodes.map(n=>n.name);linkData=config.links}else{const sources=data.map(d=>String(d[sourceField]));const targets=data.map(d=>String(d[targetField]));nodeNames=[...new Set([...sources,...targets])];linkData=data.map(d=>({source:String(d[sourceField]),target:String(d[targetField]),value:Number(d[valueField])||1}))}const{nodes,links}=computeSankeyLayout(nodeNames,linkData,dims.innerWidth,dims.innerHeight,nodeWidth,nodePadding);const nodeColorScale=d3.scaleOrdinal().domain(nodeNames).range(categorical);drawLinks(g,links,nodeColorScale,linkOpacity,tooltip);drawNodes(g,nodes,nodeColorScale,dims,tooltip);if(config.showLabels!==false){drawNodeLabels(g,nodes,config,dims)}}function drawLinks(g,links,colorScale,linkOpacity,tooltip){const linkPath=link=>{const sx=link.source.x1;const tx=link.target.x0;const mx=(sx+tx)/2;const sy0=link.y0;const ty0=link.y1;const w=link.width;return`\n M ${sx},${sy0}\n C ${mx},${sy0} ${mx},${ty0} ${tx},${ty0}\n L ${tx},${ty0+w}\n C ${mx},${ty0+w} ${mx},${sy0+w} ${sx},${sy0+w}\n Z\n `};g.selectAll(\".sankey-link\").data(links).join(\"path\").attr(\"class\",\"sankey-link\").attr(\"d\",linkPath).attr(\"fill\",d=>colorScale(d.source.name)).attr(\"opacity\",linkOpacity).attr(\"stroke\",\"none\").on(\"mouseover\",function(event,d){d3.select(this).attr(\"opacity\",linkOpacity+.3);showTooltip(tooltip,`<strong>${d.source.name} \\u2192 ${d.target.name}</strong><br/>Value: ${formatValue(d.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"opacity\",linkOpacity);hideTooltip(tooltip)})}function drawNodes(g,nodes,colorScale,dims,tooltip){g.selectAll(\".sankey-node\").data(nodes).join(\"rect\").attr(\"class\",\"sankey-node\").attr(\"x\",d=>d.x0).attr(\"y\",d=>d.y0).attr(\"width\",d=>d.x1-d.x0).attr(\"height\",d=>Math.max(d.y1-d.y0,3)).attr(\"fill\",d=>colorScale(d.name)).attr(\"rx\",2).attr(\"stroke\",\"#0f1117\").attr(\"stroke-width\",1).on(\"mouseover\",function(event,d){d3.select(this).attr(\"opacity\",.8);const inflow=d.targetLinks.reduce((s,l)=>s+l.value,0);const outflow=d.sourceLinks.reduce((s,l)=>s+l.value,0);let html=`<strong>${d.name}</strong><br/>Total: ${formatValue(d.value)}`;if(inflow>0)html+=`<br/>Inflow: ${formatValue(inflow)}`;if(outflow>0)html+=`<br/>Outflow: ${formatValue(outflow)}`;showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"opacity\",1);hideTooltip(tooltip)})}function drawNodeLabels(g,nodes,config,dims){g.selectAll(\".sankey-label\").data(nodes).join(\"text\").attr(\"class\",\"sankey-label\").attr(\"x\",d=>{if(d.x0<dims.innerWidth/2)return d.x1+6;return d.x0-6}).attr(\"y\",d=>(d.y0+d.y1)/2).attr(\"dy\",\"0.35em\").attr(\"text-anchor\",d=>d.x0<dims.innerWidth/2?\"start\":\"end\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>{const isRight=d.x0>=dims.innerWidth/2;const availChars=isRight?Math.max(10,Math.floor((d.x0-6)/6.5)):Math.max(10,Math.floor((dims.innerWidth-d.x1-6)/6.5));const label=truncateLabel(d.name,Math.min(availChars,30));if(config.showValues!==false)return`${label} (${formatValue(d.value)})`;return label})}return __toCommonJS(sankey_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
34
|
+
export const scatterBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var scatter_render_exports={};__export(scatter_render_exports,{renderChart:()=>renderScatter});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderScatter(container,spec){const{config,encoding,data}=spec;const xField=config.xField||encoding.x?.field;const yField=config.yField||encoding.y?.field;const colorField=config.colorField||encoding.color?.field||null;const sizeField=config.sizeField||encoding.size?.field||null;const baseRadius=config.dotRadius??5;const opacity=config.opacity??.7;const hasLegend=colorField!==null;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const{svg,g,dims}=createSvg(chartWrapper,spec,{right:30});const tooltip=createTooltip(container);const xValues=data.map(d=>Number(d[xField]));const yValues=data.map(d=>Number(d[yField]));const xExtent=d3.extent(xValues);const yExtent=d3.extent(yValues);const xPad=(xExtent[1]-xExtent[0])*.05||1;const yPad=(yExtent[1]-yExtent[0])*.05||1;const xScale=d3.scaleLinear().domain([xExtent[0]-xPad,xExtent[1]+xPad]).range([0,dims.innerWidth]).nice();const yScale=d3.scaleLinear().domain([yExtent[0]-yPad,yExtent[1]+yPad]).range([dims.innerHeight,0]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const colorScale=buildColorScale(encoding.color,data);let sizeScale=()=>baseRadius;if(sizeField){const sizeExtent=d3.extent(data,d=>Number(d[sizeField]));const maxBubbleRadius=Math.min(dims.innerWidth,dims.innerHeight)*.06;const sizeRange=encoding.size?.range||[3,20];const clampedRange=[Math.min(sizeRange[0],maxBubbleRadius),Math.min(sizeRange[1],maxBubbleRadius)];sizeScale=d3.scaleSqrt().domain(sizeExtent).range(clampedRange)}const pointDensity=data.length/(dims.innerWidth*dims.innerHeight/1e4);let dotRadius=baseRadius;if(!sizeField){if(pointDensity>5)dotRadius=Math.max(2,baseRadius-2);else if(pointDensity>2)dotRadius=Math.max(3,baseRadius-1)}const jitter=config.jitter??0;const pointPositions=data.map((d,i)=>{const xBase=xScale(Number(d[xField]));const yBase=yScale(Number(d[yField]));return{d,i,cx:jitter?xBase+(seededJitter(i,0)-.5)*jitter:xBase,cy:jitter?yBase+(seededJitter(i,1)-.5)*jitter:yBase,r:sizeField?sizeScale(Number(d[sizeField])):dotRadius}});const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").filter((_,j)=>j===p.i).attr(\"r\",p.r*1.5).attr(\"opacity\",1);let html=`<strong>${encoding.x?.title||xField}</strong>: ${formatValue(Number(p.d[xField]))}<br/><strong>${encoding.y?.title||yField}</strong>: ${formatValue(Number(p.d[yField]))}`;if(colorField)html+=`<br/>${colorField}: ${p.d[colorField]}`;if(sizeField)html+=`<br/>${sizeField}: ${formatValue(Number(p.d[sizeField]))}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity);activeIdx=-1}hideTooltip(tooltip)});g.selectAll(\".dot\").data(pointPositions).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",p=>p.cx).attr(\"cy\",p=>p.cy).attr(\"r\",p=>p.r).attr(\"fill\",p=>colorField?colorScale(p.d[colorField]):categorical[0]).attr(\"opacity\",opacity).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).attr(\"pointer-events\",\"none\");if(config.showTrendLine||config.showRegressionLine){const validData=data.map(d=>({x:Number(d[xField]),y:Number(d[yField])})).filter(d=>!isNaN(d.x)&&!isNaN(d.y));if(validData.length>=2){const n=validData.length;const sumX=validData.reduce((s,d)=>s+d.x,0);const sumY=validData.reduce((s,d)=>s+d.y,0);const sumXY=validData.reduce((s,d)=>s+d.x*d.y,0);const sumX2=validData.reduce((s,d)=>s+d.x*d.x,0);const denom=n*sumX2-sumX*sumX;if(Math.abs(denom)>1e-10){const slope=(n*sumXY-sumX*sumY)/denom;const intercept=(sumY-slope*sumX)/n;const x1=xExtent[0];const x2=xExtent[1];g.append(\"line\").attr(\"x1\",xScale(x1)).attr(\"y1\",yScale(slope*x1+intercept)).attr(\"x2\",xScale(x2)).attr(\"y2\",yScale(slope*x2+intercept)).attr(\"stroke\",\"#f59e0b\").attr(\"stroke-width\",1.5).attr(\"stroke-dasharray\",\"6,4\").attr(\"opacity\",.7).attr(\"pointer-events\",\"none\")}}}if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"circle\",callbacks:{onHover:category=>{g.selectAll(\".dot\").each(function(_,j){const p=pointPositions[j];const isMatch=p.d[colorField]===category;d3.select(this).attr(\"opacity\",isMatch?1:.08).attr(\"r\",isMatch?p.r*1.3:p.r)})},onLeave:()=>{g.selectAll(\".dot\").each(function(_,j){const p=pointPositions[j];d3.select(this).attr(\"opacity\",opacity).attr(\"r\",p.r)})}}});container.appendChild(legendDiv)}}function seededJitter(index,axis){let s=(index+1)*16807+axis*12345;s=(s*16807+0)%2147483647;return(s-1)/2147483646}return __toCommonJS(scatter_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
35
|
+
export const slopeChartBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var slope_chart_render_exports={};__export(slope_chart_render_exports,{renderChart:()=>renderSlopeChart});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function resolveCollisions(labels,minSpacing,minY,maxY){const passes=Math.min(labels.length,8);for(let pass=0;pass<passes;pass++){for(let i=1;i<labels.length;i++){const overlap=labels[i-1].y+minSpacing-labels[i].y;if(overlap>0){labels[i-1].y-=overlap/2;labels[i].y+=overlap/2}}}for(let i=1;i<labels.length;i++){if(labels[i].y<labels[i-1].y+minSpacing){labels[i].y=labels[i-1].y+minSpacing}}if(minY!=null||maxY!=null){if(maxY!=null&&labels.length>0&&labels[labels.length-1].y>maxY){labels[labels.length-1].y=maxY;for(let i=labels.length-2;i>=0;i--){if(labels[i].y>labels[i+1].y-minSpacing){labels[i].y=labels[i+1].y-minSpacing}}}if(minY!=null&&labels.length>0&&labels[0].y<minY){labels[0].y=minY;for(let i=1;i<labels.length;i++){if(labels[i].y<labels[i-1].y+minSpacing){labels[i].y=labels[i-1].y+minSpacing}}}}}function renderSlopeChart(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field;const valueField=config.valueField||encoding.y?.field;const timeField=config.timeField||encoding.x?.field;const periods=config.periods||[...new Set(data.map(d=>d[timeField]))].slice(0,2);const categories=[...new Set(data.map(d=>d[categoryField]))];const maxCatLen=Math.max(...categories.map(c=>String(c).length));const truncLen=Math.min(maxCatLen,20);const leftMarginEstimate=Math.max(100,Math.min(200,truncLen*7+60));const{svg,g,dims}=createSvg(container,spec,{left:leftMarginEstimate,right:100});const tooltip=createTooltip(container);const grouped={};categories.forEach(cat=>{grouped[cat]={};data.filter(d=>d[categoryField]===cat).forEach(d=>{grouped[cat][d[timeField]]=Number(d[valueField])})});const allValues=data.map(d=>Number(d[valueField]));const yScale=d3.scaleLinear().domain([d3.min(allValues)*.9,d3.max(allValues)*1.1]).range([dims.innerHeight,0]).nice();const xScale=d3.scalePoint().domain(periods).range([0,dims.innerWidth]).padding(0);const colorScale=buildColorScale(encoding.color,data);periods.forEach(period=>{g.append(\"line\").attr(\"x1\",xScale(period)).attr(\"y1\",0).attr(\"x2\",xScale(period)).attr(\"y2\",dims.innerHeight).attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",1);g.append(\"text\").attr(\"x\",xScale(period)).attr(\"y\",dims.innerHeight+25).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"13px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(String(period))});if(periods.length<=1){const singlePeriod=periods[0];const dotX=dims.innerWidth/2;const singleData=categories.map(cat=>{const catStr=cat;const vals=grouped[catStr];if(vals[singlePeriod]==null)return null;return{category:catStr,value:vals[singlePeriod],color:colorScale(cat)}}).filter(Boolean);const minLabelSpacing=14;const labels=singleData.map(d=>({...d,y:yScale(d.value)})).sort((a,b)=>a.y-b.y);resolveCollisions(labels,minLabelSpacing,0,dims.innerHeight-10);labels.forEach(d=>{g.append(\"circle\").attr(\"cx\",dotX).attr(\"cy\",yScale(d.value)).attr(\"r\",6).attr(\"fill\",d.color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",2).attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){d3.select(this).attr(\"r\",8);showTooltip(tooltip,`<strong>${d.category}</strong><br/>${singlePeriod}: ${formatValue(d.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){d3.select(this).attr(\"r\",6);hideTooltip(tooltip)});g.append(\"text\").attr(\"x\",dotX-14).attr(\"y\",d.y+4).attr(\"text-anchor\",\"end\").attr(\"fill\",d.color).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d.category);g.append(\"text\").attr(\"x\",dotX+14).attr(\"y\",d.y+4).attr(\"text-anchor\",\"start\").attr(\"fill\",d.color).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(d.value))});return}const lineData=categories.map(cat=>{const catStr=cat;const vals=grouped[catStr];if(vals[periods[0]]==null||vals[periods[1]]==null)return null;return{category:catStr,vals,y1:yScale(vals[periods[0]]),y2:yScale(vals[periods[1]]),color:colorScale(cat)}}).filter(Boolean);lineData.forEach(d=>{g.append(\"line\").attr(\"class\",\"slope-hover-target\").attr(\"x1\",xScale(periods[0])).attr(\"y1\",d.y1).attr(\"x2\",xScale(periods[1])).attr(\"y2\",d.y2).attr(\"stroke\",\"transparent\").attr(\"stroke-width\",16).attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event){g.select(`.slope-line-${CSS.escape(d.category)}`).attr(\"stroke-width\",4).attr(\"opacity\",1);g.selectAll(`.slope-dot-${CSS.escape(d.category)}`).attr(\"r\",6);const change=d.vals[periods[1]]-d.vals[periods[0]];const pctChange=(change/d.vals[periods[0]]*100).toFixed(1);showTooltip(tooltip,`<strong>${d.category}</strong><br/>${periods[0]}: ${formatValue(d.vals[periods[0]])}<br/>${periods[1]}: ${formatValue(d.vals[periods[1]])}<br/>Change: ${change>=0?\"+\":\"\"}${pctChange}%`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.select(`.slope-line-${CSS.escape(d.category)}`).attr(\"stroke-width\",2.5).attr(\"opacity\",.8);g.selectAll(`.slope-dot-${CSS.escape(d.category)}`).attr(\"r\",5);hideTooltip(tooltip)})});lineData.forEach(d=>{g.append(\"line\").attr(\"class\",`slope-line-${d.category}`).attr(\"x1\",xScale(periods[0])).attr(\"y1\",d.y1).attr(\"x2\",xScale(periods[1])).attr(\"y2\",d.y2).attr(\"stroke\",d.color).attr(\"stroke-width\",2.5).attr(\"opacity\",.8).attr(\"pointer-events\",\"none\");[periods[0],periods[1]].forEach(period=>{g.append(\"circle\").attr(\"class\",`slope-dot-${d.category}`).attr(\"cx\",xScale(period)).attr(\"cy\",yScale(d.vals[period])).attr(\"r\",5).attr(\"fill\",d.color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",2).attr(\"pointer-events\",\"none\")})});if(config.showLabels!==false){const isMany=lineData.length>15;const fontSize=isMany?\"9px\":\"11px\";const minLabelSpacing=isMany?10:12;const labelBoundsMin=0;const labelBoundsMax=dims.innerHeight-10;const maxLeftChars=isMany?12:truncLen;const leftLabels=lineData.map(d=>({category:d.category,y:d.y1,value:d.vals[periods[0]],color:d.color})).sort((a,b)=>a.y-b.y);resolveCollisions(leftLabels,minLabelSpacing,labelBoundsMin,labelBoundsMax);leftLabels.forEach(lbl=>{const catLabel=lbl.category.length>maxLeftChars?lbl.category.slice(0,maxLeftChars-1)+\"\\u2026\":lbl.category;g.append(\"text\").attr(\"x\",xScale(periods[0])-10).attr(\"y\",lbl.y+4).attr(\"text-anchor\",\"end\").attr(\"fill\",lbl.color).attr(\"font-size\",fontSize).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(`${catLabel} (${formatValue(lbl.value)})`)});const rightLabels=lineData.map(d=>({category:d.category,y:d.y2,value:d.vals[periods[1]],color:d.color})).sort((a,b)=>a.y-b.y);resolveCollisions(rightLabels,minLabelSpacing,labelBoundsMin,labelBoundsMax);rightLabels.forEach(lbl=>{g.append(\"text\").attr(\"x\",xScale(periods[1])+10).attr(\"y\",lbl.y+4).attr(\"text-anchor\",\"start\").attr(\"fill\",lbl.color).attr(\"font-size\",fontSize).attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(formatValue(lbl.value))})}}return __toCommonJS(slope_chart_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
36
|
+
export const smallMultiplesBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var small_multiples_render_exports={};__export(small_multiples_render_exports,{renderChart:()=>renderSmallMultiples});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderLine(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field||null;const interpolation=config.interpolation||\"monotone\";const showPoints=interpolation===\"step\"?false:config.showPoints??data.length<=50;const showArea=config.showArea??false;const strokeWidth=config.strokeWidth??2;const parsedData=data.map(d=>({...d,_date:parseDate(d[timeField]),_value:Number(d[valueField])})).filter(d=>d._date!==null&&!isNaN(d._value));const colorScale=buildColorScale(encoding.color,data);const seriesNames=seriesField?[...new Set(parsedData.map(d=>d[seriesField]))]:[];const isMultiSeries=seriesNames.length>1;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);if(isMultiSeries){const legendDiv=createLegend(colorScale,{shape:\"line\"});container.appendChild(legendDiv)}const{svg,g,dims}=createSvg(chartWrapper,spec,{right:30,top:40});svg.style(\"background\",\"none\");const tooltip=createTooltip(chartWrapper);if(parsedData.every(d=>d._value===0)){renderEmptyState(g,dims);return}const xExtent=d3.extent(parsedData,d=>d._date);const xScale=d3.scaleTime().domain(xExtent).range([0,dims.innerWidth]).nice();const yExtent=d3.extent(parsedData,d=>d._value);const yMin=showArea?0:yExtent[0]*.9;const yScale=d3.scaleLinear().domain([yMin,yExtent[1]*1.05]).range([dims.innerHeight,0]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(0).tickPadding(8));styleAxis(xAxis);const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const curveMap={linear:d3.curveLinear,monotone:d3.curveMonotoneX,basis:d3.curveBasis,step:d3.curveStepAfter,cardinal:d3.curveCardinal,catmullRom:d3.curveCatmullRom};const curve=curveMap[config.interpolation||\"monotone\"]||d3.curveMonotoneX;const lineGen=d3.line().x(d=>xScale(d._date)).y(d=>yScale(d._value)).curve(curve);const areaGen=d3.area().x(d=>xScale(d._date)).y0(dims.innerHeight).y1(d=>yScale(d._value)).curve(curve);const uniqueDates=new Set(parsedData.map(d=>d._date.getTime()));const isSinglePoint=uniqueDates.size<=1;if(isSinglePoint){const color=isMultiSeries?void 0:categorical[0];parsedData.forEach(d=>{const c=isMultiSeries?colorScale(d[seriesField]):color;g.append(\"circle\").attr(\"cx\",xScale(d._date)).attr(\"cy\",yScale(d._value)).attr(\"r\",6).attr(\"fill\",c).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2);g.append(\"text\").attr(\"x\",xScale(d._date)).attr(\"y\",yScale(d._value)-14).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(formatValue(d._value))})}else if(isMultiSeries){drawMultiSeries(g,parsedData,seriesField,seriesNames,colorScale,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth)}else{drawSingleSeries(g,parsedData,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth)}if(!isSinglePoint){addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,isMultiSeries)}}function parseDate(v){if(v instanceof Date)return v;const d=new Date(v);return isNaN(d.getTime())?null:d}function drawMultiSeries(g,parsedData,seriesField,seriesNames,colorScale,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth){seriesNames.forEach(name=>{const seriesData=parsedData.filter(d=>d[seriesField]===name).sort((a,b)=>a._date.getTime()-b._date.getTime());const color=colorScale(name);if(showArea){g.append(\"path\").datum(seriesData).attr(\"fill\",color).attr(\"opacity\",.1).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\")}g.append(\"path\").datum(seriesData).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\");if(showPoints){g.selectAll(`.point-${String(name).replace(/\\W/g,\"\")}`).data(seriesData).join(\"circle\").attr(\"class\",`point-${String(name).replace(/\\W/g,\"\")}`).attr(\"cx\",d=>xScale(d._date)).attr(\"cy\",d=>yScale(d._value)).attr(\"r\",1.25).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")}})}function drawSingleSeries(g,parsedData,lineGen,areaGen,xScale,yScale,showArea,showPoints,strokeWidth){const sortedData=[...parsedData].sort((a,b)=>a._date.getTime()-b._date.getTime());const color=categorical[0];if(showArea){g.append(\"path\").datum(sortedData).attr(\"fill\",color).attr(\"opacity\",.1).attr(\"d\",areaGen).attr(\"pointer-events\",\"none\")}g.append(\"path\").datum(sortedData).attr(\"class\",\"line-path\").attr(\"fill\",\"none\").attr(\"stroke\",color).attr(\"stroke-width\",strokeWidth).attr(\"d\",lineGen).attr(\"pointer-events\",\"none\");if(showPoints){g.selectAll(\".point\").data(sortedData).join(\"circle\").attr(\"class\",\"point\").attr(\"cx\",d=>xScale(d._date)).attr(\"cy\",d=>yScale(d._value)).attr(\"r\",1.25).attr(\"fill\",color).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.75).attr(\"pointer-events\",\"none\")}}function addCrosshairHover(g,parsedData,seriesField,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,isMultiSeries){const dateMap=new Map;parsedData.forEach(d=>{const key=d._date.getTime();if(!dateMap.has(key))dateMap.set(key,[]);dateMap.get(key).push(d)});const sortedDates=[...dateMap.keys()].sort((a,b)=>a-b);const crosshairLine=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const highlightDots=g.append(\"g\").attr(\"class\",\"highlight-dots\").attr(\"pointer-events\",\"none\");g.append(\"rect\").attr(\"class\",\"hover-area\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx]=d3.pointer(event,this);const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(d=>d).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestTime=sortedDates[idx];const nearestX=xScale(new Date(nearestTime));const points=dateMap.get(nearestTime)||[];crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();points.forEach(d=>{const color=isMultiSeries?colorScale(d[seriesField]):categorical[0];highlightDots.append(\"circle\").attr(\"cx\",nearestX).attr(\"cy\",yScale(d._value)).attr(\"r\",5).attr(\"fill\",color).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2)});g.selectAll(\".line-path\").attr(\"opacity\",.4);const dateLabel=points[0]?.[timeField]??new Date(nearestTime).toLocaleDateString();let html=`<strong>${dateLabel}</strong>`;if(isMultiSeries){const sorted=[...points].sort((a,b)=>b._value-a._value);sorted.forEach(d=>{const color=colorScale(d[seriesField]);html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${d[seriesField]}: ${formatValue(d._value)}`})}else{html+=`<br/>${valueField}: ${formatValue(points[0]?._value)}`}showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();g.selectAll(\".line-path\").attr(\"opacity\",1);hideTooltip(tooltip)})}function renderSmallMultiples(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field;if(!seriesField){return renderLine(container,spec)}const seriesNames=[...new Set(data.map(d=>d[seriesField]))];const cols=Math.ceil(Math.sqrt(seriesNames.length));const rows=Math.ceil(seriesNames.length/cols);const width=container.clientWidth||800;const height=container.clientHeight||500;const titleReserve=spec.title?28:0;const cellW=width/cols;const cellH=(height-titleReserve)/rows;const cellMargin={top:18,right:20,bottom:20,left:40};const innerCellW=cellW-cellMargin.left-cellMargin.right;const innerCellH=cellH-cellMargin.top-cellMargin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",16).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"13px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const allDates=data.map(d=>parseDate2(d[timeField])).filter(Boolean);const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const xDomain=d3.extent(allDates);const yDomain=[Math.min(0,d3.min(allValues)),d3.max(allValues)];if(allValues.every(v=>v===0)){svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",height/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"All values are zero\");return}const colorScale=buildColorScale(encoding.color,data);seriesNames.forEach((name,i)=>{const col=i%cols;const row=Math.floor(i/cols);const offsetX=col*cellW+cellMargin.left;const offsetY=row*cellH+cellMargin.top+titleReserve;const cellG=svg.append(\"g\").attr(\"transform\",`translate(${offsetX},${offsetY})`);const xScale=d3.scaleTime().domain(xDomain).range([0,innerCellW]);const yScale=d3.scaleLinear().domain(yDomain).range([innerCellH,0]);cellG.append(\"g\").attr(\"transform\",`translate(0,${innerCellH})`).call(d3.axisBottom(xScale).ticks(3).tickSize(0)).selectAll(\"text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"8px\");cellG.append(\"g\").call(d3.axisLeft(yScale).ticks(3).tickSize(0)).selectAll(\"text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"8px\");cellG.selectAll(\".domain\").remove();const maxLabelChars=Math.max(5,Math.floor(innerCellW/6));const seriesLabel=String(name);const truncatedLabel=seriesLabel.length>maxLabelChars?seriesLabel.slice(0,maxLabelChars-1)+\"\\u2026\":seriesLabel;cellG.append(\"text\").attr(\"x\",innerCellW/2).attr(\"y\",-4).attr(\"text-anchor\",\"middle\").attr(\"fill\",colorScale(name)).attr(\"font-size\",\"11px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(truncatedLabel);const seriesData=data.filter(d=>d[seriesField]===name).map(d=>({...d,_date:parseDate2(d[timeField]),_value:Number(d[valueField])})).filter(d=>d._date!==null).sort((a,b)=>a._date.getTime()-b._date.getTime());const line=d3.line().x(d=>xScale(d._date)).y(d=>yScale(d._value)).curve(d3.curveMonotoneX);const area=d3.area().x(d=>xScale(d._date)).y0(yScale(0)).y1(d=>yScale(d._value)).curve(d3.curveMonotoneX);if(seriesData.length<=1&&seriesData.length>0){const d=seriesData[0];cellG.append(\"circle\").attr(\"cx\",xScale(d._date)).attr(\"cy\",yScale(d._value)).attr(\"r\",5).attr(\"fill\",colorScale(name)).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",1.5);cellG.append(\"text\").attr(\"x\",xScale(d._date)).attr(\"y\",yScale(d._value)-10).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d._value)}else{cellG.append(\"path\").datum(seriesData).attr(\"fill\",colorScale(name)).attr(\"opacity\",.08).attr(\"d\",area);cellG.append(\"path\").datum(seriesData).attr(\"fill\",\"none\").attr(\"stroke\",colorScale(name)).attr(\"stroke-width\",1.5).attr(\"d\",line)}})}function parseDate2(v){const d=new Date(v);return isNaN(d.getTime())?null:d}return __toCommonJS(small_multiples_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
37
|
+
export const sparklineGridBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var sparkline_grid_render_exports={};__export(sparkline_grid_render_exports,{renderChart:()=>renderSparklineGrid});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderSparklineGrid(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.facet?.field;const strokeWidth=config.strokeWidth||1;const curveType=config.curveType||\"curve\";const showSeriesLabel=config.showSeriesLabel!==false;const showLatestValue=config.showLatestValue!==false;const showTrendIndicator=config.showTrendIndicator!==false;const seriesGroups=d3.group(data,d=>d[seriesField]);const seriesNames=Array.from(seriesGroups.keys());const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const titleHeight=spec.title?40:0;const padding=12;const numSeries=seriesNames.length;const gridCols=config.gridCols||Math.min(numSeries,Math.ceil(Math.sqrt(numSeries*(containerWidth/containerHeight))));const gridRows=Math.ceil(numSeries/gridCols);const cellWidth=config.cellWidth||Math.floor((containerWidth-padding*(gridCols+1))/gridCols);const cellHeight=config.cellHeight||Math.floor((containerHeight-titleHeight-padding*(gridRows+1))/gridRows);const width=containerWidth;const height=containerHeight;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",\"#0f1117\").style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",height/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(\"All values are zero\");return}seriesNames.forEach((seriesName,idx)=>{const row=Math.floor(idx/gridCols);const col=idx%gridCols;const x=col*(cellWidth+padding)+padding;const y=row*(cellHeight+padding)+padding+titleHeight;const seriesData=seriesGroups.get(seriesName).sort((a,b)=>new Date(a[timeField]).getTime()-new Date(b[timeField]).getTime());const g=svg.append(\"g\").attr(\"transform\",`translate(${x}, ${y})`);const values=seriesData.map(d=>Number(d[valueField]));const latestValue=values[values.length-1];const previousValue=values[values.length-2]||latestValue;const isUp=latestValue>=previousValue;const lineColor=isUp?\"#3dd9a0\":\"#ff6b5e\";g.append(\"rect\").attr(\"x\",0).attr(\"y\",0).attr(\"width\",cellWidth).attr(\"height\",cellHeight).attr(\"fill\",\"#1a1d29\").attr(\"rx\",4);if(showSeriesLabel){const maxChars=Math.max(3,Math.floor(cellWidth/7));const allLabels=seriesNames.map(String);const smartLabels=smartTruncateLabels(allLabels,maxChars);const cellLabel=smartLabels[idx];g.append(\"text\").attr(\"x\",6).attr(\"y\",12).attr(\"text-anchor\",\"start\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"opacity\",.7).text(cellLabel)}const sparkPadTop=showSeriesLabel?16:4;const sparkPadBot=showLatestValue?14:4;const sparkPadLeft=4;const sparkPadRight=4;if(seriesData.length<=1){const val=values.length>0?values[0]:0;g.append(\"circle\").attr(\"cx\",cellWidth/2).attr(\"cy\",cellHeight/2).attr(\"r\",5).attr(\"fill\",lineColor);g.append(\"text\").attr(\"x\",cellWidth/2).attr(\"y\",cellHeight/2-12).attr(\"text-anchor\",\"middle\").attr(\"fill\",lineColor).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"monospace\").text(formatValue(val))}else{const xScale=d3.scaleTime().domain(d3.extent(seriesData,d=>new Date(d[timeField]))).range([sparkPadLeft,cellWidth-sparkPadRight]);const yExtent=d3.extent(values);const yPadding=(yExtent[1]-yExtent[0])*.05||1;const yScale=d3.scaleLinear().domain([yExtent[0]-yPadding,yExtent[1]+yPadding]).range([cellHeight-sparkPadBot,sparkPadTop]);const curve=curveType===\"square\"?d3.curveStepAfter:d3.curveBasis;const line=d3.line().curve(curve).x(d=>xScale(new Date(d[timeField]))).y(d=>yScale(Number(d[valueField])));g.append(\"path\").datum(seriesData).attr(\"fill\",\"none\").attr(\"stroke\",lineColor).attr(\"stroke-width\",strokeWidth).attr(\"d\",line);if(showLatestValue){g.append(\"text\").attr(\"x\",cellWidth).attr(\"y\",yScale(latestValue)+3).attr(\"text-anchor\",\"end\").attr(\"fill\",lineColor).attr(\"font-size\",\"9px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"monospace\").text(formatValue(latestValue))}if(showTrendIndicator){g.append(\"text\").attr(\"x\",cellWidth-2).attr(\"y\",10).attr(\"text-anchor\",\"end\").attr(\"fill\",lineColor).attr(\"font-size\",\"8px\").text(isUp?\"\\u25B2\":\"\\u25BC\")}}g.append(\"rect\").attr(\"x\",0).attr(\"y\",0).attr(\"width\",cellWidth).attr(\"height\",cellHeight).attr(\"fill\",\"transparent\").style(\"cursor\",\"pointer\").on(\"mouseover\",event=>{const change=latestValue-previousValue;const changePercent=previousValue!==0?(change/previousValue*100).toFixed(1):\"0\";showTooltip(tooltip,`<strong>${seriesName}</strong><br/>Latest: ${formatValue(latestValue)}<br/>Change: ${change>=0?\"+\":\"\"}${formatValue(change)} (${changePercent}%)`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",()=>hideTooltip(tooltip))})}return __toCommonJS(sparkline_grid_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
38
|
+
export const stackedBarBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var stacked_bar_render_exports={};__export(stacked_bar_render_exports,{renderChart:()=>renderStackedBar});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderStackedBar(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.x?.field;const seriesField=config.seriesField||encoding.color?.field;const valueField=config.valueField||encoding.y?.field;const isNormalized=config.normalized||false;let categories=[...new Set(data.map(d=>d[categoryField]))];const series=[...new Set(data.map(d=>d[seriesField]))];const pivoted={};const totals={};categories.forEach(cat=>{pivoted[cat]={};let total=0;series.forEach(s=>{const row=data.find(d=>d[categoryField]===cat&&d[seriesField]===s);const val=row?Number(row[valueField])||0:0;pivoted[cat][s]=val;total+=val});totals[cat]=total});if(config.sortBy===\"value\"){const order=config.sortOrder===\"ascending\"?1:-1;categories.sort((a,b)=>order*(totals[a]-totals[b]))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;categories.sort((a,b)=>order*String(a).localeCompare(String(b),void 0,{sensitivity:\"base\",numeric:true}))}const stackData=categories.map(cat=>{const entry={_category:cat};const total=totals[cat];series.forEach(s=>{const val=pivoted[cat][s]||0;entry[s]=isNormalized&&total>0?val/total*100:val});entry._total=isNormalized?100:total;return entry});const hasNegatives=stackData.some(d=>series.some(s=>d[s]<0));const stack=d3.stack().keys(series);if(hasNegatives){stack.offset(d3.stackOffsetDiverging)}const stacked=stack(stackData);const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>250&&containerWidth>350;const colorScale=buildColorScale(encoding.color,data);container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);let legendDiv=null;if(showLegend){legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}const estimatedBarWidth=(containerWidth-130)/categories.length;const needsRotation=shouldRotateLabels(categories.map(String),estimatedBarWidth);const bottomMargin=calculateBottomMargin(categories.map(String),needsRotation);const{svg,g,dims}=createSvg(chartWrapper,spec,{bottom:bottomMargin,left:70,right:30,top:40});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const tooltip=createTooltip(container);const xScale=d3.scaleBand().domain(categories).range([0,dims.innerWidth]).padding(.2);let minY;let maxY;if(isNormalized){minY=0;maxY=100}else if(hasNegatives){minY=d3.min(stacked,layer=>d3.min(layer,d=>d[0]));maxY=d3.max(stacked,layer=>d3.max(layer,d=>d[1]))}else{minY=0;maxY=d3.max(stackData,d=>d._total)}const yScale=d3.scaleLinear().domain([minY,maxY]).range([dims.innerHeight,0]).nice();const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>isNormalized?d+\"%\":formatValue(d)));styleAxis(yAxis);g.selectAll(\".bar-hover-target\").data(stackData).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(d._category)).attr(\"y\",0).attr(\"width\",xScale.bandwidth()).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".segment\").filter(sd=>sd.data._category===d._category).attr(\"opacity\",.8);let html=`<strong>${d._category}</strong>`;series.forEach(s=>{const val=d[s];if(val>0){const swatch=`<span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${colorScale(s)};margin-right:4px\"></span>`;html+=`<br/>${swatch}${s}: ${isNormalized?val.toFixed(1)+\"%\":formatValue(val)}`}});if(!isNormalized){html+=`<br/><span style=\"color:${TEXT_MUTED};font-size:11px\">Total: ${formatValue(d._total)}</span>`}showTooltip(tooltip,html,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".segment\").attr(\"opacity\",1);hideTooltip(tooltip)});const maxBarWidth=Math.min(100,dims.innerWidth*.35);const stackBarWidth=Math.min(xScale.bandwidth(),maxBarWidth);const stackBarOffset=(xScale.bandwidth()-stackBarWidth)/2;g.selectAll(\".series\").data(stacked).join(\"g\").attr(\"class\",\"series\").attr(\"fill\",d=>colorScale(d.key)).selectAll(\"rect\").data(d=>d.map(v=>({...v,key:d.key}))).join(\"rect\").attr(\"class\",\"segment\").attr(\"x\",d=>xScale(d.data._category)+stackBarOffset).attr(\"y\",d=>Math.min(yScale(d[0]),yScale(d[1]))).attr(\"width\",stackBarWidth).attr(\"height\",d=>Math.abs(yScale(d[0])-yScale(d[1]))).attr(\"rx\",1).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,xScale.bandwidth(),false);if(showLabels){const allSegments=[];stacked.forEach(seriesData=>{seriesData.forEach(d=>{const val=d[1]-d[0];if(val>0){allSegments.push({...d,key:seriesData.key,value:val})}})});g.selectAll(\".segment-label\").data(allSegments).join(\"text\").attr(\"class\",\"segment-label\").attr(\"x\",d=>xScale(d.data._category)+xScale.bandwidth()/2).attr(\"y\",d=>{const segmentHeight=yScale(d[0])-yScale(d[1]);return yScale(d[1])+segmentHeight/2}).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",\"#ffffff\").attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\").text(d=>{const segmentHeight=yScale(d[0])-yScale(d[1]);if(segmentHeight<16)return\"\";return isNormalized?d.value.toFixed(0)+\"%\":formatValue(d.value)})}if(config.showTotal&&!isNormalized){g.selectAll(\".total-label\").data(stackData).join(\"text\").attr(\"class\",\"total-label\").attr(\"x\",d=>xScale(d._category)+xScale.bandwidth()/2).attr(\"y\",d=>yScale(d._total)-6).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"10px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>formatValue(d._total))}addSortControls(svg,container,spec,dims,renderStackedBar)}return __toCommonJS(stacked_bar_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
39
|
+
export const streamGraphBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var stream_graph_render_exports={};__export(stream_graph_render_exports,{renderChart:()=>renderStreamGraph});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function highlightLegendItem(legendDiv,activeKey){const items=legendDiv.querySelectorAll(\"[data-series]\");items.forEach(el=>{const element=el;const isActive=!activeKey||element.getAttribute(\"data-series\")===activeKey;element.style.opacity=isActive?\"1\":\"0.3\"})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderStreamGraph(container,spec){const{config,encoding,data}=spec;const timeField=config.timeField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;const seriesField=config.seriesField||encoding.color?.field;const offsetMode=config.offset||\"wiggle\";const curveMode=config.curve||\"basis\";const interactive=config.interactive!==false;if(!timeField||!valueField||!seriesField)return;const parsedData=data.map(d=>({...d,_date:parseDate(d[timeField]),_value:Number(d[valueField])||0,_series:String(d[seriesField])})).filter(d=>d._date!==null);if(parsedData.length===0)return;const seriesNames=[...new Set(parsedData.map(d=>d._series))];const dateMap=new Map;parsedData.forEach(d=>{const key=d._date.getTime();if(!dateMap.has(key))dateMap.set(key,{});dateMap.get(key)[d._series]=(dateMap.get(key)[d._series]||0)+d._value});const sortedTimes=[...dateMap.keys()].sort((a,b)=>a-b);if(sortedTimes.length===0)return;const wideData=sortedTimes.map(t=>{const row={_date:new Date(t)};const values=dateMap.get(t);seriesNames.forEach(name=>{row[name]=values[name]||0});return row});const offsetMap={wiggle:d3.stackOffsetWiggle,silhouette:d3.stackOffsetSilhouette,expand:d3.stackOffsetExpand};const curveMap={basis:d3.curveBasis,monotone:d3.curveMonotoneX,cardinal:d3.curveCardinal};const hasNegativeValues=wideData.some(row=>seriesNames.some(name=>row[name]<0));const stackOffset=hasNegativeValues?d3.stackOffsetDiverging:offsetMap[offsetMode]||d3.stackOffsetWiggle;const curve=curveMap[curveMode]||d3.curveBasis;const stackGen=d3.stack().keys(seriesNames).offset(stackOffset).order(d3.stackOrderInsideOut);const stacked=stackGen(wideData);if(parsedData.every(d=>d._value===0)){container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";const chartWrapper2=document.createElement(\"div\");chartWrapper2.style.flex=\"1\";container.appendChild(chartWrapper2);const{svg:svg2,g:g2,dims:dims2}=createSvg(chartWrapper2,spec);svg2.style(\"background\",\"none\");renderEmptyState(g2,dims2);return}const colorScale=buildColorScale(encoding.color,data);container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);const legendDiv=createLegend(colorScale);container.appendChild(legendDiv);const{svg,g,dims}=createSvg(chartWrapper,spec,{right:40,top:40,left:40,bottom:50});const tooltip=createTooltip(chartWrapper);if(sortedTimes.length<=1){const xMid=dims.innerWidth/2;const total=seriesNames.reduce((s,n)=>s+(wideData[0]?.[n]||0),0);const yScale2=d3.scaleLinear().domain([0,total||1]).range([dims.innerHeight,0]).nice();let yPos=20;seriesNames.forEach(name=>{const val=wideData[0]?.[name]||0;g.append(\"circle\").attr(\"cx\",xMid).attr(\"cy\",yPos).attr(\"r\",5).attr(\"fill\",colorScale(name));g.append(\"text\").attr(\"x\",xMid+12).attr(\"y\",yPos).attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(`${name}: ${formatValue(val)}`);yPos+=24});return}const xScale=d3.scaleTime().domain(d3.extent(wideData,d=>d._date)).range([0,dims.innerWidth]);const yMin=d3.min(stacked,layer=>d3.min(layer,d=>d[0]));const yMax=d3.max(stacked,layer=>d3.max(layer,d=>d[1]));const yScale=d3.scaleLinear().domain([yMin,yMax]).range([dims.innerHeight,0]);let xTickCount=getAdaptiveTickCount(dims.innerWidth);if(wideData.length<xTickCount){xTickCount=wideData.length}const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(0).tickPadding(8));styleAxis(xAxis);xAxis.selectAll(\".tick text\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\").attr(\"transform\",\"rotate(-35)\");if(offsetMode===\"expand\"){const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>Math.round(d*100)+\"%\"));styleAxis(yAxis)}const areaGen=d3.area().x(d=>xScale(d.data._date)).y0(d=>yScale(d[0])).y1(d=>yScale(d[1])).curve(curve);const streams=g.selectAll(\".stream\").data(stacked).join(\"path\").attr(\"class\",\"stream\").attr(\"d\",areaGen).attr(\"fill\",d=>colorScale(d.key)).attr(\"opacity\",.85).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.5);if(interactive){addStreamInteraction(g,streams,stacked,wideData,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,legendDiv,offsetMode)}}function parseDate(v){if(v instanceof Date)return v;const d=new Date(v);return isNaN(d.getTime())?null:d}function addStreamInteraction(g,streams,stacked,wideData,seriesNames,timeField,valueField,colorScale,xScale,yScale,dims,tooltip,legendDiv,offsetMode){const sortedDates=wideData.map(d=>d._date.getTime());const crosshairLine=g.append(\"line\").attr(\"class\",\"crosshair\").attr(\"y1\",0).attr(\"y2\",dims.innerHeight).attr(\"stroke\",TEXT_MUTED).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"4,3\").attr(\"pointer-events\",\"none\").attr(\"opacity\",0);const highlightDots=g.append(\"g\").attr(\"class\",\"highlight-dots\").attr(\"pointer-events\",\"none\");streams.attr(\"cursor\",\"pointer\").on(\"mouseover\",function(_event,d){const hoveredKey=d.key;streams.attr(\"opacity\",s=>s.key===hoveredKey?1:.2).attr(\"stroke-width\",s=>s.key===hoveredKey?1.5:.5);highlightLegendItem(legendDiv,hoveredKey)}).on(\"mousemove\",function(event,d){const[mx]=d3.pointer(event,g.node());const xDate=xScale.invert(mx).getTime();const hoveredKey=d.key;const bisect=d3.bisector(t=>t).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestX=xScale(wideData[idx]._date);crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();const layer=stacked.find(l=>l.key===hoveredKey);if(layer){const pt=layer[idx];const midY=yScale((pt[0]+pt[1])/2);highlightDots.append(\"circle\").attr(\"cx\",nearestX).attr(\"cy\",midY).attr(\"r\",5).attr(\"fill\",colorScale(hoveredKey)).attr(\"stroke\",\"#fff\").attr(\"stroke-width\",2)}const dateStr=wideData[idx]._date.toLocaleDateString();const val=wideData[idx][hoveredKey]||0;let html=`<strong>${hoveredKey}</strong><br/>`;html+=`<span style=\"color:${TEXT_MUTED}\">${dateStr}</span><br/>`;html+=`${valueField}: ${formatValue(val)}`;if(offsetMode===\"expand\"){const total=seriesNames.reduce((s,k)=>s+(wideData[idx][k]||0),0);if(total>0){const pct=(val/total*100).toFixed(1);html+=` (${pct}%)`}}showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){streams.attr(\"opacity\",.85).attr(\"stroke-width\",.5);crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();hideTooltip(tooltip);highlightLegendItem(legendDiv,null)});g.append(\"rect\").attr(\"class\",\"hover-area\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").style(\"pointer-events\",\"all\").lower().on(\"mousemove\",function(event){const[mx]=d3.pointer(event,g.node());const xDate=xScale.invert(mx).getTime();const bisect=d3.bisector(t=>t).left;let idx=bisect(sortedDates,xDate);if(idx>0&&idx<sortedDates.length){const d0=sortedDates[idx-1];const d1=sortedDates[idx];idx=xDate-d0>d1-xDate?idx:idx-1}else if(idx>=sortedDates.length){idx=sortedDates.length-1}const nearestX=xScale(wideData[idx]._date);crosshairLine.attr(\"x1\",nearestX).attr(\"x2\",nearestX).attr(\"opacity\",1);highlightDots.selectAll(\"circle\").remove();const dateStr=wideData[idx]._date.toLocaleDateString();let html=`<strong>${dateStr}</strong>`;const sorted=[...seriesNames].map(name=>({name,value:wideData[idx][name]||0})).sort((a,b)=>b.value-a.value);sorted.forEach(s=>{const color=colorScale(s.name);html+=`<br/><span style=\"display:inline-block;width:8px;height:8px;border-radius:2px;background:${color};margin-right:5px;vertical-align:middle;\"></span>${s.name}: ${formatValue(s.value)}`});showTooltip(tooltip,html,event)}).on(\"mouseout\",function(){crosshairLine.attr(\"opacity\",0);highlightDots.selectAll(\"circle\").remove();hideTooltip(tooltip)})}return __toCommonJS(stream_graph_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
40
|
+
export const stripPlotBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var strip_plot_render_exports={};__export(strip_plot_render_exports,{renderChart:()=>renderStripPlot});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function calculateLeftMargin(labels,fontSize=11){const charWidthLatin=fontSize*.55;const charWidthCJK=fontSize*1;const maxWidth=Math.max(...labels.map(l=>{const s=String(l);let w=0;for(let i=0;i<s.length;i++){const code=s.charCodeAt(i);w+=code>11904&&code<40959||code>65280&&code<65519?charWidthCJK:charWidthLatin}return w}));return Math.max(80,Math.min(220,maxWidth+20))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function seededJitter(index,axis){let s=(index+1)*16807+axis*12345;s=(s*16807+0)%2147483647;return(s-1)/2147483646}function renderStripPlot(container,spec){const{config,encoding,data}=spec;const valueField=encoding.x?.field||Object.keys(data[0])[0];const groupField=encoding.y?.field||null;const baseRadius=config.dotRadius??4;const opacity=config.opacity??.65;const hasLegend=groupField!==null&&encoding.color?.field!=null;container.innerHTML=\"\";container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=\"flex: 1; min-height: 0;\";container.appendChild(chartWrapper);const containerWidth=container.clientWidth||800;const isSmall=containerWidth<=400;let leftMargin=12;if(groupField&&!isSmall){const groups=[...new Set(data.map(d=>String(d[groupField])))];leftMargin=calculateLeftMargin(groups.map(l=>truncateLabel(l,25)))}const{svg,g,dims}=createSvg(chartWrapper,spec,{left:leftMargin,right:20});const tooltip=createTooltip(container);const xValues=data.map(d=>Number(d[valueField]));const xExtent=d3.extent(xValues);const xPad=(xExtent[1]-xExtent[0])*.05||1;const xScale=d3.scaleLinear().domain([xExtent[0]-xPad,xExtent[1]+xPad]).range([0,dims.innerWidth]).nice();const xTickCount=getAdaptiveTickCount(dims.innerWidth);const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).ticks(xTickCount).tickSize(-dims.innerHeight).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(xAxis);const colorScale=buildColorScale(encoding.color,data);if(groupField){renderGrouped(g,data,valueField,groupField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip,isSmall)}else{renderSingle(g,data,valueField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip)}if(hasLegend){const legendDiv=createLegend(colorScale,{shape:\"circle\",callbacks:{onHover:category=>{g.selectAll(\".dot\").each(function(_,j){const match=d3.select(this).datum()?.[encoding.color?.field||groupField]===category;d3.select(this).attr(\"opacity\",match?1:.08).attr(\"r\",match?Number(d3.select(this).attr(\"data-r\"))*1.3:Number(d3.select(this).attr(\"data-r\")))})},onLeave:()=>{g.selectAll(\".dot\").each(function(){d3.select(this).attr(\"opacity\",opacity).attr(\"r\",Number(d3.select(this).attr(\"data-r\")))})}}});container.appendChild(legendDiv)}}function renderGrouped(g,data,valueField,groupField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip,isSmall){const groups=[...new Set(data.map(d=>d[groupField]))];const yScale=d3.scaleBand().domain(groups).range([0,dims.innerHeight]).padding(.15);const bandwidth=yScale.bandwidth();if(!isSmall){const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(yAxis);const colorField=encoding.color?.field||groupField;yAxis.selectAll(\".tick text\").each(function(label){d3.select(this).attr(\"fill\",colorScale(label))})}groups.forEach(group=>{const bandTop=yScale(group);g.append(\"line\").attr(\"x1\",0).attr(\"y1\",bandTop).attr(\"x2\",dims.innerWidth).attr(\"y2\",bandTop).attr(\"stroke\",\"#1f2937\").attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\")});const totalPoints=data.length;const plotArea=dims.innerWidth*bandwidth*groups.length/1e4;const density=totalPoints/Math.max(plotArea,1);let dotRadius=baseRadius;if(density>8)dotRadius=Math.max(2,baseRadius-2);else if(density>4)dotRadius=Math.max(2.5,baseRadius-1);dotRadius=Math.min(dotRadius,bandwidth/4);const pointPositions=data.map((d,i)=>{const cx=xScale(Number(d[valueField]));const bandTop=yScale(d[groupField]);const jitterY=(seededJitter(i,0)-.5)*bandwidth*.7;const cy=bandTop+bandwidth/2+jitterY;return{d,i,cx,cy,r:dotRadius}});const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").filter((_,j)=>j===p.i).attr(\"r\",p.r*1.6).attr(\"opacity\",1);let html=`<strong>${p.d[groupField]}</strong>`;html+=`<br/>${encoding.x?.title||valueField}: ${formatValue(Number(p.d[valueField]))}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity);activeIdx=-1}hideTooltip(tooltip)});g.selectAll(\".dot\").data(pointPositions).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",p=>p.cx).attr(\"cy\",p=>p.cy).attr(\"r\",p=>p.r).attr(\"data-r\",p=>p.r).attr(\"fill\",p=>colorScale(p.d[encoding.color?.field||groupField])).attr(\"opacity\",opacity).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.8).attr(\"pointer-events\",\"none\")}function renderSingle(g,data,valueField,encoding,xScale,colorScale,baseRadius,opacity,dims,tooltip){const density=data.length/(dims.innerWidth*dims.innerHeight/1e4);let dotRadius=baseRadius;if(density>5)dotRadius=Math.max(2,baseRadius-2);else if(density>2)dotRadius=Math.max(3,baseRadius-1);const midY=dims.innerHeight/2;const pointPositions=data.map((d,i)=>{const cx=xScale(Number(d[valueField]));const jitterY=(seededJitter(i,0)-.5)*dims.innerHeight*.6;const cy=midY+jitterY;return{d,i,cx,cy,r:dotRadius}});const delaunay=d3.Delaunay.from(pointPositions,p=>p.cx,p=>p.cy);let activeIdx=-1;g.append(\"rect\").attr(\"class\",\"voronoi-overlay\").attr(\"width\",dims.innerWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"crosshair\").on(\"mousemove\",function(event){const[mx,my]=d3.pointer(event,g.node());const idx=delaunay.find(mx,my);if(idx===activeIdx){positionTooltip(tooltip,event);return}if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity)}activeIdx=idx;const p=pointPositions[idx];g.selectAll(\".dot\").filter((_,j)=>j===p.i).attr(\"r\",p.r*1.6).attr(\"opacity\",1);const html=`<strong>${encoding.x?.title||valueField}</strong>: ${formatValue(Number(p.d[valueField]))}`;showTooltip(tooltip,html,event)}).on(\"mouseleave\",function(){if(activeIdx>=0){const prev=pointPositions[activeIdx];g.selectAll(\".dot\").filter((_,j)=>j===prev.i).attr(\"r\",prev.r).attr(\"opacity\",opacity);activeIdx=-1}hideTooltip(tooltip)});const colorField=encoding.color?.field;g.selectAll(\".dot\").data(pointPositions).join(\"circle\").attr(\"class\",\"dot\").attr(\"cx\",p=>p.cx).attr(\"cy\",p=>p.cy).attr(\"r\",p=>p.r).attr(\"data-r\",p=>p.r).attr(\"fill\",p=>colorField?colorScale(p.d[colorField]):categorical[0]).attr(\"opacity\",opacity).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",.8).attr(\"pointer-events\",\"none\")}return __toCommonJS(strip_plot_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
41
|
+
export const sunburstBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var sunburst_render_exports={};__export(sunburst_render_exports,{renderChart:()=>renderSunburst});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function contrastTextMuted(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"rgba(255,255,255,0.7)\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"rgba(26,26,46,0.6)\":\"rgba(255,255,255,0.7)\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderSunburst(container,spec){const{config,encoding,data}=spec;const parentField=config.parentField;const childField=config.childField;const valueField=config.valueField||encoding.size?.field;const showLabels=config.showLabels??true;const showValues=config.showValues??false;const innerR=config.innerRadius??0;const width=container.clientWidth||600;const height=container.clientHeight||600;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";container.style.fontFamily=\"Inter, system-ui, sans-serif\";const titleHeight=spec.title?36:0;if(spec.title){const titleDiv=document.createElement(\"div\");titleDiv.style.cssText=`\n text-align: center;\n color: ${TEXT_COLOR};\n font-size: 14px;\n font-weight: 600;\n line-height: 36px;\n height: 36px;\n flex-shrink: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 0 10px;\n `;titleDiv.textContent=spec.title;titleDiv.title=spec.title;container.appendChild(titleDiv)}const chartWrapper=document.createElement(\"div\");chartWrapper.style.cssText=`flex: 1; min-height: 0; position: relative;`;container.appendChild(chartWrapper);const legendEstimate=32;const chartHeight=height-titleHeight-legendEstimate;const chartPad=12;const radius=Math.min(width-chartPad*2,chartHeight-chartPad*2)/2;const svg=d3.select(chartWrapper).append(\"svg\").attr(\"width\",width).attr(\"height\",chartHeight);const centerX=width/2;const centerY=chartHeight/2;const g=svg.append(\"g\").attr(\"transform\",`translate(${centerX},${centerY})`);const tooltip=createTooltip(container);if(valueField&&isAllZeros(data,valueField)){const emptyDiv=document.createElement(\"div\");emptyDiv.style.cssText=`\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${width}px;\n height: ${chartHeight}px;\n color: ${TEXT_MUTED};\n font-size: 14px;\n font-family: Inter, system-ui, sans-serif;\n `;emptyDiv.textContent=\"All values are zero\";chartWrapper.appendChild(emptyDiv);return}const root=buildHierarchy(data,parentField,childField,valueField,config);const effectiveInner=Math.min(innerR,radius*.6);d3.partition().size([2*Math.PI,radius-effectiveInner])(root);const topLevelNames=root.children?root.children.map(c=>c.data.name):[];const colorScale=encoding.color?buildColorScale(encoding.color,data):d3.scaleOrdinal().domain(topLevelNames).range(categorical);const arc=d3.arc().startAngle(d=>d.x0).endAngle(d=>d.x1).innerRadius(d=>d.y0+effectiveInner).outerRadius(d=>d.y1+effectiveInner);const descendants=root.descendants().filter(d=>d.depth>0);const arcs=g.selectAll(\".sunburst-arc\").data(descendants).join(\"path\").attr(\"class\",\"sunburst-arc\").attr(\"d\",d=>d3.arc().startAngle(d.x0).endAngle(d.x1).innerRadius(d.y0+effectiveInner).outerRadius(d.y1+effectiveInner).cornerRadius(d.depth*3)(d)).attr(\"fill\",d=>getArcColor(d,colorScale)).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1).attr(\"opacity\",1).style(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){arcs.attr(\"opacity\",.3);const ancestors=getAncestorChain(d);arcs.filter(n=>ancestors.has(n)||n===d).attr(\"opacity\",1);d3.select(this).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",2);const path=getAncestorPath(d);showTooltip(tooltip,`<strong>${path}</strong><br/>${valueField}: ${formatValue(d.value)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){arcs.attr(\"opacity\",1).attr(\"stroke\",DARK_BG).attr(\"stroke-width\",1);hideTooltip(tooltip)});if(showLabels&&radius>140){drawArcLabels(g,descendants,arc,showValues,colorScale,radius,0)}if(effectiveInner>30){g.append(\"text\").attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"12px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(`Total: ${formatValue(root.value)}`)}if(topLevelNames.length>1){const legendDiv=createLegend(colorScale);container.appendChild(legendDiv)}}function getArcColor(d,colorScale){const ancestor=getTopAncestor(d);const baseColor=colorScale(ancestor.data.name);if(d.depth>1){const lightenFactor=Math.min(d.depth*.12,.4);return d3.interpolateRgb(baseColor,\"#ffffff\")(lightenFactor)}return baseColor}function buildNestedHierarchy(items,levelFields,valueField,levelIdx,clampVal){const field=levelFields[levelIdx];const groups=[...new Set(items.map(d=>d[field]))];if(levelIdx===levelFields.length-1){return groups.map(name=>({name,value:clampVal(items.filter(d=>d[field]===name).reduce((sum,d)=>sum+(Number(d[valueField])||0),0)),_data:items.find(d=>d[field]===name)}))}return groups.map(name=>({name,children:buildNestedHierarchy(items.filter(d=>d[field]===name),levelFields,valueField,levelIdx+1,clampVal)}))}function buildHierarchy(data,parentField,childField,valueField,config){const levelFields=config.levelFields;const allVals=valueField?data.map(d=>Number(d[valueField])||0).filter(v=>v>0):[];const maxVal=allVals.length>0?Math.max(...allVals):0;const minVisible=maxVal*.02;const clampVal=v=>v>0&&v<minVisible?minVisible:v;if(levelFields&&levelFields.length>0&&valueField){const hierarchy2={name:\"root\",children:buildNestedHierarchy(data,levelFields,valueField,0,clampVal)};return d3.hierarchy(hierarchy2).sum(d=>d.value)}if(parentField&&childField&&valueField){const parents=[...new Set(data.map(d=>d[parentField]))];const hierarchy2={name:\"root\",children:parents.map(p=>({name:p,children:data.filter(d=>d[parentField]===p).map(d=>({name:d[childField],value:clampVal(Number(d[valueField])||0),_data:d}))}))};return d3.hierarchy(hierarchy2).sum(d=>d.value)}if(parentField&&valueField){const parents=[...new Set(data.map(d=>d[parentField]))];const hierarchy2={name:\"root\",children:parents.map(p=>{const items=data.filter(d=>d[parentField]===p);return{name:p,children:items.map((d,i)=>({name:d[childField||parentField]||`Item ${i}`,value:clampVal(Number(d[valueField])||0),_data:d}))}})};return d3.hierarchy(hierarchy2).sum(d=>d.value)}const categoryField=config.categoryField||childField||parentField;const hierarchy={name:\"root\",children:data.map(d=>({name:d[categoryField]||\"Unknown\",value:clampVal(Number(d[valueField])||0),_data:d}))};return d3.hierarchy(hierarchy).sum(d=>d.value)}function getTopAncestor(d){let node=d;while(node.parent&&node.parent.parent){node=node.parent}return node}function getAncestorChain(d){const chain=new Set;let node=d.parent;while(node&&node.depth>0){chain.add(node);node=node.parent}return chain}function getAncestorPath(d){const parts=[];let node=d;while(node&&node.depth>0){parts.unshift(node.data.name);node=node.parent}return parts.join(\" \\u203A \")}function drawArcLabels(g,descendants,arc,showValues,colorScale,_radius,_effectiveInner){const labels=g.selectAll(\".sunburst-label\").data(descendants).join(\"text\").attr(\"class\",\"sunburst-label\").attr(\"transform\",d=>{const[x,y]=arc.centroid(d);return`translate(${x},${y})`}).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"central\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"pointer-events\",\"none\");labels.each(function(d){const el=d3.select(this);const angle=d.x1-d.x0;const thickness=d.y1-d.y0;if(angle<.12||thickness<18)return;const fillColor=getArcColor(d,colorScale);const isLarge=angle>=.25&&thickness>=25;const fontSize=isLarge?\"12px\":\"10px\";const maxChars=Math.max(3,Math.floor(angle*12));const rawName=String(d.data.name);if(rawName.length>maxChars)return;el.append(\"tspan\").attr(\"x\",0).attr(\"dy\",showValues&&angle>.3?\"-0.35em\":\"0em\").attr(\"fill\",contrastText(fillColor)).attr(\"font-size\",fontSize).attr(\"font-weight\",\"600\").text(rawName);if(showValues&&angle>.3){const valueFontSize=isLarge?\"11px\":\"9px\";el.append(\"tspan\").attr(\"x\",0).attr(\"dy\",\"1.2em\").attr(\"fill\",contrastTextMuted(fillColor)).attr(\"font-size\",valueFontSize).attr(\"font-weight\",\"400\").text(formatValue(d.value))}})}return __toCommonJS(sunburst_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
42
|
+
export const treemapBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var treemap_render_exports={};__export(treemap_render_exports,{renderChart:()=>renderTreemap});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function contrastTextMuted(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"rgba(255,255,255,0.7)\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"rgba(26,26,46,0.6)\":\"rgba(255,255,255,0.7)\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderTreemap(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field||encoding.label?.field;const valueField=config.valueField||encoding.size?.field;const parentField=config.parentField||null;const padding=config.padding??2;const width=container.clientWidth||800;const height=container.clientHeight||500;const titleHeight=spec.title?36:0;const contentPadding=8;const innerWidth=width-contentPadding*2;const innerHeight=height-titleHeight-contentPadding*2;const wrapper=document.createElement(\"div\");wrapper.style.cssText=`\n position: relative;\n width: ${width}px;\n height: ${height}px;\n background: ${DARK_BG};\n border-radius: 8px;\n overflow: hidden;\n font-family: Inter, system-ui, sans-serif;\n `;container.appendChild(wrapper);if(spec.title){const titleEl=document.createElement(\"div\");titleEl.style.cssText=`\n text-align: center;\n color: ${TEXT_COLOR};\n font-size: 14px;\n font-weight: 600;\n line-height: ${titleHeight}px;\n height: ${titleHeight}px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 0 10px;\n `;titleEl.textContent=spec.title;titleEl.title=spec.title;wrapper.appendChild(titleEl)}const contentArea=document.createElement(\"div\");contentArea.style.cssText=`\n position: relative;\n width: ${innerWidth}px;\n height: ${innerHeight}px;\n margin: 0 ${contentPadding}px ${contentPadding}px;\n `;wrapper.appendChild(contentArea);const tooltip=createTooltip(container);if(valueField&&isAllZeros(data,valueField)){const emptyDiv=document.createElement(\"div\");emptyDiv.style.cssText=`\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${innerWidth}px;\n height: ${innerHeight}px;\n color: ${TEXT_MUTED};\n font-size: 14px;\n font-family: Inter, system-ui, sans-serif;\n `;emptyDiv.textContent=\"All values are zero\";contentArea.appendChild(emptyDiv);return}const root=buildHierarchy(data,categoryField,valueField,parentField,config);const treemapLayout=d3.treemap().size([innerWidth,innerHeight]).padding(padding).round(true);treemapLayout(root);const colorScale=buildColorScale(encoding.color,data);const isQuantitativeColor=encoding.color?.type===\"quantitative\";const colorField=encoding.color?.field;const leaves=root.leaves();for(const leaf of leaves){const cellW=Math.max(leaf.x1-leaf.x0,0);const cellH=Math.max(leaf.y1-leaf.y0,0);if(cellW<1||cellH<1)continue;const fillColor=isQuantitativeColor?colorScale(Number(leaf.data._data?.[colorField]??leaf.value)):parentField&&leaf.parent?.data?.name?colorScale(leaf.parent.data.name):colorScale(leaf.data.name);const cell=document.createElement(\"div\");cell.style.cssText=`\n position: absolute;\n left: ${leaf.x0}px;\n top: ${leaf.y0}px;\n width: ${cellW}px;\n height: ${cellH}px;\n background: ${fillColor};\n border-radius: 3px;\n border: ${config.borderWidth??1}px solid ${DARK_BG};\n opacity: 1;\n overflow: hidden;\n box-sizing: border-box;\n cursor: default;\n `;if(cellW>30&&cellH>20){const textPad=Math.min(6,cellW*.08);const labelColor=contrastText(fillColor);const valueColor=contrastTextMuted(fillColor);const textContainer=document.createElement(\"div\");textContainer.style.cssText=`\n padding: ${textPad}px;\n overflow: hidden;\n height: 100%;\n box-sizing: border-box;\n `;if(config.showLabels!==false){const fontSize=cellW>80?12:10;const charWidth=fontSize*.6;const maxChars=Math.max(2,Math.floor((cellW-textPad*2)/charWidth));const rawName=leaf.data.name;const displayName=rawName.length>maxChars?rawName.slice(0,maxChars-1)+\"\\u2026\":rawName;const label=document.createElement(\"div\");label.style.cssText=`\n color: ${labelColor};\n font-weight: 700;\n font-size: ${fontSize}px;\n line-height: 1.25;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n `;label.textContent=displayName;if(rawName.length>maxChars)label.title=rawName;textContainer.appendChild(label)}if(cellW>40&&cellH>36){const value=document.createElement(\"div\");value.style.cssText=`\n color: ${valueColor};\n font-weight: 400;\n font-size: ${cellW>80?\"11px\":\"9px\"};\n line-height: 1.3;\n margin-top: 2px;\n `;value.textContent=formatValue(leaf.value);textContainer.appendChild(value)}cell.appendChild(textContainer)}cell.addEventListener(\"mouseover\",event=>{cell.style.filter=\"brightness(1.15)\";cell.style.outline=\"2px solid #fff\";cell.style.outlineOffset=\"-2px\";cell.style.zIndex=\"10\";const parentName=parentField&&leaf.parent?.data?.name?leaf.parent.data.name+\" > \":\"\";showTooltip(tooltip,`<strong>${parentName}${leaf.data.name}</strong><br/>${valueField}: ${formatValue(leaf.value)}`,event)});cell.addEventListener(\"mousemove\",event=>{positionTooltip(tooltip,event)});cell.addEventListener(\"mouseout\",()=>{cell.style.filter=\"\";cell.style.outline=\"none\";cell.style.zIndex=\"\";hideTooltip(tooltip)});contentArea.appendChild(cell)}}function buildHierarchy(data,categoryField,valueField,parentField,config){const allVals=data.map(d=>Number(d[valueField])||0).filter(v=>v>0);const maxVal=allVals.length>0?Math.max(...allVals):0;const minVisible=maxVal*.02;const clampVal=v=>v>0&&v<minVisible?minVisible:v;if(parentField){const parents=[...new Set(data.map(d=>d[parentField]))];const hierarchy2={name:\"root\",children:parents.map(p=>({name:p,children:data.filter(d=>d[parentField]===p).map(d=>({name:d[categoryField]||d[config.childField]||d[parentField],value:clampVal(Number(d[valueField])||0),_data:d}))}))};return d3.hierarchy(hierarchy2).sum(d=>d.value).sort((a,b)=>b.value-a.value)}const hierarchy={name:\"root\",children:data.map(d=>({name:d[categoryField],value:clampVal(Number(d[valueField])||0),_data:d}))};return d3.hierarchy(hierarchy).sum(d=>d.value).sort((a,b)=>b.value-a.value)}return __toCommonJS(treemap_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
43
|
+
export const violinBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var violin_render_exports={};__export(violin_render_exports,{renderChart:()=>renderViolin});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function addSortControls(svg,container,spec,dims,renderFn){const currentSortBy=spec.config.sortBy||\"value\";const currentSortOrder=spec.config.sortOrder||\"descending\";const xPos=dims.width-dims.margin.right-40;const yPos=24;const controls=svg.append(\"g\").attr(\"class\",\"sort-controls\").attr(\"transform\",`translate(${xPos}, ${yPos})`).style(\"opacity\",0).style(\"cursor\",\"pointer\").style(\"transition\",\"opacity 0.2s\").style(\"user-select\",\"none\").style(\"-webkit-user-select\",\"none\");controls.append(\"rect\").attr(\"x\",-26).attr(\"y\",-10).attr(\"width\",52).attr(\"height\",20).attr(\"rx\",4).attr(\"fill\",\"#1e2028\").attr(\"stroke\",\"#2d3041\").attr(\"stroke-width\",1);controls.append(\"text\").attr(\"x\",-8).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"9px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").attr(\"font-weight\",\"600\").attr(\"fill\",TEXT_MUTED).text(currentSortBy===\"category\"?\"ABC\":\"123\");controls.append(\"text\").attr(\"x\",14).attr(\"y\",3).attr(\"text-anchor\",\"middle\").attr(\"font-size\",\"11px\").attr(\"fill\",TEXT_MUTED).text(currentSortOrder===\"descending\"?\"\\u25BC\":\"\\u25B2\");svg.on(\"mouseenter\",()=>{controls.style(\"opacity\",1)}).on(\"mouseleave\",()=>{controls.style(\"opacity\",0)});controls.on(\"click\",event=>{event.stopPropagation();const curSortBy=spec.config.sortBy||\"value\";const curSortOrder=spec.config.sortOrder||\"descending\";let newSortBy;let newSortOrder;if(curSortBy===\"value\"&&curSortOrder===\"descending\"){newSortBy=\"value\";newSortOrder=\"ascending\"}else if(curSortBy===\"value\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"ascending\"}else if(curSortBy===\"category\"&&curSortOrder===\"ascending\"){newSortBy=\"category\";newSortOrder=\"descending\"}else{newSortBy=\"value\";newSortOrder=\"descending\"}spec.config.sortBy=newSortBy;spec.config.sortOrder=newSortOrder;container.innerHTML=\"\";renderFn(container,spec)})}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function gaussianKernel(u){return 1/Math.sqrt(2*Math.PI)*Math.exp(-.5*u*u)}function stdDev(values){const n=values.length;if(n<2)return 1;const mean=values.reduce((s,v)=>s+v,0)/n;const variance=values.reduce((s,v)=>s+(v-mean)**2,0)/(n-1);return Math.sqrt(variance)}function kde(values,samplePoints,bandwidth){const n=values.length;return samplePoints.map(x=>{const density=values.reduce((sum,xi)=>sum+gaussianKernel((x-xi)/bandwidth),0)/(n*bandwidth);return{value:x,density}})}function silvermanBandwidth(values){const sd=stdDev(values);const n=values.length;const bw=1.06*sd*Math.pow(n,-.2);if(bw>0)return bw;const range=Math.max(...values)-Math.min(...values);return range>0?range*.1:1}function quartiles(sorted){const n=sorted.length;if(n===0)return{q1:0,median:0,q3:0};if(n===1)return{q1:sorted[0],median:sorted[0],q3:sorted[0]};const median=n%2===1?sorted[Math.floor(n/2)]:(sorted[n/2-1]+sorted[n/2])/2;const lowerHalf=sorted.slice(0,Math.floor(n/2));const upperHalf=sorted.slice(Math.ceil(n/2));const q1=lowerHalf.length%2===1?lowerHalf[Math.floor(lowerHalf.length/2)]:(lowerHalf[lowerHalf.length/2-1]+lowerHalf[lowerHalf.length/2])/2;const q3=upperHalf.length%2===1?upperHalf[Math.floor(upperHalf.length/2)]:(upperHalf[upperHalf.length/2-1]+upperHalf[upperHalf.length/2])/2;return{q1,median,q3}}function renderViolin(container,spec){const{config,encoding,data}=spec;const valueField=config.valueField||encoding.y?.field||Object.keys(data[0]).find(k=>typeof data[0][k]===\"number\")||Object.keys(data[0])[1];const categoryField=config.categoryField||encoding.x?.field||Object.keys(data[0])[0];const showBoxPlot=config.showBoxPlot??false;const showMedian=config.showMedian??true;const showQuartiles=config.showQuartiles??false;const userBandwidth=typeof config.bandwidth===\"number\"?config.bandwidth:void 0;let groups=[...new Set(data.map(d=>d[categoryField]))];if(config.sortBy===\"value\"){const medianMap=new Map;for(const group of groups){const vals=data.filter(d=>d[categoryField]===group).map(d=>Number(d[valueField])).filter(v=>!isNaN(v)).sort((a,b)=>a-b);medianMap.set(String(group),vals.length>0?quartiles(vals).median:0)}const order=config.sortOrder===\"ascending\"?1:-1;groups.sort((a,b)=>order*((medianMap.get(String(a))||0)-(medianMap.get(String(b))||0)))}else if(config.sortBy===\"category\"){const order=config.sortOrder===\"ascending\"?1:-1;groups.sort((a,b)=>order*String(a).localeCompare(String(b),void 0,{sensitivity:\"base\",numeric:true}))}const allValues=data.map(d=>Number(d[valueField])).filter(v=>!isNaN(v));const labels=groups.map(String);const containerWidth=container.clientWidth||800;const estimatedBandWidth=(containerWidth-140)/labels.length;const needsRotation=shouldRotateLabels(labels,estimatedBandWidth);const bottomMargin=calculateBottomMargin(labels,needsRotation);const{svg,g,dims}=createSvg(container,spec,{bottom:bottomMargin,left:70});const tooltip=createTooltip(container);const xScale=d3.scaleBand().domain(groups).range([0,dims.innerWidth]).padding(.1);const valuePadding=(d3.max(allValues)-d3.min(allValues))*.05||1;const yScale=d3.scaleLinear().domain([d3.min(allValues)-valuePadding,d3.max(allValues)+valuePadding]).range([dims.innerHeight,0]).nice();const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,25)));styleAxis(xAxis);if(needsRotation){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);const colorScale=buildColorScale(encoding.color,data);const bandWidth=xScale.bandwidth();const maxHalfWidth=groups.length===1?Math.min(bandWidth*.45,dims.innerWidth*.2):bandWidth*.45;const yDomain=yScale.domain();const sampleCount=80;const step=(yDomain[1]-yDomain[0])/(sampleCount-1);const samplePoints=Array.from({length:sampleCount},(_,i)=>yDomain[0]+i*step);const groupData=groups.map(group=>{const groupValues=data.filter(d=>d[categoryField]===group).map(d=>Number(d[valueField])).filter(v=>!isNaN(v)).sort((a,b)=>a-b);const stats=groupValues.length>0?quartiles(groupValues):{q1:0,median:0,q3:0};return{group,values:groupValues,stats}});g.selectAll(\".violin-hover-target\").data(groupData).join(\"rect\").attr(\"class\",\"violin-hover-target\").attr(\"x\",d=>xScale(d.group)).attr(\"y\",0).attr(\"width\",bandWidth).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(`.violin-shape-${groups.indexOf(d.group)}`).attr(\"opacity\",.9).attr(\"stroke-width\",2);showTooltip(tooltip,`<strong>${d.group}</strong><br/>Count: ${d.values.length}<br/>Median: ${formatValue(d.stats.median)}<br/>Q1: ${formatValue(d.stats.q1)}<br/>Q3: ${formatValue(d.stats.q3)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(_event,d){g.selectAll(`.violin-shape-${groups.indexOf(d.group)}`).attr(\"opacity\",.7).attr(\"stroke-width\",1.5);hideTooltip(tooltip)});groups.forEach((group,gi)=>{const gd=groupData[gi];const groupValues=gd.values;if(groupValues.length===0)return;const bandwidth=userBandwidth||silvermanBandwidth(groupValues);const densityPoints=kde(groupValues,samplePoints,bandwidth);const maxDensity=d3.max(densityPoints,d=>d.density)||1;const widthScale=density=>density/maxDensity*maxHalfWidth;const xCenter=xScale(group)+bandWidth/2;const colorValue=encoding.color?.field?data.find(d=>d[categoryField]===group)?.[encoding.color.field]:group;const fillColor=colorScale(colorValue);const violinArea=d3.area().x0(d=>xCenter-widthScale(d.density)).x1(d=>xCenter+widthScale(d.density)).y(d=>yScale(d.value)).curve(d3.curveBasis);g.append(\"path\").datum(densityPoints).attr(\"class\",`violin-shape violin-shape-${gi}`).attr(\"d\",violinArea).attr(\"fill\",fillColor).attr(\"opacity\",.7).attr(\"stroke\",fillColor).attr(\"stroke-width\",1.5).attr(\"stroke-opacity\",.9).attr(\"pointer-events\",\"none\");if(showBoxPlot&&groupValues.length>=4){const stats=gd.stats;const iqr=stats.q3-stats.q1;const whiskerLow=Math.max(groupValues[0],stats.q1-1.5*iqr);const whiskerHigh=Math.min(groupValues[groupValues.length-1],stats.q3+1.5*iqr);const boxWidth=Math.min(bandWidth*.12,12);g.append(\"line\").attr(\"x1\",xCenter).attr(\"x2\",xCenter).attr(\"y1\",yScale(whiskerLow)).attr(\"y2\",yScale(whiskerHigh)).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\");g.append(\"rect\").attr(\"x\",xCenter-boxWidth/2).attr(\"y\",yScale(stats.q3)).attr(\"width\",boxWidth).attr(\"height\",yScale(stats.q1)-yScale(stats.q3)).attr(\"fill\",\"rgba(15, 17, 23, 0.7)\").attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",1.5).attr(\"rx\",2).attr(\"pointer-events\",\"none\");const capWidth=boxWidth*.8;[whiskerLow,whiskerHigh].forEach(val=>{g.append(\"line\").attr(\"x1\",xCenter-capWidth/2).attr(\"x2\",xCenter+capWidth/2).attr(\"y1\",yScale(val)).attr(\"y2\",yScale(val)).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",1.5).attr(\"pointer-events\",\"none\")})}if(showQuartiles&&groupValues.length>=4){const stats=gd.stats;[stats.q1,stats.q3].forEach(qVal=>{const qDensity=densityPoints.reduce((closest,pt)=>Math.abs(pt.value-qVal)<Math.abs(closest.value-qVal)?pt:closest,densityPoints[0]);const qHalfWidth=widthScale(qDensity.density);g.append(\"line\").attr(\"x1\",xCenter-qHalfWidth).attr(\"x2\",xCenter+qHalfWidth).attr(\"y1\",yScale(qVal)).attr(\"y2\",yScale(qVal)).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"3,3\").attr(\"stroke-opacity\",.7).attr(\"pointer-events\",\"none\")})}if(showMedian&&groupValues.length>=1){const stats=gd.stats;const medianDensity=densityPoints.reduce((closest,pt)=>Math.abs(pt.value-stats.median)<Math.abs(closest.value-stats.median)?pt:closest,densityPoints[0]);const medianHalfWidth=widthScale(medianDensity.density);g.append(\"line\").attr(\"x1\",xCenter-medianHalfWidth).attr(\"x2\",xCenter+medianHalfWidth).attr(\"y1\",yScale(stats.median)).attr(\"y2\",yScale(stats.median)).attr(\"stroke\",\"#ffffff\").attr(\"stroke-width\",2).attr(\"stroke-linecap\",\"round\").attr(\"pointer-events\",\"none\")}});addSortControls(svg,container,spec,dims,renderViolin)}return __toCommonJS(violin_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
44
|
+
export const waffleBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var waffle_render_exports={};__export(waffle_render_exports,{renderChart:()=>renderWaffle});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function resolvePalette(name){const palette=PALETTE_MAP[name];return palette?[...palette]:null}function isSequentialPalette(name){return!!name&&name in sequential}function isDivergingPalette(name){return!!name&&name in diverging}function buildColorScale(encoding,data,valueField){if(!encoding||!encoding.field){return()=>categorical[0]}const field=encoding.field;if(encoding.highlight&&encoding.highlight.values.length>0){const dataValues=new Set(data.map(d=>d[field]));const hasMatchingValues=encoding.highlight.values.some(v=>dataValues.has(v));if(hasMatchingValues){const highlightSet=new Set(encoding.highlight.values);const highlightColors=Array.isArray(encoding.highlight.color)?encoding.highlight.color:encoding.highlight.color?[encoding.highlight.color]:[categorical[0]];const mutedColor=encoding.highlight.mutedColor||\"#6b7280\";const mutedOpacity=encoding.highlight.mutedOpacity??1;return value=>{if(highlightSet.has(value)){const highlightArray=Array.from(highlightSet);const idx=highlightArray.indexOf(value);return highlightColors[idx%highlightColors.length]}if(mutedOpacity<1){const hex=mutedColor.replace(\"#\",\"\");const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);return`rgba(${r}, ${g}, ${b}, ${mutedOpacity})`}return mutedColor}}}if(encoding.palette){const palette2=resolvePalette(encoding.palette);if(palette2){if(isDivergingPalette(encoding.palette)&&encoding.type===\"quantitative\"){const values=data.map(d=>Number(d[field]));const maxAbs=Math.max(Math.abs(d3.min(values)),Math.abs(d3.max(values)))||1;const mid=Math.floor(palette2.length/2);return d3.scaleLinear().domain([-maxAbs,0,maxAbs]).range([palette2[0],palette2[mid],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb).clamp(true)}if((isSequentialPalette(encoding.palette)||isDivergingPalette(encoding.palette))&&valueField){const valueExtent=d3.extent(data,d=>Number(d[valueField]));const colorScale=d3.scaleLinear().domain([valueExtent[0],valueExtent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb);const categoryToValue=new Map(data.map(d=>[d[field],Number(d[valueField])]));return category=>{const value=categoryToValue.get(category);return value!==void 0?colorScale(value):palette2[0]}}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleLinear().domain([extent[0],extent[1]]).range([palette2[0],palette2[palette2.length-1]]).interpolate(d3.interpolateRgb)}const domain2=[...new Set(data.map(d=>d[field]))];return d3.scaleOrdinal().domain(domain2).range(palette2)}}if(encoding.scale?.domain&&encoding.scale?.range){if(encoding.type===\"quantitative\"){return d3.scaleLinear().domain(encoding.scale.domain).range(encoding.scale.range).interpolate(d3.interpolateRgb)}return d3.scaleOrdinal().domain(encoding.scale.domain).range(encoding.scale.range)}if(encoding.type===\"quantitative\"){const extent=d3.extent(data,d=>Number(d[field]));return d3.scaleSequential(d3.interpolateViridis).domain(extent)}const domain=[...new Set(data.map(d=>d[field]))];let palette=[...categorical];if(domain.length>palette.length){const extra=d3.quantize(d3.interpolateRainbow,domain.length-palette.length+1);palette=palette.concat(extra)}return d3.scaleOrdinal().domain(domain).range(palette)}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function renderEmptyState(g,dims,message=\"All values are zero\"){g.append(\"text\").attr(\"x\",dims.innerWidth/2).attr(\"y\",dims.innerHeight/2).attr(\"text-anchor\",\"middle\").attr(\"dominant-baseline\",\"middle\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"14px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(message)}function isAllZeros(data,field){return data.every(d=>Number(d[field])===0)}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderWaffle(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.color?.field;const valueField=config.valueField;const gridSize=config.gridSize||10;const totalSquares=gridSize*gridSize;const total=config.total||data.reduce((s,d)=>s+(Number(d[valueField])||0),0);const items=data.map(d=>({category:d[categoryField],value:Number(d[valueField])||0,percentage:d._percentage??(Number(d[valueField])||0)/total*100,squares:d._squares??Math.round((Number(d[valueField])||0)/total*totalSquares)}));for(const item of items){if(item.value>0&&item.squares<1){item.squares=1}}const sumSquares=items.reduce((s,item)=>s+item.squares,0);if(sumSquares!==totalSquares&&items.length>0){items[0].squares+=totalSquares-sumSquares}const colorScale=buildColorScale(encoding.color,data);const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>200&&containerWidth>250;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);let legendDiv=null;if(showLegend){const legendItems=items.map(item=>({label:String(item.category),color:colorScale(item.category),extra:`${item.percentage.toFixed(1)}%`}));legendDiv=createLegend(legendItems);container.appendChild(legendDiv)}const{svg,g,dims}=createSvg(chartWrapper,spec,{top:40,left:20,right:20,bottom:20});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const tooltip=createTooltip(container);if(isAllZeros(data,valueField)){renderEmptyState(g,dims);return}const maxSquareFromWidth=(dims.innerWidth-(gridSize-1)*2)/gridSize;const maxSquareFromHeight=(dims.innerHeight-(gridSize-1)*2)/gridSize;const autoSquareSize=Math.max(4,Math.floor(Math.min(maxSquareFromWidth,maxSquareFromHeight)));const squareSize=config.squareSize?Math.min(config.squareSize,autoSquareSize):autoSquareSize;const gap=config.gap??2;const grid=[];let sqIndex=0;items.forEach(item=>{for(let s=0;s<item.squares;s++){const row=Math.floor(sqIndex/gridSize);const col=sqIndex%gridSize;grid.push({category:item.category,row,col});sqIndex++}});const gridPixelW=gridSize*squareSize+(gridSize-1)*gap;const gridPixelH=gridSize*squareSize+(gridSize-1)*gap;const offsetX=Math.max(0,(dims.innerWidth-gridPixelW)/2);const offsetY=Math.max(0,(dims.innerHeight-gridPixelH)/2);g.selectAll(\".waffle-square\").data(grid).join(\"rect\").attr(\"class\",\"waffle-square\").attr(\"x\",d=>offsetX+d.col*(squareSize+gap)).attr(\"y\",d=>offsetY+(gridSize-1-d.row)*(squareSize+gap)).attr(\"width\",squareSize).attr(\"height\",squareSize).attr(\"rx\",Math.min(3,squareSize*.15)).attr(\"fill\",d=>colorScale(d.category)).attr(\"pointer-events\",\"none\");g.selectAll(\".waffle-hover\").data(grid).join(\"rect\").attr(\"class\",\"waffle-hover\").attr(\"x\",d=>offsetX+d.col*(squareSize+gap)).attr(\"y\",d=>offsetY+(gridSize-1-d.row)*(squareSize+gap)).attr(\"width\",squareSize).attr(\"height\",squareSize).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(\".waffle-square\").attr(\"opacity\",sq=>sq.category===d.category?1:.3);const item=items.find(i=>i.category===d.category);showTooltip(tooltip,`<strong>${d.category}</strong><br/>${formatValue(item?.value??0)}<br/>${item?.percentage.toFixed(1)}%`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".waffle-square\").attr(\"opacity\",1);hideTooltip(tooltip)})}return __toCommonJS(waffle_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|
|
45
|
+
export const waterfallBundle = "\"use strict\";var __dolex=(()=>{var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var waterfall_render_exports={};__export(waterfall_render_exports,{renderChart:()=>renderWaterfall});var categorical=[\"#6280c1\",\"#c99a3e\",\"#48a882\",\"#c46258\",\"#5ea4c8\",\"#9e74bf\",\"#c88450\",\"#3ea898\",\"#b85e78\",\"#85a63e\",\"#807cba\",\"#b09838\"];var sequential={blue:[\"#e8f0fe\",\"#c5d9fc\",\"#9cbcf8\",\"#6e9cf4\",\"#4a7eec\",\"#2f63d9\",\"#1d4cb8\",\"#143893\",\"#0d2668\"],green:[\"#e2f5ec\",\"#b6e6d0\",\"#7ed4ae\",\"#4cc08c\",\"#2ba86f\",\"#1e8d58\",\"#157244\",\"#0d5833\",\"#084024\"],purple:[\"#f0e8ff\",\"#d8c6fd\",\"#bd9efa\",\"#a278f3\",\"#8755e8\",\"#6d3dd1\",\"#5630ab\",\"#402485\",\"#2d1961\"],warm:[\"#fef0e2\",\"#fdd9b4\",\"#fbbd7e\",\"#f79e4d\",\"#ef7e25\",\"#d4620f\",\"#ac4a0a\",\"#843608\",\"#5e2506\"]};var diverging={blueRed:[\"#2166ac\",\"#4393c3\",\"#6db4d5\",\"#a6d1e8\",\"#e0e0e0\",\"#f1b0a0\",\"#e07060\",\"#ca3832\",\"#b2182b\"],greenPurple:[\"#1b7837\",\"#41a055\",\"#73c378\",\"#a8dda0\",\"#e0e0e0\",\"#c4a5d9\",\"#9970be\",\"#7640a0\",\"#5e2d84\"],tealOrange:[\"#0d6b6e\",\"#2a9191\",\"#54b4b0\",\"#92d4cc\",\"#e0e0e0\",\"#f5c28a\",\"#e69b44\",\"#c87422\",\"#a35212\"],redGreen:[\"#b84040\",\"#c85e5e\",\"#d48080\",\"#daa8a8\",\"#c8c8c8\",\"#a0c8a0\",\"#68a868\",\"#489048\",\"#307430\"]};var darkTheme={background:\"#0f1117\",surface:\"#161822\",surfaceRaised:\"#1e2028\",axis:\"#4b5563\",grid:\"#1f2937\",border:\"#2a2d3a\",text:\"#e2e5eb\",textMuted:\"#9ca3af\",textDim:\"#6b7280\",plotArea:\"#13151d\",overlay:\"rgba(0, 0, 0, 0.6)\"};var colorSchemes={\"traffic-light\":[\"#ef4444\",\"#f59e0b\",\"#10b981\"],\"profit-loss\":[\"#ef4444\",\"#6b7280\",\"#10b981\"],temperature:[\"#3b82f6\",\"#9ca3af\",\"#f59e0b\"]};var DARK_BG=darkTheme.background;var AXIS_COLOR=darkTheme.axis;var GRID_COLOR=darkTheme.grid;var TEXT_COLOR=darkTheme.text;var TEXT_MUTED=darkTheme.textMuted;var DEFAULT_MARGINS={top:40,right:30,bottom:50,left:60};function createSvg(container,spec,marginOverrides){const margin={...DEFAULT_MARGINS,...marginOverrides};const width=container.clientWidth||800;const height=container.clientHeight||500;const innerWidth=width-margin.left-margin.right;const innerHeight=height-margin.top-margin.bottom;const svg=d3.select(container).append(\"svg\").attr(\"width\",width).attr(\"height\",height).style(\"background\",DARK_BG).style(\"border-radius\",\"8px\");if(spec.title){const titleEl=svg.append(\"text\").attr(\"x\",width/2).attr(\"y\",24).attr(\"text-anchor\",\"middle\").attr(\"fill\",TEXT_COLOR).attr(\"font-size\",\"14px\").attr(\"font-weight\",\"600\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(spec.title);truncateTitle(titleEl,spec.title,width-20)}const g=svg.append(\"g\").attr(\"transform\",`translate(${margin.left},${margin.top})`);return{svg,g,dims:{width,height,innerWidth,innerHeight,margin}}}var PALETTE_MAP={categorical,...sequential,...diverging,...colorSchemes};function contrastText(bgColor){const rgb=parseColor(bgColor);if(!rgb)return\"#ffffff\";const luminance=relativeLuminance(rgb[0],rgb[1],rgb[2]);return luminance>.18?\"#1a1a2e\":\"#ffffff\"}function parseColor(color){const hexMatch=color.match(/^#([0-9a-f]{3,8})$/i);if(hexMatch){let hex=hexMatch[1];if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return[parseInt(hex.substring(0,2),16),parseInt(hex.substring(2,4),16),parseInt(hex.substring(4,6),16)]}const rgbMatch=color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/);if(rgbMatch){return[Number(rgbMatch[1]),Number(rgbMatch[2]),Number(rgbMatch[3])]}return null}function relativeLuminance(r,g,b){const[rs,gs,bs]=[r/255,g/255,b/255].map(c=>c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4));return .2126*rs+.7152*gs+.0722*bs}function getAdaptiveTickCount(availableSpace,minSpacing=60){return Math.max(3,Math.floor(availableSpace/minSpacing))}function shouldRotateLabels(labels,barWidth,fontSize=11){const avgLabelLength=labels.reduce((sum,l)=>sum+String(l).length,0)/labels.length;const estimatedLabelWidth=avgLabelLength*(fontSize*.6);return estimatedLabelWidth>barWidth*.8}function calculateBottomMargin(labels,willRotate,fontSize=11){if(!willRotate)return 60;const maxLength=Math.max(...labels.map(l=>String(l).length));const charWidth=fontSize*.6;const estimatedHeight=maxLength*charWidth*.7;return Math.max(70,Math.min(150,estimatedHeight+35))}function truncateLabel(label,maxLength=25){const str=String(label);if(str.length<=maxLength)return str;return str.slice(0,maxLength-1)+\"\\u2026\"}function truncateTitle(textEl,fullText,maxWidth){const node=textEl.node();if(!node||!node.getComputedTextLength)return;if(node.getComputedTextLength()<=maxWidth)return;let lo=0;let hi=fullText.length;while(lo<hi){const mid=lo+hi+1>>1;node.textContent=fullText.slice(0,mid)+\"\\u2026\";if(node.getComputedTextLength()<=maxWidth){lo=mid}else{hi=mid-1}}node.textContent=lo>0?fullText.slice(0,lo)+\"\\u2026\":\"\\u2026\";textEl.append(\"title\").text(fullText)}function shouldShowValueLabels(config,barDimension,isHorizontal){if(config.showLabels!==void 0)return config.showLabels;return isHorizontal?barDimension>=20:barDimension>=35}function styleAxis(axis){axis.selectAll(\".domain\").attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",.5);axis.selectAll(\".tick line\").attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",.5).attr(\"stroke-dasharray\",\"2,2\");axis.selectAll(\".tick text\").attr(\"fill\",TEXT_MUTED).attr(\"font-size\",\"11px\").attr(\"font-family\",\"Inter, system-ui, sans-serif\");fixTickLabels(axis)}function fixTickLabels(axis){const ticks=axis.selectAll(\".tick text\");const nodes=[];ticks.each(function(){nodes.push(this)});if(nodes.length<2)return;const texts=nodes.map(n=>n.textContent||\"\");const uniqueTexts=new Set(texts);if(uniqueTexts.size<Math.min(nodes.length,3)){const values=[];ticks.each(function(d){values.push(Number(d))});const validValues=values.filter(v=>!isNaN(v));if(validValues.length<2)return;const min=Math.min(...validValues);const max=Math.max(...validValues);const span=max-min;if(span>0){const precision=span>=1?1:Math.max(2,Math.ceil(-Math.log10(span))+2);const fmt=v=>{if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Number.isInteger(v)&&Math.abs(v)<1e3)return v.toFixed(0);return v.toFixed(precision)};ticks.each(function(d){const v=Number(d);if(!isNaN(v))this.textContent=fmt(v)})}const reformattedTexts=nodes.map(n=>n.textContent||\"\");const seen=new Set;reformattedTexts.forEach((t,i)=>{if(seen.has(t)){nodes[i].style.display=\"none\";const line=nodes[i].parentNode?.querySelector(\"line\");if(line)line.style.display=\"none\"}else{seen.add(t)}})}}var tooltipEl=null;var tooltipContainer=null;function createTooltip(container){tooltipContainer=container;if(tooltipEl&&document.body.contains(tooltipEl)){return tooltipEl}tooltipEl=document.createElement(\"div\");tooltipEl.style.cssText=`\n position: fixed;\n pointer-events: none;\n background: #1e2028;\n color: ${TEXT_COLOR};\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: Inter, system-ui, sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n border: 1px solid #2d3041;\n z-index: 10000;\n opacity: 0;\n transition: opacity 0.15s;\n max-width: 300px;\n line-height: 1.5;\n `;document.body.appendChild(tooltipEl);return tooltipEl}function positionTooltip(tooltip,event){const gap=12;const tw=tooltip.offsetWidth;const th=tooltip.offsetHeight;const vh=window.innerHeight;const rect=tooltipContainer?.getBoundingClientRect();const midX=rect?rect.left+rect.width/2:window.innerWidth/2;let left=event.clientX>midX?event.clientX-tw-gap:event.clientX+gap;let top=event.clientY-gap;if(top+th>vh)top=event.clientY-th-gap;if(left<0)left=0;if(top<0)top=0;tooltip.style.left=left+\"px\";tooltip.style.top=top+\"px\"}function showTooltip(tooltip,html,event){tooltip.innerHTML=html;tooltip.style.opacity=\"1\";positionTooltip(tooltip,event)}function hideTooltip(tooltip){tooltip.style.opacity=\"0\"}function smartTruncateLabels(labels,maxLen){if(labels.every(l=>l.length<=maxLen))return labels;const prefixLen=findCommonAffixLength(labels,\"prefix\");const suffixLen=findCommonAffixLength(labels,\"suffix\");const hasSharedAffix=prefixLen+suffixLen>5;if(hasSharedAffix){return labels.map(l=>{if(l.length<=maxLen)return l;const uniquePart=l.slice(prefixLen,l.length-suffixLen||void 0);if(uniquePart.length<=maxLen-2){return\"\\u2026\"+uniquePart+\"\\u2026\"}const keep=maxLen-2;return\"\\u2026\"+uniquePart.slice(0,keep)+\"\\u2026\"})}return labels.map(l=>{if(l.length<=maxLen)return l;const keep=maxLen-1;const front=Math.ceil(keep*.5);const back=keep-front;return back>0?l.slice(0,front)+\"\\u2026\"+l.slice(-back):l.slice(0,keep)+\"\\u2026\"})}function findCommonAffixLength(strings,direction){if(strings.length<=1)return 0;const get=direction===\"prefix\"?(s,i)=>s[i]:(s,i)=>s[s.length-1-i];const minLen=Math.min(...strings.map(s=>s.length));let len=0;for(let i=0;i<minLen;i++){const ch=get(strings[0],i);if(strings.every(s=>get(s,i)===ch)){len++}else{break}}return len}function createLegend(source,options){const shape=options?.shape??\"square\";const callbacks=options?.callbacks;let entries;if(Array.isArray(source)&&source.length>0&&source[0]?.label!==void 0){entries=source}else{const domain=source.domain?.()??[];entries=domain.map(label=>({label:String(label),color:source(label)}))}if(!entries.length){return document.createElement(\"div\")}const maxItems=options?.maxItems??12;let overflowCount=0;if(entries.length>maxItems){overflowCount=entries.length-(maxItems-1);entries=entries.slice(0,maxItems-1)}const maxLabelLen=20;const displayLabels=smartTruncateLabels(entries.map(e=>e.label),maxLabelLen);const legend=document.createElement(\"div\");legend.style.cssText=`\n display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;\n padding: 6px 12px 8px; font-family: Inter, system-ui, sans-serif;\n font-size: 11px; line-height: 1;\n `;entries.forEach((entry,idx)=>{const item=document.createElement(\"div\");item.style.cssText=callbacks?\"display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: pointer; transition: opacity 0.15s;\":\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";item.setAttribute(\"data-series\",entry.label);const swatch=document.createElement(\"span\");if(shape===\"circle\"){swatch.style.cssText=`\n width: 8px; height: 8px; border-radius: 50%;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line\"){swatch.style.cssText=`\n width: 16px; height: 3px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}else if(shape===\"line-dot\"){swatch.style.cssText=`\n width: 16px; height: 2px; border-radius: 1px;\n background: ${entry.color}; flex-shrink: 0; position: relative;\n transition: transform 0.15s;\n `;const dot=document.createElement(\"span\");dot.style.cssText=`\n position: absolute; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n width: 6px; height: 6px; border-radius: 50%;\n background: ${entry.color}; border: 1px solid ${DARK_BG};\n `;swatch.appendChild(dot)}else{swatch.style.cssText=`\n width: 10px; height: 10px; border-radius: 2px;\n background: ${entry.color}; flex-shrink: 0; transition: transform 0.15s;\n `}const text=document.createElement(\"span\");text.style.color=TEXT_MUTED;text.textContent=displayLabels[idx];if(entry.label.length>maxLabelLen)text.title=entry.label;item.appendChild(swatch);item.appendChild(text);if(entry.extra){const extra=document.createElement(\"span\");extra.style.color=TEXT_MUTED;extra.style.opacity=\"0.7\";extra.textContent=entry.extra;item.appendChild(extra)}if(callbacks){item.addEventListener(\"mouseenter\",()=>{swatch.style.transform=shape===\"line\"||shape===\"line-dot\"?\"scaleY(2)\":\"scale(1.4)\";callbacks.onHover?.(entry.label)});item.addEventListener(\"mouseleave\",()=>{swatch.style.transform=\"\";callbacks.onLeave?.()})}legend.appendChild(item)});if(overflowCount>0){const more=document.createElement(\"div\");more.style.cssText=\"display: flex; align-items: center; gap: 5px; white-space: nowrap;\";const moreText=document.createElement(\"span\");moreText.style.cssText=`color: ${TEXT_MUTED}; opacity: 0.6; font-style: italic;`;moreText.textContent=`+${overflowCount} more`;more.appendChild(moreText);legend.appendChild(more)}return legend}function formatValue(v){if(Math.abs(v)>=1e12)return(v/1e12).toFixed(1)+\"T\";if(Math.abs(v)>=1e9)return(v/1e9).toFixed(1)+\"B\";if(Math.abs(v)>=1e6)return(v/1e6).toFixed(1)+\"M\";if(Math.abs(v)>=1e3)return(v/1e3).toFixed(1)+\"K\";if(Math.abs(v)<1&&v!==0){const precision=Math.max(2,Math.ceil(-Math.log10(Math.abs(v)))+1);return v.toFixed(Math.min(precision,6))}return Number.isInteger(v)?v.toFixed(0):v.toFixed(1)}function renderWaterfall(container,spec){const{config,encoding,data}=spec;const categoryField=config.categoryField||encoding.x?.field;const valueField=config.valueField||encoding.y?.field;if(!categoryField||!valueField)return;const totalColumns=new Set;if(Array.isArray(config.totalColumns)){for(const t of config.totalColumns){if(t===\"first\")totalColumns.add(String(data[0]?.[categoryField]));else if(t===\"last\")totalColumns.add(String(data[data.length-1]?.[categoryField]));else totalColumns.add(String(t))}}else{if(data.length>=2){totalColumns.add(String(data[0]?.[categoryField]));totalColumns.add(String(data[data.length-1]?.[categoryField]))}}const items=[];let running=0;for(const d of data){const label=String(d[categoryField]);const value=Number(d[valueField])||0;const isTotal=totalColumns.has(label);if(isTotal){items.push({label,value,isTotal:true,start:0,end:value,type:\"total\"});running=value}else{const start=running;running+=value;items.push({label,value,isTotal:false,start,end:running,type:value>=0?\"positive\":\"negative\"})}}const positiveColor=config.positiveColor||\"#3dd9a0\";const negativeColor=config.negativeColor||\"#ff6b5e\";const totalColor=config.totalColor||categorical[0];const showConnectors=config.showConnectors!==false;const labels=items.map(d=>d.label);const containerWidth=container.clientWidth||800;const containerHeight=container.clientHeight||500;const showLegend=containerHeight>250&&containerWidth>300;container.style.display=\"flex\";container.style.flexDirection=\"column\";container.style.background=DARK_BG;container.style.borderRadius=\"8px\";container.style.overflow=\"hidden\";const chartWrapper=document.createElement(\"div\");chartWrapper.style.flex=\"1\";chartWrapper.style.minHeight=\"0\";container.appendChild(chartWrapper);if(showLegend){const legendDiv=createLegend([{label:\"Increase\",color:positiveColor},{label:\"Decrease\",color:negativeColor},{label:\"Total\",color:totalColor}]);container.appendChild(legendDiv)}const estBarWidth=(containerWidth-140)/labels.length;const willRotate=shouldRotateLabels(labels,estBarWidth);const bottomMargin=calculateBottomMargin(labels,willRotate);const{svg,g,dims}=createSvg(chartWrapper,spec,{bottom:bottomMargin,left:70,top:40,right:30});svg.style(\"background\",\"none\").style(\"border-radius\",\"0\");const tooltip=createTooltip(container);const allValues=items.flatMap(d=>[d.start,d.end]);const minVal=Math.min(0,...allValues);const maxVal=Math.max(0,...allValues);const xScale=d3.scaleBand().domain(labels).range([0,dims.innerWidth]).padding(.3);const yScale=d3.scaleLinear().domain([minVal,maxVal]).range([dims.innerHeight,0]).nice();const xAxis=g.append(\"g\").attr(\"class\",\"x-axis\").attr(\"transform\",`translate(0,${dims.innerHeight})`).call(d3.axisBottom(xScale).tickSize(0).tickPadding(8).tickFormat(d=>truncateLabel(d,20)));styleAxis(xAxis);if(willRotate){g.selectAll(\".x-axis .tick text\").attr(\"transform\",\"rotate(-35)\").attr(\"text-anchor\",\"end\").attr(\"dx\",\"-0.5em\").attr(\"dy\",\"0.15em\")}const yTickCount=getAdaptiveTickCount(dims.innerHeight,40);const yAxis=g.append(\"g\").attr(\"class\",\"y-axis\").call(d3.axisLeft(yScale).ticks(yTickCount).tickSize(-dims.innerWidth).tickPadding(8).tickFormat(d=>formatValue(d)));styleAxis(yAxis);if(minVal<0){g.append(\"line\").attr(\"x1\",0).attr(\"x2\",dims.innerWidth).attr(\"y1\",yScale(0)).attr(\"y2\",yScale(0)).attr(\"stroke\",AXIS_COLOR).attr(\"stroke-width\",1)}if(showConnectors){for(let i=0;i<items.length-1;i++){const current=items[i];const next=items[i+1];const connectY=yScale(current.end);const x1=(xScale(current.label)??0)+xScale.bandwidth();const x2=xScale(next.label)??0;g.append(\"line\").attr(\"class\",\"connector\").attr(\"x1\",x1).attr(\"x2\",x2).attr(\"y1\",connectY).attr(\"y2\",connectY).attr(\"stroke\",GRID_COLOR).attr(\"stroke-width\",1).attr(\"stroke-dasharray\",\"3,3\")}}g.selectAll(\".bar-hover-target\").data(items).join(\"rect\").attr(\"class\",\"bar-hover-target\").attr(\"x\",d=>xScale(d.label)).attr(\"y\",0).attr(\"width\",xScale.bandwidth()).attr(\"height\",dims.innerHeight).attr(\"fill\",\"transparent\").attr(\"cursor\",\"pointer\").on(\"mouseover\",function(event,d){g.selectAll(`.bar[data-label=\"${CSS.escape(d.label)}\"]`).attr(\"opacity\",.8);const prefix=d.isTotal?\"Total\":d.value>=0?\"+\":\"\";showTooltip(tooltip,`<strong>${d.label}</strong><br/>${prefix}${formatValue(d.value)}<br/>Running: ${formatValue(d.end)}`,event)}).on(\"mousemove\",event=>{positionTooltip(tooltip,event)}).on(\"mouseout\",function(){g.selectAll(\".bar\").attr(\"opacity\",1);hideTooltip(tooltip)});const maxBarWidth=Math.min(80,dims.innerWidth*.3);const wBarWidth=Math.min(xScale.bandwidth(),maxBarWidth);const wBarOffset=(xScale.bandwidth()-wBarWidth)/2;g.selectAll(\".bar\").data(items).join(\"rect\").attr(\"class\",\"bar\").attr(\"data-label\",d=>d.label).attr(\"x\",d=>(xScale(d.label)??0)+wBarOffset).attr(\"y\",d=>yScale(Math.max(d.start,d.end))).attr(\"width\",wBarWidth).attr(\"height\",d=>Math.max(2,Math.abs(yScale(d.start)-yScale(d.end)))).attr(\"fill\",d=>{if(d.type===\"total\")return totalColor;return d.type===\"positive\"?positiveColor:negativeColor}).attr(\"rx\",2).attr(\"pointer-events\",\"none\");const showLabels=shouldShowValueLabels(config,xScale.bandwidth(),false);if(showLabels){g.selectAll(\".bar-label\").data(items).join(\"text\").attr(\"class\",\"bar-label\").attr(\"x\",d=>(xScale(d.label)??0)+xScale.bandwidth()/2).attr(\"y\",d=>{const top=yScale(Math.max(d.start,d.end));const barH=Math.abs(yScale(d.start)-yScale(d.end));return barH<20?top-6:top+14}).attr(\"text-anchor\",\"middle\").attr(\"fill\",d=>{const barH=Math.abs(yScale(d.start)-yScale(d.end));if(barH<20)return TEXT_MUTED;const fillColor=d.type===\"total\"?totalColor:d.type===\"positive\"?positiveColor:negativeColor;return contrastText(fillColor)}).attr(\"font-size\",\"10px\").attr(\"font-weight\",\"500\").attr(\"font-family\",\"Inter, system-ui, sans-serif\").text(d=>{const prefix=d.isTotal?\"\":d.value>=0?\"+\":\"\";return prefix+formatValue(d.value)})}}return __toCommonJS(waterfall_render_exports);})();\n\nvar renderChart = __dolex.renderChart;";
|