From 91e2eef1772dc06118ce5aa1e0b388d12bf91918 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 14 Aug 2026 22:20:37 -0600 Subject: [PATCH 1/3] Simplify catalog example source --- .changeset/clean-catalog-motion.md | 5 + API-FRICTION.md | 98 +- .../cases/01-line-gaps/example.tsx | 45 +- .../conformance/cases/01-line-gaps/plot.ts | 2 +- .../02-multi-line-end-labels/example.tsx | 92 +- .../cases/02-multi-line-end-labels/plot.ts | 2 +- .../02-multi-line-end-labels/selection.ts | 2 +- .../02-multi-line-end-labels/tanstack.test.ts | 10 +- .../03-temperature-range-band/example.tsx | 100 +- .../cases/03-temperature-range-band/plot.ts | 2 +- .../cases/04-stacked-time-area/example.tsx | 86 +- .../cases/04-stacked-time-area/plot.ts | 2 +- .../cases/100-radial-bars/example.tsx | 81 +- .../cases/100-radial-bars/recharts.ts | 2 +- .../cases/100-radial-bars/selection.ts | 2 +- .../cases/100-radial-bars/tanstack.test.ts | 8 +- .../cases/101-sunburst/example.tsx | 94 +- .../cases/101-sunburst/recharts.ts | 2 +- .../cases/101-sunburst/selection.ts | 2 +- .../cases/101-sunburst/tanstack.test.ts | 8 +- .../cases/101-sunburst/transform.ts | 2 +- .../cases/102-world-choropleth/example.tsx | 98 +- .../cases/102-world-choropleth/plot.ts | 6 +- .../cases/103-bubble-map/example.tsx | 96 +- .../conformance/cases/103-bubble-map/plot.ts | 6 +- .../cases/104-orthographic-globe/example.tsx | 99 +- .../cases/104-orthographic-globe/plot.ts | 2 +- .../cases/105-route-map/example.tsx | 83 +- .../conformance/cases/105-route-map/plot.ts | 2 +- .../cases/105-route-map/transform.ts | 2 +- .../cases/106-polar-line/echarts.ts | 2 +- .../cases/106-polar-line/example.tsx | 98 +- .../cases/106-polar-line/transform.test.ts | 2 +- .../cases/106-polar-line/transform.ts | 4 +- .../cases/107-polar-scatter/echarts.ts | 2 +- .../cases/107-polar-scatter/example.tsx | 102 +- .../cases/107-polar-scatter/transform.test.ts | 2 +- .../cases/107-polar-scatter/transform.ts | 4 +- .../cases/108-country-choropleth/example.tsx | 100 +- .../cases/108-country-choropleth/plot.ts | 6 +- .../cases/109-us-state-choropleth/example.tsx | 66 +- .../109-us-state-choropleth/tanstack.test.ts | 6 +- .../109-us-state-choropleth/transform.ts | 6 +- .../cases/110-projection-gallery/example.tsx | 103 +- .../cases/110-projection-gallery/plot.ts | 2 +- .../110-projection-gallery/tanstack.test.ts | 10 +- .../cases/111-basic-sankey/example.tsx | 196 +- .../cases/111-basic-sankey/tanstack.test.ts | 8 +- .../cases/111-sankey-flow/example.tsx | 356 ++- .../cases/111-sankey-flow/tanstack.test.ts | 8 +- .../cases/112-motion-entrance/example.tsx | 6 +- .../cases/113-motion-updates/example.tsx | 5 +- .../cases/114-spring-line-motion/example.tsx | 5 +- .../cases/115-definition-motion/example.tsx | 5 +- .../cases/116-geometry-morph/example.tsx | 5 +- .../cases/117-focus-cursor-motion/example.tsx | 5 +- .../118-token-usage-calendar/example.tsx | 10 +- .../118-token-usage-calendar/tanstack.test.ts | 10 +- .../119-stacked-bar-band-cursor/example.tsx | 173 +- .../119-stacked-bar-band-cursor/model.ts | 2 +- .../119-stacked-bar-band-cursor/tanstack.ts | 9 +- .../119-stacked-bar-band-cursor/view.tsx | 4 +- .../120-themed-interactive-area/example.tsx | 312 ++- .../tanstack.test.ts | 8 +- .../120-themed-interactive-area/tanstack.ts | 24 +- .../121-active-bar-dashboard/example.tsx | 5 +- .../122-premium-kpi-sparklines/example.tsx | 8 +- .../cases/123-active-donut-metric/example.tsx | 11 +- .../124-theme-palette-matrix/example.tsx | 2 +- .../cases/125-sales-funnel/example.tsx | 90 +- .../cases/126-drillable-sunburst/example.tsx | 7 +- .../cases/126-drillable-sunburst/model.ts | 4 +- .../126-drillable-sunburst/tanstack.test.ts | 2 +- .../cases/126-drillable-sunburst/tanstack.ts | 2 +- .../cases/127-shadcn-dashboard/example.tsx | 196 +- .../127-shadcn-dashboard/tanstack.test.ts | 4 +- .../cases/128-shadcn-bar-multiple/example.tsx | 138 +- .../cases/128-shadcn-bar-multiple/styles.css | 319 --- .../cases/128-shadcn-bar-multiple/tanstack.ts | 1 - .../129-shadcn-pie-donut-text/example.tsx | 121 +- .../129-shadcn-pie-donut-text/styles.css | 314 --- .../129-shadcn-pie-donut-text/tanstack.ts | 1 - .../cases/13-interval-timeline/example.tsx | 74 +- .../cases/13-interval-timeline/plot.ts | 2 +- .../130-shadcn-radar-multiple/example.tsx | 180 +- .../130-shadcn-radar-multiple/styles.css | 314 --- .../130-shadcn-radar-multiple/tanstack.ts | 1 - .../cases/131-shadcn-radial-text/example.tsx | 197 +- .../cases/131-shadcn-radial-text/styles.css | 314 --- .../cases/131-shadcn-radial-text/tanstack.ts | 1 - .../132-shadcn-tooltip-advanced/example.tsx | 146 +- .../132-shadcn-tooltip-advanced/styles.css | 281 --- .../132-shadcn-tooltip-advanced/tanstack.ts | 1 - .../cases/133-shadcn-area-axes/example.tsx | 151 +- .../cases/133-shadcn-area-axes/styles.css | 319 --- .../cases/133-shadcn-area-axes/tanstack.ts | 1 - .../cases/134-shadcn-area-default/example.tsx | 145 +- .../cases/134-shadcn-area-default/styles.css | 319 --- .../cases/134-shadcn-area-default/tanstack.ts | 1 - .../135-shadcn-area-gradient/example.tsx | 171 +- .../cases/135-shadcn-area-gradient/styles.css | 319 --- .../135-shadcn-area-gradient/tanstack.ts | 1 - .../cases/136-shadcn-area-icons/example.tsx | 154 +- .../cases/136-shadcn-area-icons/styles.css | 296 --- .../cases/136-shadcn-area-icons/tanstack.ts | 1 - .../137-shadcn-area-interactive/example.tsx | 217 +- .../137-shadcn-area-interactive/styles.css | 259 -- .../137-shadcn-area-interactive/tanstack.ts | 1 - .../cases/138-shadcn-area-legend/example.tsx | 154 +- .../cases/138-shadcn-area-legend/styles.css | 300 --- .../cases/138-shadcn-area-legend/tanstack.ts | 1 - .../cases/139-shadcn-area-linear/example.tsx | 145 +- .../cases/139-shadcn-area-linear/styles.css | 319 --- .../cases/139-shadcn-area-linear/tanstack.ts | 1 - .../cases/14-error-bars/example.tsx | 114 +- .../conformance/cases/14-error-bars/plot.ts | 2 +- .../cases/14-error-bars/tanstack.test.ts | 10 +- .../example.tsx | 166 +- .../140-shadcn-area-stacked-expand/styles.css | 319 --- .../tanstack.ts | 1 - .../cases/141-shadcn-area-stacked/example.tsx | 151 +- .../cases/141-shadcn-area-stacked/styles.css | 319 --- .../cases/141-shadcn-area-stacked/tanstack.ts | 1 - .../cases/142-shadcn-area-step/example.tsx | 145 +- .../cases/142-shadcn-area-step/styles.css | 319 --- .../cases/142-shadcn-area-step/tanstack.ts | 1 - .../cases/143-shadcn-bar-active/example.tsx | 144 +- .../cases/143-shadcn-bar-active/styles.css | 319 --- .../cases/143-shadcn-bar-active/tanstack.ts | 1 - .../cases/144-shadcn-bar-default/example.tsx | 110 +- .../cases/144-shadcn-bar-default/styles.css | 319 --- .../cases/144-shadcn-bar-default/tanstack.ts | 1 - .../145-shadcn-bar-horizontal/example.tsx | 114 +- .../145-shadcn-bar-horizontal/styles.css | 319 --- .../145-shadcn-bar-horizontal/tanstack.ts | 1 - .../146-shadcn-bar-interactive/example.tsx | 168 +- .../146-shadcn-bar-interactive/styles.css | 288 --- .../146-shadcn-bar-interactive/tanstack.ts | 1 - .../147-shadcn-bar-label-custom/example.tsx | 171 +- .../147-shadcn-bar-label-custom/styles.css | 319 --- .../147-shadcn-bar-label-custom/tanstack.ts | 1 - .../cases/148-shadcn-bar-label/example.tsx | 111 +- .../cases/148-shadcn-bar-label/styles.css | 319 --- .../cases/148-shadcn-bar-label/tanstack.ts | 1 - .../cases/149-shadcn-bar-mixed/example.tsx | 128 +- .../cases/149-shadcn-bar-mixed/styles.css | 319 --- .../cases/149-shadcn-bar-mixed/tanstack.ts | 1 - .../conformance/cases/15-boxplot/example.tsx | 100 +- .../conformance/cases/15-boxplot/plot.ts | 2 +- .../cases/15-boxplot/tanstack.test.ts | 10 +- .../cases/150-shadcn-bar-negative/example.tsx | 115 +- .../cases/150-shadcn-bar-negative/styles.css | 319 --- .../cases/150-shadcn-bar-negative/tanstack.ts | 1 - .../cases/151-shadcn-bar-stacked/example.tsx | 138 +- .../cases/151-shadcn-bar-stacked/styles.css | 300 --- .../cases/151-shadcn-bar-stacked/tanstack.ts | 1 - .../cases/152-shadcn-line-default/example.tsx | 163 +- .../cases/152-shadcn-line-default/styles.css | 319 --- .../cases/152-shadcn-line-default/tanstack.ts | 1 - .../153-shadcn-line-dots-colors/example.tsx | 148 +- .../153-shadcn-line-dots-colors/styles.css | 319 --- .../153-shadcn-line-dots-colors/tanstack.ts | 1 - .../154-shadcn-line-dots-custom/example.tsx | 158 +- .../154-shadcn-line-dots-custom/styles.css | 319 --- .../154-shadcn-line-dots-custom/tanstack.ts | 1 - .../cases/155-shadcn-line-dots/example.tsx | 158 +- .../cases/155-shadcn-line-dots/styles.css | 319 --- .../cases/155-shadcn-line-dots/tanstack.ts | 1 - .../156-shadcn-line-interactive/example.tsx | 196 +- .../156-shadcn-line-interactive/styles.css | 288 --- .../156-shadcn-line-interactive/tanstack.ts | 1 - .../157-shadcn-line-label-custom/example.tsx | 148 +- .../157-shadcn-line-label-custom/styles.css | 319 --- .../157-shadcn-line-label-custom/tanstack.ts | 1 - .../cases/158-shadcn-line-label/example.tsx | 158 +- .../cases/158-shadcn-line-label/styles.css | 319 --- .../cases/158-shadcn-line-label/tanstack.ts | 1 - .../cases/159-shadcn-line-linear/example.tsx | 163 +- .../cases/159-shadcn-line-linear/styles.css | 319 --- .../cases/159-shadcn-line-linear/tanstack.ts | 1 - .../conformance/cases/16-lollipop/example.tsx | 93 +- .../conformance/cases/16-lollipop/plot.ts | 2 +- .../160-shadcn-line-multiple/example.tsx | 167 +- .../cases/160-shadcn-line-multiple/styles.css | 319 --- .../160-shadcn-line-multiple/tanstack.ts | 1 - .../cases/161-shadcn-line-step/example.tsx | 163 +- .../cases/161-shadcn-line-step/styles.css | 319 --- .../cases/161-shadcn-line-step/tanstack.ts | 1 - .../162-shadcn-pie-donut-active/example.tsx | 121 +- .../162-shadcn-pie-donut-active/styles.css | 314 --- .../162-shadcn-pie-donut-active/tanstack.ts | 1 - .../cases/163-shadcn-pie-donut/example.tsx | 121 +- .../cases/163-shadcn-pie-donut/styles.css | 314 --- .../cases/163-shadcn-pie-donut/tanstack.ts | 1 - .../164-shadcn-pie-interactive/example.tsx | 252 +- .../164-shadcn-pie-interactive/styles.css | 276 --- .../164-shadcn-pie-interactive/tanstack.ts | 1 - .../165-shadcn-pie-label-custom/example.tsx | 121 +- .../165-shadcn-pie-label-custom/styles.css | 314 --- .../165-shadcn-pie-label-custom/tanstack.ts | 1 - .../166-shadcn-pie-label-list/example.tsx | 121 +- .../166-shadcn-pie-label-list/styles.css | 314 --- .../166-shadcn-pie-label-list/tanstack.ts | 1 - .../cases/167-shadcn-pie-label/example.tsx | 121 +- .../cases/167-shadcn-pie-label/styles.css | 314 --- .../cases/167-shadcn-pie-label/tanstack.ts | 1 - .../cases/168-shadcn-pie-legend/example.tsx | 119 +- .../cases/168-shadcn-pie-legend/styles.css | 322 --- .../cases/168-shadcn-pie-legend/tanstack.ts | 1 - .../169-shadcn-pie-separator-none/example.tsx | 121 +- .../169-shadcn-pie-separator-none/styles.css | 314 --- .../169-shadcn-pie-separator-none/tanstack.ts | 1 - .../conformance/cases/17-dumbbell/example.tsx | 100 +- .../conformance/cases/17-dumbbell/plot.ts | 2 +- .../cases/170-shadcn-pie-simple/example.tsx | 121 +- .../cases/170-shadcn-pie-simple/styles.css | 314 --- .../cases/170-shadcn-pie-simple/tanstack.ts | 1 - .../cases/171-shadcn-pie-stacked/example.tsx | 160 +- .../cases/171-shadcn-pie-stacked/styles.css | 314 --- .../cases/171-shadcn-pie-stacked/tanstack.ts | 1 - .../172-shadcn-radar-default/example.tsx | 154 +- .../cases/172-shadcn-radar-default/styles.css | 314 --- .../172-shadcn-radar-default/tanstack.ts | 1 - .../cases/173-shadcn-radar-dots/example.tsx | 172 +- .../cases/173-shadcn-radar-dots/styles.css | 314 --- .../cases/173-shadcn-radar-dots/tanstack.ts | 1 - .../example.tsx | 153 +- .../styles.css | 314 --- .../tanstack.ts | 1 - .../example.tsx | 172 +- .../styles.css | 314 --- .../tanstack.ts | 1 - .../176-shadcn-radar-grid-circle/example.tsx | 172 +- .../176-shadcn-radar-grid-circle/styles.css | 314 --- .../176-shadcn-radar-grid-circle/tanstack.ts | 1 - .../177-shadcn-radar-grid-custom/example.tsx | 154 +- .../177-shadcn-radar-grid-custom/styles.css | 314 --- .../177-shadcn-radar-grid-custom/tanstack.ts | 1 - .../178-shadcn-radar-grid-fill/example.tsx | 153 +- .../178-shadcn-radar-grid-fill/styles.css | 314 --- .../178-shadcn-radar-grid-fill/tanstack.ts | 1 - .../179-shadcn-radar-grid-none/example.tsx | 170 +- .../179-shadcn-radar-grid-none/styles.css | 314 --- .../179-shadcn-radar-grid-none/tanstack.ts | 1 - .../cases/18-cumulative-histogram/example.tsx | 55 +- .../cases/18-cumulative-histogram/plot.ts | 2 +- .../cases/180-shadcn-radar-icons/example.tsx | 183 +- .../cases/180-shadcn-radar-icons/styles.css | 291 --- .../cases/180-shadcn-radar-icons/tanstack.ts | 1 - .../181-shadcn-radar-label-custom/example.tsx | 234 +- .../181-shadcn-radar-label-custom/styles.css | 311 --- .../181-shadcn-radar-label-custom/tanstack.ts | 1 - .../cases/182-shadcn-radar-legend/example.tsx | 183 +- .../cases/182-shadcn-radar-legend/styles.css | 295 --- .../cases/182-shadcn-radar-legend/tanstack.ts | 1 - .../183-shadcn-radar-lines-only/example.tsx | 180 +- .../183-shadcn-radar-lines-only/styles.css | 314 --- .../183-shadcn-radar-lines-only/tanstack.ts | 1 - .../cases/184-shadcn-radar-radius/example.tsx | 179 +- .../cases/184-shadcn-radar-radius/styles.css | 314 --- .../cases/184-shadcn-radar-radius/tanstack.ts | 1 - .../cases/185-shadcn-radial-grid/example.tsx | 173 +- .../cases/185-shadcn-radial-grid/styles.css | 314 --- .../cases/185-shadcn-radial-grid/tanstack.ts | 1 - .../cases/186-shadcn-radial-label/example.tsx | 222 +- .../cases/186-shadcn-radial-label/styles.css | 314 --- .../cases/186-shadcn-radial-label/tanstack.ts | 1 - .../cases/187-shadcn-radial-shape/example.tsx | 197 +- .../cases/187-shadcn-radial-shape/styles.css | 314 --- .../cases/187-shadcn-radial-shape/tanstack.ts | 1 - .../188-shadcn-radial-simple/example.tsx | 165 +- .../cases/188-shadcn-radial-simple/styles.css | 314 --- .../188-shadcn-radial-simple/tanstack.ts | 1 - .../189-shadcn-radial-stacked/example.tsx | 161 +- .../189-shadcn-radial-stacked/styles.css | 314 --- .../189-shadcn-radial-stacked/tanstack.ts | 1 - .../cases/19-moving-average-line/example.tsx | 63 +- .../cases/19-moving-average-line/plot.ts | 2 +- .../190-shadcn-tooltip-default/example.tsx | 146 +- .../190-shadcn-tooltip-default/styles.css | 281 --- .../190-shadcn-tooltip-default/tanstack.ts | 1 - .../191-shadcn-tooltip-formatter/example.tsx | 146 +- .../191-shadcn-tooltip-formatter/styles.css | 281 --- .../191-shadcn-tooltip-formatter/tanstack.ts | 1 - .../192-shadcn-tooltip-icons/example.tsx | 149 +- .../cases/192-shadcn-tooltip-icons/styles.css | 258 -- .../192-shadcn-tooltip-icons/tanstack.ts | 1 - .../example.tsx | 146 +- .../styles.css | 281 --- .../tanstack.ts | 1 - .../example.tsx | 146 +- .../styles.css | 281 --- .../tanstack.ts | 1 - .../example.tsx | 146 +- .../styles.css | 281 --- .../tanstack.ts | 1 - .../example.tsx | 146 +- .../styles.css | 281 --- .../tanstack.ts | 1 - .../197-shadcn-tooltip-label-none/example.tsx | 146 +- .../197-shadcn-tooltip-label-none/styles.css | 281 --- .../197-shadcn-tooltip-label-none/tanstack.ts | 1 - .../20-normalized-stacked-area/example.tsx | 67 +- .../cases/20-normalized-stacked-area/plot.ts | 2 +- .../cases/21-streamgraph/example.tsx | 82 +- .../conformance/cases/21-streamgraph/plot.ts | 2 +- .../cases/21-streamgraph/tanstack.test.ts | 13 +- .../cases/22-bollinger-band/example.tsx | 79 +- .../cases/22-bollinger-band/plot.ts | 2 +- .../cases/22-bollinger-band/selection.ts | 2 +- .../cases/22-bollinger-band/tanstack.test.ts | 10 +- .../example.tsx | 88 +- .../24-quantitative-binned-heatmap/plot.ts | 2 +- .../cases/25-calendar-heatmap/example.tsx | 71 +- .../cases/25-calendar-heatmap/plot.ts | 2 +- .../cases/25-calendar-heatmap/selection.ts | 2 +- .../cases/26-diverging-likert/example.tsx | 75 +- .../cases/26-diverging-likert/plot.ts | 2 +- .../cases/26-diverging-likert/selection.ts | 2 +- .../26-diverging-likert/tanstack.test.ts | 6 +- .../cases/27-parallel-coordinates/example.tsx | 75 +- .../cases/27-parallel-coordinates/plot.ts | 2 +- .../27-parallel-coordinates/selection.ts | 2 +- .../27-parallel-coordinates/tanstack.test.ts | 6 +- .../27-parallel-coordinates/transform.test.ts | 2 +- .../27-parallel-coordinates/transform.ts | 2 +- .../cases/28-candlestick/example.tsx | 96 +- .../conformance/cases/28-candlestick/plot.ts | 2 +- .../cases/28-candlestick/selection.ts | 2 +- .../cases/29-waterfall/example.tsx | 87 +- .../conformance/cases/29-waterfall/plot.ts | 4 +- .../cases/29-waterfall/tanstack.test.ts | 6 +- .../cases/30-slopegraph/example.tsx | 117 +- .../conformance/cases/30-slopegraph/plot.ts | 2 +- .../cases/30-slopegraph/tanstack.test.ts | 8 +- .../cases/30-slopegraph/transform.ts | 2 +- .../cases/31-linear-regression/example.tsx | 118 +- .../cases/31-linear-regression/plot.ts | 4 +- .../31-linear-regression/tanstack.test.ts | 4 +- .../cases/32-change-arrows/example.tsx | 67 +- .../cases/32-change-arrows/plot.ts | 2 +- .../cases/33-difference-chart/example.tsx | 67 +- .../cases/33-difference-chart/plot.ts | 2 +- .../33-difference-chart/tanstack.test.ts | 4 +- .../cases/33-difference-chart/transform.ts | 2 +- .../cases/34-pointer-tooltip/example.tsx | 8 +- .../cases/34-pointer-tooltip/plot.ts | 2 +- .../cases/34-pointer-tooltip/selection.ts | 2 +- .../cases/34-pointer-tooltip/tanstack.ts | 2 +- .../cases/35-grouped-tooltip/example.tsx | 6 +- .../cases/35-grouped-tooltip/plot.ts | 2 +- .../cases/35-grouped-tooltip/selection.ts | 2 +- .../cases/36-hierarchy-tree/example.tsx | 146 +- .../cases/36-hierarchy-tree/plot.ts | 2 +- .../cases/36-hierarchy-tree/selection.ts | 2 +- .../cases/36-hierarchy-tree/tanstack.test.ts | 8 +- .../cases/37-delaunay-network/example.tsx | 75 +- .../cases/37-delaunay-network/plot.ts | 2 +- .../cases/38-contour-topography/example.tsx | 53 +- .../38-contour-topography/tanstack.test.ts | 9 +- .../cases/38-contour-topography/transform.ts | 2 +- .../cases/39-density-contours/example.tsx | 65 +- .../cases/39-density-contours/plot.ts | 2 +- .../39-density-contours/tanstack.test.ts | 9 +- .../40-force-directed-network/example.tsx | 132 +- .../cases/40-force-directed-network/layout.ts | 2 +- .../cases/40-force-directed-network/plot.ts | 2 +- .../tanstack.test.ts | 6 +- .../40-force-directed-network/transform.ts | 2 +- .../cases/40-geojson-map/example.tsx | 68 +- .../conformance/cases/40-geojson-map/plot.ts | 2 +- .../cases/41-waffle-unit-chart/example.tsx | 51 +- .../cases/41-waffle-unit-chart/plot.ts | 2 +- .../cases/42-vector-field/example.tsx | 41 +- .../conformance/cases/42-vector-field/plot.ts | 2 +- .../cases/42-vector-field/selection.ts | 2 +- .../cases/42-vector-field/tanstack.test.ts | 14 +- .../cases/43-hexbin-density/example.tsx | 92 +- .../cases/43-hexbin-density/plot.ts | 2 +- .../cases/44-framed-scatter/example.tsx | 69 +- .../cases/44-framed-scatter/plot.ts | 2 +- .../cases/50-empirical-cdf/example.tsx | 71 +- .../cases/50-empirical-cdf/plot.ts | 2 +- .../cases/50-empirical-cdf/tanstack.test.ts | 8 +- .../51-faceted-distributions/example.tsx | 106 +- .../cases/51-faceted-distributions/plot.ts | 2 +- .../51-faceted-distributions/tanstack.test.ts | 10 +- .../cases/52-beeswarm-dodge/example.tsx | 61 +- .../cases/52-beeswarm-dodge/plot.ts | 2 +- .../cases/53-log-scale-scatter/example.tsx | 80 +- .../cases/53-log-scale-scatter/plot.ts | 2 +- .../53-log-scale-scatter/tanstack.test.ts | 9 +- .../cases/54-bump-ranking/example.tsx | 117 +- .../conformance/cases/54-bump-ranking/plot.ts | 4 +- .../cases/54-bump-ranking/tanstack.test.ts | 8 +- .../cases/55-indexed-multi-line/example.tsx | 124 +- .../cases/55-indexed-multi-line/plot.ts | 2 +- .../55-indexed-multi-line/tanstack.test.ts | 53 +- .../cases/56-connected-scatter/example.tsx | 123 +- .../cases/56-connected-scatter/plot.ts | 2 +- .../56-connected-scatter/tanstack.test.ts | 12 +- .../cases/56-connected-scatter/transform.ts | 2 +- .../example.tsx | 287 ++- .../57-scatter-marginal-histograms/plot.ts | 4 +- .../tanstack.test.ts | 16 +- .../cases/58-select-extrema/example.tsx | 126 +- .../cases/58-select-extrema/plot.ts | 4 +- .../cases/58-select-extrema/tanstack.test.ts | 16 +- .../cases/59-grouped-reducer-bars/example.tsx | 71 +- .../cases/59-grouped-reducer-bars/plot.ts | 2 +- .../cases/60-lag-autocorrelation/example.tsx | 65 +- .../cases/60-lag-autocorrelation/plot.ts | 2 +- .../cases/61-quantile-ribbon/example.tsx | 84 +- .../cases/61-quantile-ribbon/plot.ts | 2 +- .../cases/61-quantile-ribbon/tanstack.test.ts | 13 +- .../cases/62-ridgeline-density/example.tsx | 93 +- .../cases/62-ridgeline-density/plot.ts | 2 +- .../cases/62-ridgeline-density/selection.ts | 2 +- .../62-ridgeline-density/tanstack.test.ts | 16 +- .../62-ridgeline-density/transform.test.ts | 2 +- .../cases/63-violin-distributions/example.tsx | 128 +- .../cases/63-violin-distributions/plot.ts | 2 +- .../63-violin-distributions/selection.ts | 2 +- .../63-violin-distributions/tanstack.test.ts | 20 +- .../63-violin-distributions/transform.test.ts | 2 +- .../cases/64-marimekko-mosaic/example.tsx | 103 +- .../cases/64-marimekko-mosaic/layout.test.ts | 2 +- .../cases/64-marimekko-mosaic/layout.ts | 2 +- .../cases/64-marimekko-mosaic/plot.ts | 2 +- .../cases/64-marimekko-mosaic/selection.ts | 2 +- .../64-marimekko-mosaic/tanstack.test.ts | 10 +- .../65-voronoi-nearest-tooltip/example.tsx | 8 +- .../cases/65-voronoi-nearest-tooltip/plot.ts | 2 +- .../cases/70-composed-chart/example.tsx | 97 +- .../cases/70-composed-chart/recharts.ts | 2 +- .../cases/70-composed-chart/tanstack.test.ts | 7 +- .../example.tsx | 81 +- .../recharts.ts | 2 +- .../selection.ts | 2 +- .../tanstack.test.ts | 28 +- .../transform.test.ts | 2 +- .../transform.ts | 2 +- .../cases/72-recharts-mixed-bars/example.tsx | 91 +- .../cases/72-recharts-mixed-bars/recharts.ts | 2 +- .../cases/73-many-point-scatter/example.tsx | 73 +- .../cases/73-many-point-scatter/recharts.ts | 2 +- .../cases/73-many-point-scatter/selection.ts | 2 +- .../73-many-point-scatter/tanstack.test.ts | 30 +- .../cases/73-many-point-scatter/transform.ts | 2 +- .../cases/74-recharts-treemap/example.tsx | 67 +- .../cases/74-recharts-treemap/recharts.ts | 2 +- .../cases/74-recharts-treemap/selection.ts | 2 +- .../74-recharts-treemap/tanstack.test.ts | 8 +- .../cases/74-recharts-treemap/transform.ts | 2 +- .../conformance/cases/75-radar/example.tsx | 132 +- .../conformance/cases/75-radar/recharts.ts | 2 +- .../conformance/cases/75-radar/selection.ts | 2 +- .../cases/75-radar/tanstack.test.ts | 8 +- .../cases/75-radar/transform.test.ts | 2 +- .../conformance/cases/75-radar/transform.ts | 2 +- .../conformance/cases/76-pie/example.tsx | 70 +- .../conformance/cases/76-pie/recharts.ts | 2 +- .../conformance/cases/76-pie/selection.ts | 2 +- .../conformance/cases/76-pie/tanstack.test.ts | 8 +- .../conformance/cases/77-donut/example.tsx | 72 +- .../conformance/cases/77-donut/recharts.ts | 2 +- .../conformance/cases/77-donut/selection.ts | 2 +- .../cases/77-donut/tanstack.test.ts | 8 +- .../conformance/cases/78-gauge/example.tsx | 70 +- .../conformance/cases/78-gauge/recharts.ts | 2 +- .../cases/78-gauge/tanstack.test.ts | 6 +- .../cases/78-gauge/transform.test.ts | 2 +- .../conformance/cases/78-gauge/transform.ts | 2 +- .../cases/80-echarts-axis-pointer/echarts.ts | 2 +- .../cases/80-echarts-axis-pointer/example.tsx | 144 +- .../80-echarts-axis-pointer/selection.ts | 2 +- .../80-echarts-axis-pointer/tanstack.test.ts | 14 +- .../cases/80-echarts-axis-pointer/tanstack.ts | 10 +- .../example.tsx | 6 +- .../81-recharts-interactive-legend/model.ts | 2 +- .../recharts.ts | 2 +- .../tanstack.test.ts | 4 +- .../82-chart-table-selection/example.tsx | 2 +- .../cases/82-chart-table-selection/model.ts | 2 +- .../82-chart-table-selection/recharts.ts | 2 +- .../82-chart-table-selection/tanstack.test.ts | 2 +- .../cases/82-chart-table-selection/view.tsx | 2 +- .../cases/83-focus-context-window/example.tsx | 12 +- .../cases/83-focus-context-window/model.ts | 2 +- .../cases/83-focus-context-window/plot.ts | 2 +- .../83-focus-context-window/tanstack.test.ts | 4 +- .../cases/83-focus-context-window/view.tsx | 4 +- .../example.tsx | 8 +- .../85-scrollable-resource-lanes/example.tsx | 4 +- .../data.test.ts | 2 +- .../echarts.ts | 4 +- .../example.tsx | 4 +- .../86-streaming-window-preservation/model.ts | 2 +- .../selection.ts | 2 +- .../tanstack.test.ts | 4 +- .../86-streaming-window-preservation/view.tsx | 4 +- .../data.test.ts | 2 +- .../echarts.ts | 2 +- .../example.tsx | 4 +- .../87-echarts-synchronized-cursors/model.ts | 2 +- .../selection.ts | 2 +- .../summary.ts | 2 +- .../tanstack.test.ts | 4 +- .../tanstack.ts | 4 +- .../87-echarts-synchronized-cursors/view.tsx | 4 +- .../cases/88-echarts-free-cursor/echarts.ts | 2 +- .../cases/88-echarts-free-cursor/example.tsx | 2 +- .../cases/88-echarts-free-cursor/model.ts | 2 +- .../cases/88-echarts-free-cursor/tanstack.ts | 2 +- .../cases/89-brush-range-selection/echarts.ts | 2 +- .../89-brush-range-selection/example.tsx | 4 +- .../cases/89-brush-range-selection/model.ts | 2 +- .../89-brush-range-selection/tanstack.test.ts | 4 +- .../89-brush-range-selection/tanstack.ts | 4 +- .../cases/89-brush-range-selection/view.tsx | 4 +- .../cases/90-zoomable-time-window/echarts.ts | 2 +- .../cases/90-zoomable-time-window/example.tsx | 4 +- .../cases/90-zoomable-time-window/model.ts | 2 +- .../90-zoomable-time-window/tanstack.test.ts | 4 +- .../cases/90-zoomable-time-window/tanstack.ts | 4 +- .../cases/90-zoomable-time-window/view.tsx | 2 +- .../91-timeline-playback-scrubber/echarts.ts | 4 +- .../91-timeline-playback-scrubber/example.tsx | 4 +- .../91-timeline-playback-scrubber/model.ts | 2 +- .../tanstack.test.ts | 4 +- .../91-timeline-playback-scrubber/tanstack.ts | 2 +- .../91-timeline-playback-scrubber/view.tsx | 2 +- .../cases/93-labeled-pie/example.tsx | 101 +- .../cases/93-labeled-pie/recharts.ts | 2 +- .../cases/93-labeled-pie/selection.ts | 2 +- .../cases/93-labeled-pie/tanstack.test.ts | 8 +- .../cases/94-center-donut/example.tsx | 98 +- .../cases/94-center-donut/recharts.ts | 2 +- .../cases/94-center-donut/selection.ts | 2 +- .../cases/94-center-donut/tanstack.test.ts | 11 +- .../cases/95-rounded-donut/example.tsx | 72 +- .../cases/95-rounded-donut/recharts.ts | 2 +- .../cases/95-rounded-donut/selection.ts | 2 +- .../cases/95-rounded-donut/tanstack.test.ts | 11 +- .../cases/96-nested-donut/example.tsx | 69 +- .../cases/96-nested-donut/recharts.ts | 2 +- .../cases/96-nested-donut/tanstack.test.ts | 9 +- .../cases/96-nested-donut/transform.test.ts | 2 +- .../cases/96-nested-donut/transform.ts | 2 +- .../conformance/cases/97-rose/example.tsx | 71 +- .../conformance/cases/97-rose/recharts.ts | 4 +- .../conformance/cases/97-rose/selection.ts | 2 +- .../cases/97-rose/tanstack.test.ts | 8 +- .../cases/98-needle-gauge/example.tsx | 166 +- .../cases/98-needle-gauge/recharts.ts | 2 +- .../cases/98-needle-gauge/tanstack.test.ts | 9 +- .../cases/99-comparative-radar/example.tsx | 119 +- .../cases/99-comparative-radar/recharts.ts | 2 +- .../cases/99-comparative-radar/selection.ts | 2 +- .../99-comparative-radar/tanstack.test.ts | 8 +- .../99-comparative-radar/transform.test.ts | 2 +- .../cases/99-comparative-radar/transform.ts | 2 +- .../conformance/cases/bar-grouped/example.tsx | 98 +- .../conformance/cases/bar-grouped/plot.ts | 2 +- .../cases/bar-grouped/tanstack.test.ts | 8 +- .../cases/bar-horizontal-ranking/example.tsx | 61 +- .../cases/bar-horizontal-ranking/plot.ts | 2 +- .../conformance/cases/bar-stacked/example.tsx | 65 +- .../conformance/cases/bar-stacked/plot.ts | 2 +- .../cases/bar-stacked/tanstack.test.ts | 8 +- .../cases/bar-vertical-sorted/example.tsx | 68 +- .../cases/bar-vertical-sorted/plot.ts | 2 +- .../cases/facets-anscombe/example.tsx | 81 +- .../conformance/cases/facets-anscombe/plot.ts | 2 +- .../cases/heatmap-labeled/example.tsx | 134 +- .../conformance/cases/heatmap-labeled/plot.ts | 2 +- .../conformance/cases/histogram/example.tsx | 76 +- .../conformance/cases/histogram/plot.ts | 2 +- .../cases/scatter-bubble/example.tsx | 71 +- .../conformance/cases/scatter-bubble/model.ts | 4 +- benchmarks/conformance/catalog-loader.test.ts | 18 +- benchmarks/conformance/catalog-loader.ts | 4 +- benchmarks/conformance/previews/manifest.json | 2 +- .../shared/fixtures/country-atlas.ts | 2 +- .../shared/fixtures/geography.test.ts | 8 +- .../shared/fixtures/simplify-geo.ts | 2 +- .../conformance/shared/shadcn-catalog-data.ts | 2 +- .../shared/shadcn-catalog-tanstack.tsx | 2152 ----------------- .../shared/shadcn-interaction.test.ts | 45 +- .../conformance/shared/shadcn-motion.test.ts | 80 +- .../conformance/shared/shadcn-motion.ts | 21 - .../shared/transforms/learning-poverty.ts | 2 +- docs/reference/motion.md | 6 + examples/charts-octane/package.json | 2 +- examples/charts-octane/src/charts.ts | 8 +- examples/charts-react/package.json | 2 +- examples/charts-react/src/charts.ts | 14 +- examples/conformance/package.json | 2 +- examples/conformance/src/source-view.test.ts | 6 +- examples/conformance/src/source-view.tsx | 2 +- examples/sandbox/package.json | 2 +- examples/sandbox/src/App.tsx | 2 +- examples/sandbox/src/plots.ts | 4 +- examples/sandbox/src/transforms.test.ts | 4 +- examples/sandbox/src/transforms.ts | 18 +- package.json | 2 +- packages/charts-core/docs/reference/motion.md | 6 + packages/charts-core/src/box.test.ts | 4 +- packages/charts-core/src/dom-types.ts | 21 + packages/charts-core/src/index.ts | 1 + .../charts-core/src/mark-decorative.test.ts | 2 + packages/charts-core/src/mark-decorative.ts | 20 +- packages/charts-core/src/motion.ts | 36 +- packages/charts-core/src/scene.test.ts | 44 + packages/charts-core/src/scene.ts | 88 +- packages/charts-core/src/types.ts | 52 +- packages/charts-core/src/view.ts | 35 +- packages/charts-demo-data/package.json | 2 +- .../raw/observable-plot/README.md | 2 +- .../src/learning-poverty-geography.ts | 4 +- packages/charts-demo-data/src/metadata.js | 54 +- packages/charts-fixtures/package.json | 2 +- packages/charts-fixtures/src/index.test.ts | 4 +- packages/charts-fixtures/src/index.ts | 8 +- packages/fixtures/package.json | 2 +- packages/fixtures/src/data.test.ts | 4 +- packages/fixtures/src/data.ts | 8 +- packages/react-charts/src/Chart.test.tsx | 20 +- pnpm-lock.yaml | 14 +- scripts/catalog-definition-shapes.test.mjs | 47 +- scripts/check-catalog-examples.mjs | 92 +- scripts/clean-catalog-examples.mjs | 581 ++++- scripts/compare-plot-catalog.mjs | 2 +- scripts/demo-data.test.mjs | 8 +- scripts/generate-shadcn-cases.mjs | 31 +- scripts/public-callback-contract.mjs | 9 + scripts/shadcn-example-source.mjs | 858 ------- scripts/sync-demo-data.mjs | 2 +- 638 files changed, 9891 insertions(+), 37509 deletions(-) create mode 100644 .changeset/clean-catalog-motion.md delete mode 100644 benchmarks/conformance/shared/shadcn-catalog-tanstack.tsx delete mode 100644 benchmarks/conformance/shared/shadcn-motion.ts delete mode 100644 scripts/shadcn-example-source.mjs diff --git a/.changeset/clean-catalog-motion.md b/.changeset/clean-catalog-motion.md new file mode 100644 index 00000000..259b613b --- /dev/null +++ b/.changeset/clean-catalog-motion.md @@ -0,0 +1,5 @@ +--- +'@tanstack/charts': minor +--- + +Improve definition-driven inference for optional motion renderers, raw chart specs with separate behaviors, responsive chart factories, and decorative marks. diff --git a/API-FRICTION.md b/API-FRICTION.md index 030dcd3f..e51a837c 100644 --- a/API-FRICTION.md +++ b/API-FRICTION.md @@ -5,7 +5,7 @@ observed difficulty from examples, production migrations, tests, and agent evaluations so later API, documentation, and TanStack Intent skill work is based on evidence. -Last updated: 2026-08-12 +Last updated: 2026-08-14 ## Triage rule @@ -323,6 +323,10 @@ Each entry records: | F-284 | Stagger timing required repeated callback arithmetic | API | resolved | | F-285 | Absolute catalog links lost their docs navigation tab | Documentation | resolved | | F-286 | Browser imports treated raw JSON as a source module | Tooling | resolved | +| F-287 | Motion renderers required definition type extraction | API | resolved | +| F-288 | Generated examples exposed shared implementation scaffolding | Tooling/API | resolved | +| F-289 | Catalog workbenches exposed runtime bootstrap files | Tooling | resolved | +| F-290 | Public examples imported a private workspace package | Tooling | resolved | ## Findings @@ -839,7 +843,7 @@ Each entry records: - Status: resolved - Severity: high -- Owner: Tooling +- Owner: Tooling/API - Observed in: cross-library bundle and browser comparison matrix; executable catalog production loading - Friction: re-exporting one benchmark mount from a module containing four @@ -904,7 +908,7 @@ Each entry records: - Status: resolved - Severity: medium -- Owner: Tooling +- Owner: Tooling/API - Observed in: tiered cross-library benchmark validation - Friction: `benchmark:check` and `benchmark:update-baseline` wrote their size-only result to the canonical comparison paths. Running normal @@ -8281,3 +8285,91 @@ Each entry records: - Verification: the catalog contract validates all example imports, and the revision-pinned esm.sh URL for the fixture returns a JavaScript module that renders the production sandbox. + +### F-287 — Motion renderers required definition type extraction + +- Status: resolved +- Severity: medium +- Owner: API +- Observed in: making every catalog example show its authored chart before its + React shell +- Friction: `motion()` fixed its datum and axis generics when the renderer was + created, before `RendererChart` received the definition that already knew + those types. Seventy generated examples therefore extracted three conditional + types from the definition only to pass them back to `motion<...>()`. +- Decision: let the optional motion factory return a definition-agnostic + renderer whose generic methods acquire chart types from the host. Preserve + the explicit generic overload for low-level callers. +- Verification: the React type contract passes `motion()` directly beside a + typed definition, all 188 catalog entries typecheck, and no public example + contains a `motion<...>()` instantiation. + +### F-288 — Generated examples exposed shared implementation scaffolding + +- Status: resolved +- Severity: high +- Owner: Tooling +- Observed in: auditing the source shown for every catalog example +- Friction: generated ShadCN entries copied a complete shared stylesheet, + repeated definition type aliases and null component branches, and wrapped + the actual definition in another `defineChart()` call. Eighty-five older + catalog entries also exposed a generated `definition()` → + `createExampleChart()` chain. Seventy-nine public factories retained a + generic `ExampleOptions` bag containing dimensions, preview flags, and other + fields the authored definition never read. Merging tooltip behavior into the chart object + during cleanup made callback datum inference fall back to `unknown`. + Decorative guides also polluted the inferred interactive datum union even + though they cannot own focus or tooltip points. The newly exercised + `defineChart(responsiveFactory, behaviors)` path also exposed a runtime bug: + the constructor spread the factory like an object and silently dropped it. +- Decision: make each case-local `example.tsx` and stylesheet authoritative, + delete the 2,152-line shared ShadCN implementation and its source-extraction + script, and limit generation to metadata and conformance adapters. Collapse + every delegating definition factory into the public example factory, and + keep `defineChart(chart, behaviors)` as one call with two inference phases. + Raw static and responsive overloads infer the chart before behaviors, while + `decorative()` contributes scale types but no interactive datum type. + Preserve a responsive factory as the definition's `chart` callback when + separate behaviors are supplied. + Omit unused component branches, empty spreads, unused option fields, and + unused CSS. Name the remaining definition-driving input `ChartOptions`. Keep + conformance adapters and Recharts references outside the public import + closure; interaction tests import the real examples directly. +- Verification: generation produces 70 entries whose public factory contains + the authored definition, the catalog contract rejects nested or locally + delegated definitions and validates 188 self-contained entries with a + largest TypeScript closure of four files. The cleanup is idempotent after a + fresh 70-case ShadCN metadata generation. A catalog-wide cleanup reduces all + 79 legacy option bags to the properties their definitions actually read and + rejects the old `ExampleOptions` surface. The complete workspace typecheck, 1,877 + unit tests, packed-package checks, 188 generated preview checks, and 70/70 + ShadCN visual comparisons pass. + +### F-289 — Catalog workbenches exposed runtime bootstrap files + +- Status: resolved +- Severity: medium +- Owner: Tooling +- Observed in: opening Charts examples on tanstack.com +- Friction: `/__catalog.tsx` and `/index.html` are generated execution plumbing, + but the workbench displayed both beside authored source. They were also + retained as visible files after sharing an example. +- Decision: mark generated bootstrap paths as hidden example metadata. Keep + them in the executable workspace while filtering them from initial-file + selection, tabs, the file explorer, and shared-project views. +- Verification: tanstack.com catalog and shared-project contract tests preserve + the hidden paths while confirming both bootstrap files remain runnable. + +### F-290 — Public examples imported a private workspace package + +- Status: resolved +- Severity: medium +- Owner: Tooling +- Observed in: opening all 188 catalog examples in the public workbench +- Friction: 163 entries displayed `@charts-poc/demo-data`, exposing an internal + package name and requiring the host to understand a private convention. +- Decision: expose revision-pinned fixture subpaths through the stable + `@tanstack/charts-data` catalog alias and reject private package imports from + every public source closure. +- Verification: the catalog contract resolves every fixture subpath as a + browser module and reports no `@charts-poc/` import in any public example. diff --git a/benchmarks/conformance/cases/01-line-gaps/example.tsx b/benchmarks/conformance/cases/01-line-gaps/example.tsx index 6aaa90f7..7b4cb6a2 100644 --- a/benchmarks/conformance/cases/01-line-gaps/example.tsx +++ b/benchmarks/conformance/cases/01-line-gaps/example.tsx @@ -1,46 +1,37 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { defineChart, lineY } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = aapl.slice(Math.abs(input.revision) % 2) - return defineChart({ - marks: [ - lineY(rows, { - x: 'Date', - y: (row) => (row.Date.getUTCMonth() < 3 ? null : row.Close), - stroke: '#2563eb', - strokeWidth: 2.25, - }), - ], - x: { scale: scaleUtc, axis: { label: 'Week' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Close (USD)' } }, - }) + return defineChart( + { + marks: [ + lineY(rows, { + x: 'Date', + y: (row) => (row.Date.getUTCMonth() < 3 ? null : row.Close), + stroke: '#2563eb', + strokeWidth: 2.25, + }), + ], + x: { scale: scaleUtc, axis: { label: 'Week' } }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Close (USD)' } }, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Apple closing price with first-quarter gaps' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/01-line-gaps/plot.ts b/benchmarks/conformance/cases/01-line-gaps/plot.ts index 9cd553c9..e9fd5bc0 100644 --- a/benchmarks/conformance/cases/01-line-gaps/plot.ts +++ b/benchmarks/conformance/cases/01-line-gaps/plot.ts @@ -1,4 +1,4 @@ -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import * as Plot from '@observablehq/plot' import type { ConformanceInput, ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/02-multi-line-end-labels/example.tsx b/benchmarks/conformance/cases/02-multi-line-end-labels/example.tsx index ebe6ed51..c42891ec 100644 --- a/benchmarks/conformance/cases/02-multi-line-end-labels/example.tsx +++ b/benchmarks/conformance/cases/02-multi-line-end-labels/example.tsx @@ -3,63 +3,61 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, lineY, select, text } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { selectMultiLineData } from './selection' import type { MultiLineDatum } from './selection' const colors = ['#2563eb', '#ea580c', '#059669'] -export const multiLineEndLabelsDefinition = ( - rows: readonly MultiLineDatum[], - preview = false, -) => { +export const createExampleChart = (input: ChartOptions) => { + const rows: readonly MultiLineDatum[] = selectMultiLineData( + industries, + input.revision, + ) + const preview = input.preview === true const endpoints = select(rows, { by: 'industry', value: (datum) => datum.date.getTime(), select: 'max', }) - return defineChart({ - marks: [ - lineY(rows, { - id: 'industry-lines', - x: 'date', - y: 'unemployed', - color: 'industry', - strokeWidth: 2.25, - }), - text(endpoints, { - id: 'industry-end-labels', - x: 'date', - y: 'unemployed', - text: 'industry', - color: 'industry', - anchor: preview ? 'end' : 'start', - dx: preview ? -5 : 5, - fontWeight: 600, - }), - ], - x: { scale: scaleUtc, axis: { label: 'Week' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Unemployed (thousands)' }, - }, - color: { - range: colors, + return defineChart( + { + marks: [ + lineY(rows, { + id: 'industry-lines', + x: 'date', + y: 'unemployed', + color: 'industry', + strokeWidth: 2.25, + }), + text(endpoints, { + id: 'industry-end-labels', + x: 'date', + y: 'unemployed', + text: 'industry', + color: 'industry', + anchor: preview ? 'end' : 'start', + dx: preview ? -5 : 5, + fontWeight: 600, + }), + ], + x: { scale: scaleUtc, axis: { label: 'Week' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Unemployed (thousands)' }, + }, + color: { + range: colors, + }, + margin: { right: 112 }, }, - margin: { right: 112 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export const definition = (input: ExampleOptions) => - multiLineEndLabelsDefinition( - selectMultiLineData(industries, input.revision), - input.preview === true, - ) -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } @@ -67,15 +65,7 @@ export interface ExampleOptions { export const exampleAriaLabel = 'Unemployment by industry with direct end labels' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/02-multi-line-end-labels/plot.ts b/benchmarks/conformance/cases/02-multi-line-end-labels/plot.ts index 21af7790..23b39deb 100644 --- a/benchmarks/conformance/cases/02-multi-line-end-labels/plot.ts +++ b/benchmarks/conformance/cases/02-multi-line-end-labels/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import type { ConformanceInput, ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' import { selectMultiLineData } from './selection' diff --git a/benchmarks/conformance/cases/02-multi-line-end-labels/selection.ts b/benchmarks/conformance/cases/02-multi-line-end-labels/selection.ts index 9f7733e3..52e96039 100644 --- a/benchmarks/conformance/cases/02-multi-line-end-labels/selection.ts +++ b/benchmarks/conformance/cases/02-multi-line-end-labels/selection.ts @@ -1,4 +1,4 @@ -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' export const industryNames = ['Manufacturing', 'Construction', 'Finance'] export type IndustryName = (typeof industryNames)[number] diff --git a/benchmarks/conformance/cases/02-multi-line-end-labels/tanstack.test.ts b/benchmarks/conformance/cases/02-multi-line-end-labels/tanstack.test.ts index 9784f1bc..24ab6478 100644 --- a/benchmarks/conformance/cases/02-multi-line-end-labels/tanstack.test.ts +++ b/benchmarks/conformance/cases/02-multi-line-end-labels/tanstack.test.ts @@ -1,18 +1,18 @@ -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { loadTanStackSources } from '../../native-catalog' import { industryNames, selectMultiLineData } from './selection' -import { multiLineEndLabelsDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { MultiLineDatum } from './selection' describe('multi-line end labels', () => { it('selects each newest dated observation when source order changes', () => { const rows = selectMultiLineData(industries, 0) - const reordered = [...rows].reverse() + const input = { width: 720, height: 480, revision: 0 } const scene = createChartRuntime().render( - multiLineEndLabelsDefinition(reordered), - { width: 720, height: 480 }, + createExampleChart(input), + input, ) const linePoints = scene.points.filter( ({ markId }) => markId === 'industry-lines', diff --git a/benchmarks/conformance/cases/03-temperature-range-band/example.tsx b/benchmarks/conformance/cases/03-temperature-range-band/example.tsx index 153c2ced..1c9ad000 100644 --- a/benchmarks/conformance/cases/03-temperature-range-band/example.tsx +++ b/benchmarks/conformance/cases/03-temperature-range-band/example.tsx @@ -2,61 +2,65 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { areaY, defineChart, lineY } from '@tanstack/charts' -import { sfTemperatures } from '@charts-poc/demo-data/sf-temperatures' +import { sfTemperatures } from '@tanstack/charts-data/sf-temperatures' import { scaleLinear, scaleUtc } from 'd3-scale' -export const definition = () => { +export const createExampleChart = () => { const rows = sfTemperatures - return defineChart({ - marks: [ - areaY(rows, { - x: 'date', - y1: 'low', - y2: 'high', - fill: '#60a5fa', - fillOpacity: 0.24, - }), - lineY(rows, { - x: 'date', - y: 'low', - stroke: '#2563eb', - strokeWidth: 1.75, - }), - lineY(rows, { - x: 'date', - y: 'high', - stroke: '#dc2626', - strokeWidth: 1.75, - }), - ], - x: { scale: scaleUtc, axis: { label: 'Week' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Temperature (°F)' } }, - }) + return defineChart( + { + marks: [ + areaY(rows, { + x: 'date', + y1: 'low', + y2: 'high', + fill: '#60a5fa', + fillOpacity: 0.24, + }), + lineY(rows, { + x: 'date', + y: 'low', + stroke: '#2563eb', + strokeWidth: 1.75, + }), + lineY(rows, { + x: 'date', + y: 'high', + stroke: '#dc2626', + strokeWidth: 1.75, + }), + ], + x: { scale: scaleUtc, axis: { label: 'Week' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Temperature (°F)' }, + }, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.date.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric', + timeZone: 'UTC', + })} · ${datum.low.toLocaleString('en-US', { + maximumFractionDigits: 1, + })}–${datum.high.toLocaleString('en-US', { + maximumFractionDigits: 1, + })} °F`, + }, + }, + }, + ) } export const exampleAriaLabel = 'San Francisco daily low-to-high temperature range' -export const createExampleChart = () => - defineChart(definition(), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.date.toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric', - timeZone: 'UTC', - })} · ${datum.low.toLocaleString('en-US', { - maximumFractionDigits: 1, - })}–${datum.high.toLocaleString('en-US', { - maximumFractionDigits: 1, - })} °F`, - }, - }, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/03-temperature-range-band/plot.ts b/benchmarks/conformance/cases/03-temperature-range-band/plot.ts index 185d731a..bd3d3b29 100644 --- a/benchmarks/conformance/cases/03-temperature-range-band/plot.ts +++ b/benchmarks/conformance/cases/03-temperature-range-band/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { sfTemperatures } from '@charts-poc/demo-data/sf-temperatures' +import { sfTemperatures } from '@tanstack/charts-data/sf-temperatures' import type { ConformanceInput, ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/04-stacked-time-area/example.tsx b/benchmarks/conformance/cases/04-stacked-time-area/example.tsx index 84801bb8..934dd057 100644 --- a/benchmarks/conformance/cases/04-stacked-time-area/example.tsx +++ b/benchmarks/conformance/cases/04-stacked-time-area/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { areaY, colorLegend, defineChart, ruleY } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' const colors = [ '#4e79a7', @@ -18,59 +18,53 @@ const colors = [ '#bab0ab', ] -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - areaY(industries, { - x: 'date', - y: 'unemployed', - color: 'industry', - fillOpacity: 0.78, - }), - ruleY([0]), - ], - x: { scale: scaleUtc, axis: { label: 'Month' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Unemployed (thousands)' }, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + areaY(industries, { + x: 'date', + y: 'unemployed', + color: 'industry', + fillOpacity: 0.78, + }), + ruleY([0]), + ], + x: { scale: scaleUtc, axis: { label: 'Month' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Unemployed (thousands)' }, + }, + color: { + range: colors, + ...(input.preview === true + ? {} + : { legend: colorLegend({ label: 'Industry' }) }), + }, }, - color: { - range: colors, - ...(input.preview === true - ? {} - : { legend: colorLegend({ label: 'Industry' }) }), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { + month: 'short', + year: 'numeric', + timeZone: 'UTC', + })} · ${datum.unemployed.toLocaleString('en-US')} thousand unemployed`, + }, + }, }, - }) -export interface ExampleOptions { - width: number - height: number - revision: number + ) +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Unemployment by industry as stacked areas' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { - month: 'short', - year: 'numeric', - timeZone: 'UTC', - })} · ${datum.unemployed.toLocaleString('en-US')} thousand unemployed`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/04-stacked-time-area/plot.ts b/benchmarks/conformance/cases/04-stacked-time-area/plot.ts index cbfe2dce..419dad10 100644 --- a/benchmarks/conformance/cases/04-stacked-time-area/plot.ts +++ b/benchmarks/conformance/cases/04-stacked-time-area/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import type { ConformanceInput, ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/100-radial-bars/example.tsx b/benchmarks/conformance/cases/100-radial-bars/example.tsx index 1edfa8bb..e00008c0 100644 --- a/benchmarks/conformance/cases/100-radial-bars/example.tsx +++ b/benchmarks/conformance/cases/100-radial-bars/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { polar, radialBarAngle } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { scaleBand, scaleLinear } from 'd3-scale' import { selectRadialBarData } from './selection' @@ -11,61 +11,52 @@ const innerRadiusRatio = 0.2 const colors = ['#7c3aed', '#0ea5e9', '#14b8a6', '#f59e0b'] const maximumFrequency = alphabet[0]?.frequency ?? 1 -export const radialBarsDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const data = selectRadialBarData(alphabet, input.revision) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.84, - angle: { - scale: scaleLinear().domain([0, maximumFrequency]), - }, - radius: { - scale: () => - scaleBand().paddingInner(0.38).paddingOuter(0.19), - range: [ - ({ radius }) => radius * innerRadiusRatio, - ({ radius }) => radius, + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.84, + angle: { + scale: scaleLinear().domain([0, maximumFrequency]), + }, + radius: { + scale: () => + scaleBand().paddingInner(0.38).paddingOuter(0.19), + range: [ + ({ radius }) => radius * innerRadiusRatio, + ({ radius }) => radius, + ], + }, + marks: [ + radialBarAngle(data, { + id: 'letter-bars', + className: 'ts-chart__radial-bars', + angle: 'frequency', + radius: 'letter', + key: 'letter', + color: 'letter', + cornerRadius: 'full', + }), ], - }, - marks: [ - radialBarAngle(data, { - id: 'letter-bars', - className: 'ts-chart__radial-bars', - angle: 'frequency', - radius: 'letter', - key: 'letter', - color: 'letter', - cornerRadius: 'full', - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + }), + ], + color: { range: colors }, + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Concentric letter frequency bars' -export const createExampleChart = (options: ExampleOptions) => - defineChart(radialBarsDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/100-radial-bars/recharts.ts b/benchmarks/conformance/cases/100-radial-bars/recharts.ts index ee42c362..93a0cbe4 100644 --- a/benchmarks/conformance/cases/100-radial-bars/recharts.ts +++ b/benchmarks/conformance/cases/100-radial-bars/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, PolarAngleAxis, RadialBar, RadialBarChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectRadialBarData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/100-radial-bars/selection.ts b/benchmarks/conformance/cases/100-radial-bars/selection.ts index 33b4be3d..1a3fbe6c 100644 --- a/benchmarks/conformance/cases/100-radial-bars/selection.ts +++ b/benchmarks/conformance/cases/100-radial-bars/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 4 diff --git a/benchmarks/conformance/cases/100-radial-bars/tanstack.test.ts b/benchmarks/conformance/cases/100-radial-bars/tanstack.test.ts index 988d1b71..820e3be0 100644 --- a/benchmarks/conformance/cases/100-radial-bars/tanstack.test.ts +++ b/benchmarks/conformance/cases/100-radial-bars/tanstack.test.ts @@ -1,13 +1,13 @@ import { existsSync, readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { scaleBand } from 'd3-scale' import { arc } from 'd3-shape' import { describe, expect, it } from 'vitest' import { selectRadialBarData } from './selection' -import { radialBarsDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -133,7 +133,7 @@ describe('native concentric radial bars', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(radialBarsDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function radialBandScale( diff --git a/benchmarks/conformance/cases/101-sunburst/example.tsx b/benchmarks/conformance/cases/101-sunburst/example.tsx index 2efb002d..9ce5bcb5 100644 --- a/benchmarks/conformance/cases/101-sunburst/example.tsx +++ b/benchmarks/conformance/cases/101-sunburst/example.tsx @@ -4,69 +4,63 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { sunburst } from '@tanstack/charts/hierarchy/sunburst' import { polar } from '@tanstack/charts/polar' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { selectSunburstData } from './selection' -export const sunburstDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const data = selectSunburstData(flare, input.revision) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.88, - startAngle: Math.PI / 2, - endAngle: Math.PI / 2 - Math.PI * 2, - marks: [ - sunburst(data, { - id: 'sunburst-arcs', - path: 'name', - delimiter: '.', - value: 'size', - innerRadius: ({ radius }) => radius * 0.14, - outerRadius: ({ radius }) => { - const innerRadius = radius * 0.14 - return innerRadius + ((radius - innerRadius) * 2) / 3 + 2 - }, - ringPadding: 2, - color: 'branchId', - stroke: '#ffffff', - strokeWidth: 2, - }), - ], - }), - ], - color: { - range: ['#7c3aed', '#0ea5e9', '#14b8a6'], + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.88, + startAngle: Math.PI / 2, + endAngle: Math.PI / 2 - Math.PI * 2, + marks: [ + sunburst(data, { + id: 'sunburst-arcs', + path: 'name', + delimiter: '.', + value: 'size', + innerRadius: ({ radius }) => radius * 0.14, + outerRadius: ({ radius }) => { + const innerRadius = radius * 0.14 + return innerRadius + ((radius - innerRadius) * 2) / 3 + 2 + }, + ringPadding: 2, + color: 'branchId', + stroke: '#ffffff', + strokeWidth: 2, + }), + ], + }), + ], + color: { + range: ['#7c3aed', '#0ea5e9', '#14b8a6'], + }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${(datum.data?.name ?? datum.id).replaceAll('.', ' › ')} · ${datum.value.toLocaleString('en-US')}`, + }, + }, }, - margin: 0, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Flare analytics sunburst' -export const createExampleChart = (options: ExampleOptions) => - defineChart(sunburstDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${(datum.data?.name ?? datum.id).replaceAll('.', ' › ')} · ${datum.value.toLocaleString('en-US')}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/101-sunburst/recharts.ts b/benchmarks/conformance/cases/101-sunburst/recharts.ts index c81953b7..f921f9da 100644 --- a/benchmarks/conformance/cases/101-sunburst/recharts.ts +++ b/benchmarks/conformance/cases/101-sunburst/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { SunburstChart } from 'recharts' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { selectSunburstData } from './selection' import { sunburstTree } from './transform' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/101-sunburst/selection.ts b/benchmarks/conformance/cases/101-sunburst/selection.ts index 1d31937b..01ff0caf 100644 --- a/benchmarks/conformance/cases/101-sunburst/selection.ts +++ b/benchmarks/conformance/cases/101-sunburst/selection.ts @@ -1,4 +1,4 @@ -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' export function selectSunburstData(rows: readonly FlareRow[], revision = 0) { return revision % 2 === 0 diff --git a/benchmarks/conformance/cases/101-sunburst/tanstack.test.ts b/benchmarks/conformance/cases/101-sunburst/tanstack.test.ts index a18f85aa..175fa5df 100644 --- a/benchmarks/conformance/cases/101-sunburst/tanstack.test.ts +++ b/benchmarks/conformance/cases/101-sunburst/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { selectSunburstData } from './selection' -import { sunburstDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { SunburstNode } from '@tanstack/charts/hierarchy/sunburst' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { ChartPoint, ChartScene, @@ -197,7 +197,7 @@ describe('native responsive sunburst', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(sunburstDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function sunburstPoints( diff --git a/benchmarks/conformance/cases/101-sunburst/transform.ts b/benchmarks/conformance/cases/101-sunburst/transform.ts index b3decd6b..e5b051b2 100644 --- a/benchmarks/conformance/cases/101-sunburst/transform.ts +++ b/benchmarks/conformance/cases/101-sunburst/transform.ts @@ -1,5 +1,5 @@ import { stratify } from 'd3-hierarchy' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { HierarchyNode } from 'd3-hierarchy' export interface SunburstTreeNode { diff --git a/benchmarks/conformance/cases/102-world-choropleth/example.tsx b/benchmarks/conformance/cases/102-world-choropleth/example.tsx index 43217da4..1ea3e9cb 100644 --- a/benchmarks/conformance/cases/102-world-choropleth/example.tsx +++ b/benchmarks/conformance/cases/102-world-choropleth/example.tsx @@ -9,11 +9,11 @@ import { previewWorldLand, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { learningPovertyCountries, previewLearningPovertyCountries, -} from '@charts-poc/demo-data/learning-poverty-geography' +} from '@tanstack/charts-data/learning-poverty-geography' const colorRanges = [ ['#eff6ff', '#bfdbfe', '#60a5fa', '#2563eb', '#1e3a8a'], @@ -29,67 +29,63 @@ const previewProjection = { fit: 'sphere' as const, } -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape([input.preview ? previewWorldLand : worldLand], { - projection: input.preview ? previewProjection : projection, - fill: '#e2e8f0', - stroke: '#ffffff', - strokeWidth: 0.5, - }), - geoShape( - input.preview - ? previewLearningPovertyCountries - : learningPovertyCountries, - { +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape([input.preview ? previewWorldLand : worldLand], { projection: input.preview ? previewProjection : projection, - color: (country) => country.properties['Learning Poverty'], + fill: '#e2e8f0', stroke: '#ffffff', strokeWidth: 0.5, + }), + geoShape( + input.preview + ? previewLearningPovertyCountries + : learningPovertyCountries, + { + projection: input.preview ? previewProjection : projection, + color: (country) => country.properties['Learning Poverty'], + stroke: '#ffffff', + strokeWidth: 0.5, + }, + ), + geoShape([worldSphere], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.35, + strokeWidth: 0.75, + }), + ], + color: { + scale: scaleThreshold, + domain: thresholds, + range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, + margin: 10, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'properties' in datum && 'Learning Poverty' in datum.properties + ? `${datum.properties['Country Name']} · ${datum.properties['Learning Poverty']}% learning poverty` + : 'World land', }, - ), - geoShape([worldSphere], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.35, - strokeWidth: 0.75, - }), - ], - color: { - scale: scaleThreshold, - domain: thresholds, - range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, }, - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number + ) +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'World learning-poverty choropleth' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'properties' in datum && 'Learning Poverty' in datum.properties - ? `${datum.properties['Country Name']} · ${datum.properties['Learning Poverty']}% learning poverty` - : 'World land', - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/102-world-choropleth/plot.ts b/benchmarks/conformance/cases/102-world-choropleth/plot.ts index f33d334f..7318002d 100644 --- a/benchmarks/conformance/cases/102-world-choropleth/plot.ts +++ b/benchmarks/conformance/cases/102-world-choropleth/plot.ts @@ -1,8 +1,8 @@ import * as Plot from '@observablehq/plot' -import { worldLand, worldSphere } from '@charts-poc/demo-data/country-atlas' -import { learningPovertyCountries } from '@charts-poc/demo-data/learning-poverty-geography' +import { worldLand, worldSphere } from '@tanstack/charts-data/country-atlas' +import { learningPovertyCountries } from '@tanstack/charts-data/learning-poverty-geography' import { mountObservablePlot } from '../../shared/mount' -import type { LearningPovertyCountry } from '@charts-poc/demo-data/learning-poverty-geography' +import type { LearningPovertyCountry } from '@tanstack/charts-data/learning-poverty-geography' import type { ConformanceMount } from '../../types' const colorRanges = [ diff --git a/benchmarks/conformance/cases/103-bubble-map/example.tsx b/benchmarks/conformance/cases/103-bubble-map/example.tsx index 7ca132f3..734e45e5 100644 --- a/benchmarks/conformance/cases/103-bubble-map/example.tsx +++ b/benchmarks/conformance/cases/103-bubble-map/example.tsx @@ -9,8 +9,8 @@ import { previewWorldLand, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' -import { learningPovertyPointsByPopulation } from '@charts-poc/demo-data/learning-poverty-geography' +} from '@tanstack/charts-data/country-atlas' +import { learningPovertyPointsByPopulation } from '@tanstack/charts-data/learning-poverty-geography' const fills = ['#2563eb', '#0891b2'] const projection = { @@ -22,62 +22,58 @@ const previewProjection = { fit: 'sphere' as const, } -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape([input.preview ? previewWorldLand : worldLand], { - projection: input.preview ? previewProjection : projection, - fill: '#e2e8f0', - stroke: '#ffffff', - strokeWidth: 0.5, - }), - geoShape(learningPovertyPointsByPopulation, { - projection: input.preview ? previewProjection : projection, - r: (country) => country.properties.population, - rScale: { - scale: () => scaleSqrt().range([2, 18]), +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape([input.preview ? previewWorldLand : worldLand], { + projection: input.preview ? previewProjection : projection, + fill: '#e2e8f0', + stroke: '#ffffff', + strokeWidth: 0.5, + }), + geoShape(learningPovertyPointsByPopulation, { + projection: input.preview ? previewProjection : projection, + r: (country) => country.properties.population, + rScale: { + scale: () => scaleSqrt().range([2, 18]), + }, + fill: fills[input.revision % 2] ?? fills[0], + fillOpacity: 0.72, + stroke: '#ffffff', + strokeWidth: 0.75, + }), + geoShape([worldSphere], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.35, + strokeWidth: 0.75, + }), + ], + margin: 10, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'properties' in datum && 'population' in datum.properties + ? `${datum.properties['Country Name']} · ${datum.properties.population.toLocaleString()} people` + : 'World land', }, - fill: fills[input.revision % 2] ?? fills[0], - fillOpacity: 0.72, - stroke: '#ffffff', - strokeWidth: 0.75, - }), - geoShape([worldSphere], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.35, - strokeWidth: 0.75, - }), - ], - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number + }, + }, + ) +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'World population bubble map' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'properties' in datum && 'population' in datum.properties - ? `${datum.properties['Country Name']} · ${datum.properties.population.toLocaleString()} people` - : 'World land', - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/103-bubble-map/plot.ts b/benchmarks/conformance/cases/103-bubble-map/plot.ts index 33b6f087..cd61276c 100644 --- a/benchmarks/conformance/cases/103-bubble-map/plot.ts +++ b/benchmarks/conformance/cases/103-bubble-map/plot.ts @@ -1,8 +1,8 @@ import * as Plot from '@observablehq/plot' -import { worldLand, worldSphere } from '@charts-poc/demo-data/country-atlas' -import { learningPovertyPointsByPopulation } from '@charts-poc/demo-data/learning-poverty-geography' +import { worldLand, worldSphere } from '@tanstack/charts-data/country-atlas' +import { learningPovertyPointsByPopulation } from '@tanstack/charts-data/learning-poverty-geography' import { mountObservablePlot } from '../../shared/mount' -import type { LearningPovertyPoint } from '@charts-poc/demo-data/learning-poverty-geography' +import type { LearningPovertyPoint } from '@tanstack/charts-data/learning-poverty-geography' import type { ConformanceMount } from '../../types' const fills = ['#2563eb', '#0891b2'] diff --git a/benchmarks/conformance/cases/104-orthographic-globe/example.tsx b/benchmarks/conformance/cases/104-orthographic-globe/example.tsx index 415ac280..b032bba8 100644 --- a/benchmarks/conformance/cases/104-orthographic-globe/example.tsx +++ b/benchmarks/conformance/cases/104-orthographic-globe/example.tsx @@ -10,67 +10,60 @@ import { previewWorldLand, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape([worldSphere], { - projection: { - type: () => geoOrthographic().rotate([0, -30, 20]), - fit: 'sphere', - }, - fill: '#dbeafe', - stroke: '#64748b', - strokeWidth: 1.25, - }), - geoShape([input.preview ? previewWorldGraticule : worldGraticule], { - projection: { - type: () => - geoOrthographic() - .rotate([0, -30, 20]) - .precision(input.preview ? 2 : Math.SQRT1_2), - fit: 'sphere', - }, - fill: 'none', - stroke: '#94a3b8', - strokeOpacity: 0.5, - strokeWidth: 0.75, - }), - geoShape([input.preview ? previewWorldLand : worldLand], { - projection: { - type: () => - geoOrthographic() - .rotate([0, -30, 20]) - .precision(input.preview ? 2 : Math.SQRT1_2), - fit: 'sphere', - }, - fill: input.revision % 2 === 0 ? '#22c55e' : '#0d9488', - fillOpacity: 0.82, - stroke: '#f8fafc', - strokeWidth: 0.75, - }), - ], - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape([worldSphere], { + projection: { + type: () => geoOrthographic().rotate([0, -30, 20]), + fit: 'sphere', + }, + fill: '#dbeafe', + stroke: '#64748b', + strokeWidth: 1.25, + }), + geoShape([input.preview ? previewWorldGraticule : worldGraticule], { + projection: { + type: () => + geoOrthographic() + .rotate([0, -30, 20]) + .precision(input.preview ? 2 : Math.SQRT1_2), + fit: 'sphere', + }, + fill: 'none', + stroke: '#94a3b8', + strokeOpacity: 0.5, + strokeWidth: 0.75, + }), + geoShape([input.preview ? previewWorldLand : worldLand], { + projection: { + type: () => + geoOrthographic() + .rotate([0, -30, 20]) + .precision(input.preview ? 2 : Math.SQRT1_2), + fit: 'sphere', + }, + fill: input.revision % 2 === 0 ? '#22c55e' : '#0d9488', + fillOpacity: 0.82, + stroke: '#f8fafc', + strokeWidth: 0.75, + }), + ], + margin: 10, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Orthographic globe with graticule' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/104-orthographic-globe/plot.ts b/benchmarks/conformance/cases/104-orthographic-globe/plot.ts index 228d9c66..42423544 100644 --- a/benchmarks/conformance/cases/104-orthographic-globe/plot.ts +++ b/benchmarks/conformance/cases/104-orthographic-globe/plot.ts @@ -3,7 +3,7 @@ import { worldGraticule, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/105-route-map/example.tsx b/benchmarks/conformance/cases/105-route-map/example.tsx index dc314bc6..4222b673 100644 --- a/benchmarks/conformance/cases/105-route-map/example.tsx +++ b/benchmarks/conformance/cases/105-route-map/example.tsx @@ -10,7 +10,7 @@ import { previewWorldLand, worldGraticule, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { beagleRoute } from './transform' const routeColors = ['#dc2626', '#2563eb'] @@ -23,57 +23,50 @@ const previewProjection = { fit: 'sphere' as const, } -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape([input.preview ? previewWorldLand : detailedWorldLand], { - projection: input.preview ? previewProjection : projection, - fill: '#e2e8f0', - stroke: '#ffffff', - strokeWidth: 0.5, - }), - geoShape([input.preview ? previewWorldGraticule : worldGraticule], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.2, - strokeWidth: 0.5, - }), - geoShape([beagleRoute], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: routeColors[input.revision % 2] ?? routeColors[0], - strokeWidth: 2, - strokeOpacity: 0.9, - }), - geoShape([worldSphere], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.4, - strokeWidth: 0.75, - }), - ], - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape([input.preview ? previewWorldLand : detailedWorldLand], { + projection: input.preview ? previewProjection : projection, + fill: '#e2e8f0', + stroke: '#ffffff', + strokeWidth: 0.5, + }), + geoShape([input.preview ? previewWorldGraticule : worldGraticule], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.2, + strokeWidth: 0.5, + }), + geoShape([beagleRoute], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: routeColors[input.revision % 2] ?? routeColors[0], + strokeWidth: 2, + strokeOpacity: 0.9, + }), + geoShape([worldSphere], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.4, + strokeWidth: 0.75, + }), + ], + margin: 10, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'HMS Beagle voyage' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/105-route-map/plot.ts b/benchmarks/conformance/cases/105-route-map/plot.ts index b3781c1d..bb1e5b9a 100644 --- a/benchmarks/conformance/cases/105-route-map/plot.ts +++ b/benchmarks/conformance/cases/105-route-map/plot.ts @@ -3,7 +3,7 @@ import { detailedWorldLand, worldGraticule, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { beagleRoute } from './transform' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/105-route-map/transform.ts b/benchmarks/conformance/cases/105-route-map/transform.ts index efe8dcd2..11b6451e 100644 --- a/benchmarks/conformance/cases/105-route-map/transform.ts +++ b/benchmarks/conformance/cases/105-route-map/transform.ts @@ -1,4 +1,4 @@ -import { beagle } from '@charts-poc/demo-data/beagle' +import { beagle } from '@tanstack/charts-data/beagle' import type { ExtendedFeature, GeoGeometryObjects } from 'd3-geo' type RouteLineString = Extract diff --git a/benchmarks/conformance/cases/106-polar-line/echarts.ts b/benchmarks/conformance/cases/106-polar-line/echarts.ts index 709a4572..ff0eb2e8 100644 --- a/benchmarks/conformance/cases/106-polar-line/echarts.ts +++ b/benchmarks/conformance/cases/106-polar-line/echarts.ts @@ -4,7 +4,7 @@ import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' import { echartsMount } from '../../shared/echarts-mount' import { dayOfYearAngle, seattleWeatherYear } from './transform' -import type { WeatherRow } from '@charts-poc/demo-data/weather' +import type { WeatherRow } from '@tanstack/charts-data/weather' import type { EChartsCoreOption, EChartsType } from 'echarts/core' import type { ConformanceGeometryQuery, diff --git a/benchmarks/conformance/cases/106-polar-line/example.tsx b/benchmarks/conformance/cases/106-polar-line/example.tsx index 926e6806..87026ee8 100644 --- a/benchmarks/conformance/cases/106-polar-line/example.tsx +++ b/benchmarks/conformance/cases/106-polar-line/example.tsx @@ -18,68 +18,62 @@ const radiusGridValues = [0, 10, 20, 30, 40] as const const lineColor = '#0f766e' const gridColor = '#94a3b8' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = seattleWeatherYear(input.revision) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.72, - angle: { scale: scaleLinear().domain(angleDomain) }, - radius: { scale: scaleLinear().domain(radiusDomain) }, - guides: [ - radialGrid({ - values: radiusGridValues, - labels: false, - stroke: gridColor, - strokeOpacity: 0.35, - }), - angleGrid({ - values: angleGridValues, - labels: false, - stroke: gridColor, - strokeOpacity: 0.35, - }), - ], - marks: [ - radialLine(rows, { - angle: dayOfYearAngle, - radius: 'temp_max', - stroke: lineColor, - strokeWidth: 2.5, - }), - ], - }), - ], - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.72, + angle: { scale: scaleLinear().domain(angleDomain) }, + radius: { scale: scaleLinear().domain(radiusDomain) }, + guides: [ + radialGrid({ + values: radiusGridValues, + labels: false, + stroke: gridColor, + strokeOpacity: 0.35, + }), + angleGrid({ + values: angleGridValues, + labels: false, + stroke: gridColor, + strokeOpacity: 0.35, + }), + ], + marks: [ + radialLine(rows, { + angle: dayOfYearAngle, + radius: 'temp_max', + stroke: lineColor, + strokeWidth: 2.5, + }), + ], + }), + ], + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.date.toISOString().slice(0, 10)} · ${datum.temp_max}°C high`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Seattle daily high-temperature polar line' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.date.toISOString().slice(0, 10)} · ${datum.temp_max}°C high`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/106-polar-line/transform.test.ts b/benchmarks/conformance/cases/106-polar-line/transform.test.ts index 2cf7b339..e290b566 100644 --- a/benchmarks/conformance/cases/106-polar-line/transform.test.ts +++ b/benchmarks/conformance/cases/106-polar-line/transform.test.ts @@ -1,4 +1,4 @@ -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { describe, expect, it } from 'vitest' import { dayOfYearAngle, seattleWeatherYear } from './transform' diff --git a/benchmarks/conformance/cases/106-polar-line/transform.ts b/benchmarks/conformance/cases/106-polar-line/transform.ts index 26ec1f42..98c461ec 100644 --- a/benchmarks/conformance/cases/106-polar-line/transform.ts +++ b/benchmarks/conformance/cases/106-polar-line/transform.ts @@ -1,5 +1,5 @@ -import { weather } from '@charts-poc/demo-data/weather' -import type { WeatherRow } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' +import type { WeatherRow } from '@tanstack/charts-data/weather' const selectableYears = [2012, 2013] as const diff --git a/benchmarks/conformance/cases/107-polar-scatter/echarts.ts b/benchmarks/conformance/cases/107-polar-scatter/echarts.ts index 1177e377..0872285e 100644 --- a/benchmarks/conformance/cases/107-polar-scatter/echarts.ts +++ b/benchmarks/conformance/cases/107-polar-scatter/echarts.ts @@ -4,7 +4,7 @@ import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' import { echartsMount } from '../../shared/echarts-mount' import { windDirection, windLatitudeBand, windSpeed } from './transform' -import type { WindRow } from '@charts-poc/demo-data/wind' +import type { WindRow } from '@tanstack/charts-data/wind' import type { EChartsCoreOption, EChartsType } from 'echarts/core' import type { ConformanceGeometryQuery, diff --git a/benchmarks/conformance/cases/107-polar-scatter/example.tsx b/benchmarks/conformance/cases/107-polar-scatter/example.tsx index 323f1c7f..3799b298 100644 --- a/benchmarks/conformance/cases/107-polar-scatter/example.tsx +++ b/benchmarks/conformance/cases/107-polar-scatter/example.tsx @@ -13,70 +13,64 @@ const radiusGridValues = [3, 6, 9, 12] as const const dotColor = '#e11d48' const gridColor = '#94a3b8' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = windLatitudeBand(input.revision) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.72, - angle: { scale: scaleLinear().domain(angleDomain) }, - radius: { scale: scaleLinear().domain(radiusDomain) }, - guides: [ - radialGrid({ - values: radiusGridValues, - labels: false, - stroke: gridColor, - strokeOpacity: 0.35, - }), - angleGrid({ - values: angleGridValues, - labels: false, - stroke: gridColor, - strokeOpacity: 0.35, - }), - ], - marks: [ - radialDot(rows, { - angle: windDirection, - radius: windSpeed, - r: 4.5, - fill: dotColor, - stroke: '#ffffff', - strokeWidth: 1, - }), - ], - }), - ], - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.72, + angle: { scale: scaleLinear().domain(angleDomain) }, + radius: { scale: scaleLinear().domain(radiusDomain) }, + guides: [ + radialGrid({ + values: radiusGridValues, + labels: false, + stroke: gridColor, + strokeOpacity: 0.35, + }), + angleGrid({ + values: angleGridValues, + labels: false, + stroke: gridColor, + strokeOpacity: 0.35, + }), + ], + marks: [ + radialDot(rows, { + angle: windDirection, + radius: windSpeed, + r: 4.5, + fill: dotColor, + stroke: '#ffffff', + strokeWidth: 1, + }), + ], + }), + ], + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.latitude}°N, ${datum.longitude}°E · ${windSpeed(datum).toFixed(1)} m/s`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Surface wind polar scatter' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.latitude}°N, ${datum.longitude}°E · ${windSpeed(datum).toFixed(1)} m/s`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/107-polar-scatter/transform.test.ts b/benchmarks/conformance/cases/107-polar-scatter/transform.test.ts index e5015008..4012f8f0 100644 --- a/benchmarks/conformance/cases/107-polar-scatter/transform.test.ts +++ b/benchmarks/conformance/cases/107-polar-scatter/transform.test.ts @@ -1,4 +1,4 @@ -import { wind } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' import { describe, expect, it } from 'vitest' import { windDirection, windLatitudeBand, windSpeed } from './transform' diff --git a/benchmarks/conformance/cases/107-polar-scatter/transform.ts b/benchmarks/conformance/cases/107-polar-scatter/transform.ts index 437d9daa..5b80aa2c 100644 --- a/benchmarks/conformance/cases/107-polar-scatter/transform.ts +++ b/benchmarks/conformance/cases/107-polar-scatter/transform.ts @@ -1,5 +1,5 @@ -import { wind } from '@charts-poc/demo-data/wind' -import type { WindRow } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' +import type { WindRow } from '@tanstack/charts-data/wind' const selectableLatitudeBands = [48.125, 55.125] as const diff --git a/benchmarks/conformance/cases/108-country-choropleth/example.tsx b/benchmarks/conformance/cases/108-country-choropleth/example.tsx index c518ff0e..649596b8 100644 --- a/benchmarks/conformance/cases/108-country-choropleth/example.tsx +++ b/benchmarks/conformance/cases/108-country-choropleth/example.tsx @@ -9,11 +9,11 @@ import { previewWorldLand, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { learningPovertyCountries, previewLearningPovertyCountries, -} from '@charts-poc/demo-data/learning-poverty-geography' +} from '@tanstack/charts-data/learning-poverty-geography' const colorRanges = [ ['#ecfeff', '#a5f3fc', '#67e8f9', '#06b6d4', '#0e7490', '#164e63'], @@ -28,67 +28,63 @@ const previewProjection = { fit: 'sphere' as const, } -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape([input.preview ? previewWorldLand : worldLand], { - projection: input.preview ? previewProjection : projection, - fill: '#e2e8f0', - stroke: '#ffffff', - strokeWidth: 0.55, - }), - geoShape( - input.preview - ? previewLearningPovertyCountries - : learningPovertyCountries, - { +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape([input.preview ? previewWorldLand : worldLand], { projection: input.preview ? previewProjection : projection, - color: (country) => country.properties.density, - stroke: 'currentColor', - strokeOpacity: 0.34, + fill: '#e2e8f0', + stroke: '#ffffff', strokeWidth: 0.55, + }), + geoShape( + input.preview + ? previewLearningPovertyCountries + : learningPovertyCountries, + { + projection: input.preview ? previewProjection : projection, + color: (country) => country.properties.density, + stroke: 'currentColor', + strokeOpacity: 0.34, + strokeWidth: 0.55, + }, + ), + geoShape([worldSphere], { + projection: input.preview ? previewProjection : projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.35, + strokeWidth: 0.75, + }), + ], + color: { + scale: scaleQuantize, + range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, + margin: 12, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'properties' in datum && 'density' in datum.properties + ? `${datum.properties['Country Name']} · ${datum.properties.density} people/km²` + : 'World land', }, - ), - geoShape([worldSphere], { - projection: input.preview ? previewProjection : projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.35, - strokeWidth: 0.75, - }), - ], - color: { - scale: scaleQuantize, - range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, }, - margin: 12, - }) -export interface ExampleOptions { - width: number - height: number + ) +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'World population-density choropleth' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'properties' in datum && 'density' in datum.properties - ? `${datum.properties['Country Name']} · ${datum.properties.density} people/km²` - : 'World land', - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/108-country-choropleth/plot.ts b/benchmarks/conformance/cases/108-country-choropleth/plot.ts index 37731f52..afbb9ea8 100644 --- a/benchmarks/conformance/cases/108-country-choropleth/plot.ts +++ b/benchmarks/conformance/cases/108-country-choropleth/plot.ts @@ -1,8 +1,8 @@ import * as Plot from '@observablehq/plot' -import { worldLand, worldSphere } from '@charts-poc/demo-data/country-atlas' -import { learningPovertyCountries } from '@charts-poc/demo-data/learning-poverty-geography' +import { worldLand, worldSphere } from '@tanstack/charts-data/country-atlas' +import { learningPovertyCountries } from '@tanstack/charts-data/learning-poverty-geography' import { mountObservablePlot } from '../../shared/mount' -import type { LearningPovertyCountry } from '@charts-poc/demo-data/learning-poverty-geography' +import type { LearningPovertyCountry } from '@tanstack/charts-data/learning-poverty-geography' import type { ConformanceMount } from '../../types' const colorRanges = [ diff --git a/benchmarks/conformance/cases/109-us-state-choropleth/example.tsx b/benchmarks/conformance/cases/109-us-state-choropleth/example.tsx index b155ed61..8bd16c0e 100644 --- a/benchmarks/conformance/cases/109-us-state-choropleth/example.tsx +++ b/benchmarks/conformance/cases/109-us-state-choropleth/example.tsx @@ -35,51 +35,45 @@ const colorRanges = [ ], ] -export const usStateChoroplethDefinition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape(projectedUnemploymentCounties, { - projection: { - type: geoAlbersUsa, - fit: unemploymentCountyCollection, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape(projectedUnemploymentCounties, { + projection: { + type: geoAlbersUsa, + fit: unemploymentCountyCollection, + }, + color: (county) => county.properties.rate, + stroke: '#f8fafc', + strokeWidth: 0.35, + }), + ], + color: { + scale: scaleQuantile, + range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, + margin: 10, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.properties.county}, ${datum.properties.state} · ${datum.properties.rate}% unemployment`, }, - color: (county) => county.properties.rate, - stroke: '#f8fafc', - strokeWidth: 0.35, - }), - ], - color: { - scale: scaleQuantile, - range: colorRanges[input.revision % 2] ?? colorRanges[0], + }, }, - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number + ) +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'United States county unemployment choropleth' -export const createExampleChart = (options: ExampleOptions) => - defineChart(usStateChoroplethDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.properties.county}, ${datum.properties.state} · ${datum.properties.rate}% unemployment`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/109-us-state-choropleth/tanstack.test.ts b/benchmarks/conformance/cases/109-us-state-choropleth/tanstack.test.ts index 2213da48..879507ba 100644 --- a/benchmarks/conformance/cases/109-us-state-choropleth/tanstack.test.ts +++ b/benchmarks/conformance/cases/109-us-state-choropleth/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import { createChartRuntime } from '@tanstack/charts' import { geoAlbersUsa, geoPath } from 'd3-geo' import { describe, expect, expectTypeOf, it } from 'vitest' -import { usStateChoroplethDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import { projectedUnemploymentCounties, unemploymentCountyCollection, @@ -26,7 +26,7 @@ const input = { describe('definition-owned Albers USA choropleth', () => { it('fits every county through the public explicit-geometry descriptor', () => { - const definition = usStateChoroplethDefinition(input) + const definition = createExampleChart(input) const scene = createChartRuntime< UnemploymentCounty, number, diff --git a/benchmarks/conformance/cases/109-us-state-choropleth/transform.ts b/benchmarks/conformance/cases/109-us-state-choropleth/transform.ts index b1a81e84..5b849d6c 100644 --- a/benchmarks/conformance/cases/109-us-state-choropleth/transform.ts +++ b/benchmarks/conformance/cases/109-us-state-choropleth/transform.ts @@ -1,9 +1,9 @@ -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import countiesAtlasJson from 'us-atlas/counties-10m.json' import { geoAlbersUsa, geoPath } from 'd3-geo' import { feature } from 'topojson-client' -import { simplifyPolygonGeometry } from '@charts-poc/demo-data/simplify-geo' -import type { UsCountyUnemploymentRow } from '@charts-poc/demo-data/us-county-unemployment' +import { simplifyPolygonGeometry } from '@tanstack/charts-data/simplify-geo' +import type { UsCountyUnemploymentRow } from '@tanstack/charts-data/us-county-unemployment' import type { ExtendedFeature, ExtendedFeatureCollection, diff --git a/benchmarks/conformance/cases/110-projection-gallery/example.tsx b/benchmarks/conformance/cases/110-projection-gallery/example.tsx index b68ad3f6..61828e43 100644 --- a/benchmarks/conformance/cases/110-projection-gallery/example.tsx +++ b/benchmarks/conformance/cases/110-projection-gallery/example.tsx @@ -7,7 +7,7 @@ import { previewWorldLand, worldLand, worldSphere, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { projectionGalleryData } from './projection' const projectionColors = [ @@ -15,76 +15,69 @@ const projectionColors = [ ['#1d4ed8', '#6d28d9', '#0e7490', '#c2410c'], ] -function projectionGalleryChart(input: ExampleOptions, preview: boolean) { +export const createExampleChart = (input: ChartOptions) => { + const preview = false + const projections = projectionGalleryData() const color = { domain: projections.map(({ id }) => id), range: projectionColors[input.revision % 2] ?? projectionColors[0], } - return facetChart(projections, { - id: 'projection-gallery', - by: 'id', - columns: 2, - gap: 0, - label: false, - chart: ([entry]) => { - const projection = { - type: preview ? () => entry.create().precision(2) : entry.create, - fit: 'sphere' as const, - inset: 8, - } + return defineChart( + facetChart(projections, { + id: 'projection-gallery', + by: 'id', + columns: 2, + gap: 0, + label: false, + chart: ([entry]) => { + const projection = { + type: preview ? () => entry.create().precision(2) : entry.create, + fit: 'sphere' as const, + inset: 8, + } - return { - marks: [ - geoShape([worldSphere], { - id: 'sphere', - projection, - fill: 'none', - stroke: 'currentColor', - strokeOpacity: 0.5, - strokeWidth: 0.8, - }), - geoShape([preview ? previewWorldLand : worldLand], { - id: 'land', - projection, - color: () => entry.id, - fillOpacity: 0.78, - stroke: 'currentColor', - strokeOpacity: 0.28, - strokeWidth: 0.45, - }), - ], - color, - guides: false, - margin: 0, - } + return { + marks: [ + geoShape([worldSphere], { + id: 'sphere', + projection, + fill: 'none', + stroke: 'currentColor', + strokeOpacity: 0.5, + strokeWidth: 0.8, + }), + geoShape([preview ? previewWorldLand : worldLand], { + id: 'land', + projection, + color: () => entry.id, + fillOpacity: 0.78, + stroke: 'currentColor', + strokeOpacity: 0.28, + strokeWidth: 0.45, + }), + ], + color, + guides: false, + margin: 0, + } + }, + }), + { + keyboard: true, + tooltip: exampleTooltip, }, - }) + ) } - -export const projectionGalleryDefinition = (input: ExampleOptions) => - projectionGalleryChart(input, false) -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Standard world projection gallery' -export const createExampleChart = (options: ExampleOptions) => - defineChart(projectionGalleryDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/110-projection-gallery/plot.ts b/benchmarks/conformance/cases/110-projection-gallery/plot.ts index 9ee6a5ac..10227275 100644 --- a/benchmarks/conformance/cases/110-projection-gallery/plot.ts +++ b/benchmarks/conformance/cases/110-projection-gallery/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { worldLand, worldSphere } from '@charts-poc/demo-data/country-atlas' +import { worldLand, worldSphere } from '@tanstack/charts-data/country-atlas' import { projectionGalleryData } from './projection' import type { ConformanceInput, ConformanceMount } from '../../types' import type { GeoProjection } from 'd3-geo' diff --git a/benchmarks/conformance/cases/110-projection-gallery/tanstack.test.ts b/benchmarks/conformance/cases/110-projection-gallery/tanstack.test.ts index 015f9b9d..12de9817 100644 --- a/benchmarks/conformance/cases/110-projection-gallery/tanstack.test.ts +++ b/benchmarks/conformance/cases/110-projection-gallery/tanstack.test.ts @@ -3,10 +3,10 @@ import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { geoPath } from 'd3-geo' import { describe, expect, expectTypeOf, it } from 'vitest' -import { worldLand, worldSphere } from '@charts-poc/demo-data/country-atlas' +import { worldLand, worldSphere } from '@tanstack/charts-data/country-atlas' import { projectionGalleryData } from './projection' -import { projectionGalleryDefinition } from './tanstack' -import type { LandFeature } from '@charts-poc/demo-data/country-atlas' +import { createExampleChart } from './tanstack' +import type { LandFeature } from '@tanstack/charts-data/country-atlas' import type { ChartScene, ChartSpecDatum, @@ -94,7 +94,7 @@ describe('declarative projection gallery', () => { it('preserves child geo datum types and identity through the facet', () => { const scene = render(640, 400, 0) - type Datum = ChartSpecDatum> + type Datum = ChartSpecDatum> expectTypeOf().toEqualTypeOf() expect( @@ -136,7 +136,7 @@ describe('declarative projection gallery', () => { function render(width: number, height: number, revision: number) { const input = { width, height, revision } satisfies ConformanceInput - return createChartRuntime().render(projectionGalleryDefinition(input), input) + return createChartRuntime().render(createExampleChart(input), input) } function facetCells(scene: ChartScene): SceneGroup[] { diff --git a/benchmarks/conformance/cases/111-basic-sankey/example.tsx b/benchmarks/conformance/cases/111-basic-sankey/example.tsx index 3cfebe6b..55985438 100644 --- a/benchmarks/conformance/cases/111-basic-sankey/example.tsx +++ b/benchmarks/conformance/cases/111-basic-sankey/example.tsx @@ -20,122 +20,118 @@ export type BasicSankeyLinkRow = SankeyLink< > export type BasicSankeyDatum = BasicSankeyNodeRow | BasicSankeyLinkRow -export const basicSankeyDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const { nodes, links } = basicSankeyData(input.revision) - return defineChart({ - marks: [ - sankeyDiagram({ - id: 'basic-sankey', - nodes, - links, - nodeKey: 'id', - source: 'source', - target: 'target', - value: 'value', - align: 'left', - nodeWidth: - input.preview === true - ? 8 - : ({ width }) => clamp(width * 0.025, 10, 18), - nodePadding: - input.preview === true - ? 8 - : ({ height }) => clamp(height * 0.12, 18, 38), - inset: - input.preview === true - ? 4 - : ({ width, height }) => ({ - left: clamp(width * 0.14, 48, 82), - right: clamp(width * 0.14, 48, 82), - top: clamp(height * 0.1, 18, 32), - bottom: clamp(height * 0.1, 18, 32), + return defineChart( + { + marks: [ + sankeyDiagram({ + id: 'basic-sankey', + nodes, + links, + nodeKey: 'id', + source: 'source', + target: 'target', + value: 'value', + align: 'left', + nodeWidth: + input.preview === true + ? 8 + : ({ width }) => clamp(width * 0.025, 10, 18), + nodePadding: + input.preview === true + ? 8 + : ({ height }) => clamp(height * 0.12, 18, 38), + inset: + input.preview === true + ? 4 + : ({ width, height }) => ({ + left: clamp(width * 0.14, 48, 82), + right: clamp(width * 0.14, 48, 82), + top: clamp(height * 0.1, 18, 32), + bottom: clamp(height * 0.1, 18, 32), + }), + iterations: 16, + marks: ({ chart, nodes: sankeyNodes, links: sankeyLinks }) => { + const labelFontSize = clamp(chart.width * 0.018, 8, 12) + const labelOffset = clamp(chart.width * 0.012, 4, 8) + return [ + link(sankeyLinks, { + id: 'links', + x1: 'x1', + y1: 'y1', + x2: 'x2', + y2: 'y2', + key: 'key', + stroke: 'currentColor', + strokeOpacity: 0.35, + strokeWidth: (flow) => Math.max(1, flow.width), + lineCap: 'butt', + curve: d3Curve(curveBumpX), }), - iterations: 16, - marks: ({ chart, nodes: sankeyNodes, links: sankeyLinks }) => { - const labelFontSize = clamp(chart.width * 0.018, 8, 12) - const labelOffset = clamp(chart.width * 0.012, 4, 8) - return [ - link(sankeyLinks, { - id: 'links', - x1: 'x1', - y1: 'y1', - x2: 'x2', - y2: 'y2', - key: 'key', - stroke: 'currentColor', - strokeOpacity: 0.35, - strokeWidth: (flow) => Math.max(1, flow.width), - lineCap: 'butt', - curve: d3Curve(curveBumpX), - }), - rect(sankeyNodes, { - id: 'nodes', - x1: 'x0', - x2: 'x1', - y1: 'y0', - y2: 'y1', - key: 'key', - fill: 'currentColor', - fillOpacity: 0.72, - inset: 0, - }), - ...(input.preview === true - ? [] - : [ - text(sankeyNodes, { - id: 'labels', - x: (node) => - node.depth === 0 - ? node.x0 - labelOffset - : node.x1 + labelOffset, - y: (node) => node.y, - text: (node) => node.data.label, - key: 'key', - anchor: (node) => (node.depth === 0 ? 'end' : 'start'), - fill: 'currentColor', - fontSize: labelFontSize, - fontWeight: 650, - }), - ]), - ] as const + rect(sankeyNodes, { + id: 'nodes', + x1: 'x0', + x2: 'x1', + y1: 'y0', + y2: 'y1', + key: 'key', + fill: 'currentColor', + fillOpacity: 0.72, + inset: 0, + }), + ...(input.preview === true + ? [] + : [ + text(sankeyNodes, { + id: 'labels', + x: (node) => + node.depth === 0 + ? node.x0 - labelOffset + : node.x1 + labelOffset, + y: (node) => node.y, + text: (node) => node.data.label, + key: 'key', + anchor: (node) => (node.depth === 0 ? 'end' : 'start'), + fill: 'currentColor', + fontSize: labelFontSize, + fontWeight: 650, + }), + ]), + ] as const + }, + }), + ], + guides: false, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + datum.kind === 'node' + ? `${datum.data.label} · ${datum.value}` + : `${datum.sourceNode.data.label} → ${datum.targetNode.data.label} · ${datum.value}`, }, - }), - ], - guides: false, - margin: 0, - }) + }, + }, + ) } function clamp(value: number, minimum: number, maximum: number) { return Math.min(maximum, Math.max(minimum, value)) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Basic Sankey' -export const createExampleChart = (options: ExampleOptions) => - defineChart(basicSankeyDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - datum.kind === 'node' - ? `${datum.data.label} · ${datum.value}` - : `${datum.sourceNode.data.label} → ${datum.targetNode.data.label} · ${datum.value}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/111-basic-sankey/tanstack.test.ts b/benchmarks/conformance/cases/111-basic-sankey/tanstack.test.ts index 8a61b113..2875ede5 100644 --- a/benchmarks/conformance/cases/111-basic-sankey/tanstack.test.ts +++ b/benchmarks/conformance/cases/111-basic-sankey/tanstack.test.ts @@ -3,7 +3,7 @@ import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { basicFlowNodes, basicSankeyData } from './model' -import { basicSankeyDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { BasicSankeyDatum, BasicSankeyLinkRow, @@ -151,7 +151,7 @@ describe('basic Sankey composition', () => { const runtime = createChartRuntime() const renderRevision = (revision: number) => { const input = { ...baseInput, revision } - return runtime.render(basicSankeyDefinition(input), input) + return runtime.render(createExampleChart(input), input) } const first = renderRevision(0) const repeated = renderRevision(0) @@ -207,7 +207,7 @@ describe('basic Sankey composition', () => { ), 'utf8', ) - type Datum = ChartSpecDatum> + type Datum = ChartSpecDatum> expectTypeOf().toEqualTypeOf() expect(source).toContain("from '@tanstack/charts/network/sankey'") @@ -230,7 +230,7 @@ describe('basic Sankey composition', () => { function render(input: ConformanceInput) { return createChartRuntime().render( - basicSankeyDefinition(input), + createExampleChart(input), input, ) } diff --git a/benchmarks/conformance/cases/111-sankey-flow/example.tsx b/benchmarks/conformance/cases/111-sankey-flow/example.tsx index 6710b39b..f2cda781 100644 --- a/benchmarks/conformance/cases/111-sankey-flow/example.tsx +++ b/benchmarks/conformance/cases/111-sankey-flow/example.tsx @@ -46,206 +46,202 @@ interface IncomeSankeyLabelRow extends IncomeSankeyNodeRow { export type IncomeSankeyDatum = IncomeSankeyNodeRow | IncomeSankeyLinkRow | IncomeSankeyTitleRow -export const sankeyDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const sourceData = incomeStatementData(input.revision) - return defineChart({ - marks: [ - sankeyDiagram({ - id: 'income-sankey', - nodes: sourceData.nodes, - links: sourceData.links, - nodeKey: 'id', - source: 'source', - target: 'target', - value: 'value', - align: 'left', - nodeSort: (left, right) => left.data.order - right.data.order, - nodeWidth: - input.preview === true - ? 8 - : ({ width }) => clamp(width * 0.032, 10, 24), - nodePadding: - input.preview === true - ? 3 - : ({ height }) => clamp(height * 0.11, 12, 40), - inset: - input.preview === true - ? 4 - : ({ width, height }) => ({ - left: clamp(width * 0.15, 56, 122), - right: clamp(width * 0.13, 48, 105), - top: clamp(height * 0.14, 38, 70), - bottom: clamp(height * 0.025, 8, 14), + return defineChart( + { + marks: [ + sankeyDiagram({ + id: 'income-sankey', + nodes: sourceData.nodes, + links: sourceData.links, + nodeKey: 'id', + source: 'source', + target: 'target', + value: 'value', + align: 'left', + nodeSort: (left, right) => left.data.order - right.data.order, + nodeWidth: + input.preview === true + ? 8 + : ({ width }) => clamp(width * 0.032, 10, 24), + nodePadding: + input.preview === true + ? 3 + : ({ height }) => clamp(height * 0.11, 12, 40), + inset: + input.preview === true + ? 4 + : ({ width, height }) => ({ + left: clamp(width * 0.15, 56, 122), + right: clamp(width * 0.13, 48, 105), + top: clamp(height * 0.14, 38, 70), + bottom: clamp(height * 0.025, 8, 14), + }), + iterations: 32, + marks: ({ chart, nodes: sankeyNodes, links: sankeyLinks }) => { + const flowMarks = [ + link(sankeyLinks, { + id: 'links', + x1: 'x1', + y1: 'y1', + x2: 'x2', + y2: 'y2', + key: 'key', + stroke: (flow) => linkColors[flow.data.tone], + strokeOpacity: (flow) => + flow.data.tone === 'Neutral' ? 0.58 : 0.64, + strokeWidth: (flow) => Math.max(1, flow.width), + lineCap: 'butt', + curve: d3Curve(curveBumpX), }), - iterations: 32, - marks: ({ chart, nodes: sankeyNodes, links: sankeyLinks }) => { - const flowMarks = [ - link(sankeyLinks, { - id: 'links', - x1: 'x1', - y1: 'y1', - x2: 'x2', - y2: 'y2', - key: 'key', - stroke: (flow) => linkColors[flow.data.tone], - strokeOpacity: (flow) => - flow.data.tone === 'Neutral' ? 0.58 : 0.64, - strokeWidth: (flow) => Math.max(1, flow.width), - lineCap: 'butt', - curve: d3Curve(curveBumpX), - }), - rect(sankeyNodes, { - id: 'nodes', - x1: 'x0', - x2: 'x1', - y1: 'y0', - y2: 'y1', - key: 'key', - color: (node) => node.data.tone, - inset: 0, - }), - ] as const - if (input.preview === true) return flowMarks + rect(sankeyNodes, { + id: 'nodes', + x1: 'x0', + x2: 'x1', + y1: 'y0', + y2: 'y1', + key: 'key', + color: (node) => node.data.tone, + inset: 0, + }), + ] as const + if (input.preview === true) return flowMarks - const labelFontSize = clamp(chart.width * 0.013, 6.5, 10.5) - const labelOffset = clamp(chart.width * 0.008, 3, 6) - const labelRows = sankeyNodes.map((node): IncomeSankeyLabelRow => { - const labelAnchor = - node.data.labelSide === 'right' ? 'start' : 'end' - const labelX = - node.data.labelSide === 'right' - ? node.x1 + labelOffset - : node.x0 - labelOffset - const labelText = - chart.width < 720 && node.data.compactLabel - ? node.data.compactLabel - : node.data.label - const backdrop = labelBackdropBounds({ - anchor: labelAnchor, - centerY: node.y, - fontSize: labelFontSize, - label: labelText, - labelX, - value: node.data.displayValue, + const labelFontSize = clamp(chart.width * 0.013, 6.5, 10.5) + const labelOffset = clamp(chart.width * 0.008, 3, 6) + const labelRows = sankeyNodes.map((node): IncomeSankeyLabelRow => { + const labelAnchor = + node.data.labelSide === 'right' ? 'start' : 'end' + const labelX = + node.data.labelSide === 'right' + ? node.x1 + labelOffset + : node.x0 - labelOffset + const labelText = + chart.width < 720 && node.data.compactLabel + ? node.data.compactLabel + : node.data.label + const backdrop = labelBackdropBounds({ + anchor: labelAnchor, + centerY: node.y, + fontSize: labelFontSize, + label: labelText, + labelX, + value: node.data.displayValue, + }) + return { + ...node, + labelText, + labelX, + labelNameY: node.y - labelFontSize * 0.5, + labelValueY: node.y + labelFontSize * 0.58, + labelAnchor, + backdropX0: backdrop.x, + backdropX1: backdrop.x + backdrop.width, + backdropY0: backdrop.y, + backdropY1: backdrop.y + backdrop.height, + } }) - return { - ...node, - labelText, - labelX, - labelNameY: node.y - labelFontSize * 0.5, - labelValueY: node.y + labelFontSize * 0.58, - labelAnchor, - backdropX0: backdrop.x, - backdropX1: backdrop.x + backdrop.width, - backdropY0: backdrop.y, - backdropY1: backdrop.y + backdrop.height, - } - }) - const backdropRows = labelRows.filter( - (node) => node.data.labelBackdrop, - ) - const titleRows: readonly IncomeSankeyTitleRow[] = [ - { - kind: 'title', - id: 'title', - title: incomeStatementTitle, - x: chart.x + chart.width / 2, - y: chart.y + clamp(chart.height * 0.065, 17, 32), - }, - ] + const backdropRows = labelRows.filter( + (node) => node.data.labelBackdrop, + ) + const titleRows: readonly IncomeSankeyTitleRow[] = [ + { + kind: 'title', + id: 'title', + title: incomeStatementTitle, + x: chart.x + chart.width / 2, + y: chart.y + clamp(chart.height * 0.065, 17, 32), + }, + ] - return [ - ...flowMarks, - rect(backdropRows, { - id: 'label-backdrops', - x1: 'backdropX0', - x2: 'backdropX1', - y1: 'backdropY0', - y2: 'backdropY1', - key: 'key', - fill: 'var(--panel, #ffffff)', - fillOpacity: 0.82, - inset: 0, - radius: 1, - }), - text(labelRows, { - id: 'label-names', - x: 'labelX', - y: 'labelNameY', - text: 'labelText', - key: 'key', - anchor: (node) => node.labelAnchor, - fill: 'currentColor', - fontSize: labelFontSize, - fontWeight: 700, - }), - text(labelRows, { - id: 'label-values', - x: 'labelX', - y: 'labelValueY', - text: (node) => node.data.displayValue, - key: 'key', - anchor: (node) => node.labelAnchor, - fill: 'currentColor', - fontSize: labelFontSize, - fontWeight: 500, - }), - text(titleRows, { - id: 'title', - x: 'x', - y: 'y', - text: 'title', - key: 'id', - fill: '#155477', - fontSize: clamp(chart.width * 0.034, 14, 26), - fontWeight: 750, - }), - ] as const + return [ + ...flowMarks, + rect(backdropRows, { + id: 'label-backdrops', + x1: 'backdropX0', + x2: 'backdropX1', + y1: 'backdropY0', + y2: 'backdropY1', + key: 'key', + fill: 'var(--panel, #ffffff)', + fillOpacity: 0.82, + inset: 0, + radius: 1, + }), + text(labelRows, { + id: 'label-names', + x: 'labelX', + y: 'labelNameY', + text: 'labelText', + key: 'key', + anchor: (node) => node.labelAnchor, + fill: 'currentColor', + fontSize: labelFontSize, + fontWeight: 700, + }), + text(labelRows, { + id: 'label-values', + x: 'labelX', + y: 'labelValueY', + text: (node) => node.data.displayValue, + key: 'key', + anchor: (node) => node.labelAnchor, + fill: 'currentColor', + fontSize: labelFontSize, + fontWeight: 500, + }), + text(titleRows, { + id: 'title', + x: 'x', + y: 'y', + text: 'title', + key: 'id', + fill: '#155477', + fontSize: clamp(chart.width * 0.034, 14, 26), + fontWeight: 750, + }), + ] as const + }, + }), + ], + color: { + domain: toneDomain, + range: toneDomain.map((tone) => toneColors[tone]), + }, + guides: false, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => { + if (datum.kind === 'title') return datum.title + if (datum.kind === 'node') { + return `${datum.data.label} · ${datum.data.displayValue}` + } + return `${datum.sourceNode.data.label} → ${datum.targetNode.data.label} · ${datum.value}` + }, }, - }), - ], - color: { - domain: toneDomain, - range: toneDomain.map((tone) => toneColors[tone]), + }, }, - guides: false, - margin: 0, - }) + ) } function clamp(value: number, minimum: number, maximum: number) { return Math.min(maximum, Math.max(minimum, value)) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = incomeStatementTitle -export const createExampleChart = (options: ExampleOptions) => - defineChart(sankeyDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => { - if (datum.kind === 'title') return datum.title - if (datum.kind === 'node') { - return `${datum.data.label} · ${datum.data.displayValue}` - } - return `${datum.sourceNode.data.label} → ${datum.targetNode.data.label} · ${datum.value}` - }, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/111-sankey-flow/tanstack.test.ts b/benchmarks/conformance/cases/111-sankey-flow/tanstack.test.ts index 4ff704a2..385a5764 100644 --- a/benchmarks/conformance/cases/111-sankey-flow/tanstack.test.ts +++ b/benchmarks/conformance/cases/111-sankey-flow/tanstack.test.ts @@ -8,7 +8,7 @@ import { linkColors, toneColors, } from './model' -import { sankeyDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { IncomeSankeyDatum, IncomeSankeyLinkRow, @@ -225,7 +225,7 @@ describe('Apple income statement Sankey composition', () => { const runtime = createChartRuntime() const renderRevision = (revision: number) => { const input = { ...baseInput, revision } - return runtime.render(sankeyDefinition(input), input) + return runtime.render(createExampleChart(input), input) } const first = renderRevision(0) const repeated = renderRevision(0) @@ -281,7 +281,7 @@ describe('Apple income statement Sankey composition', () => { ), 'utf8', ) - type Datum = ChartSpecDatum> + type Datum = ChartSpecDatum> expectTypeOf().toMatchTypeOf() expect(source).toContain("from '@tanstack/charts/network/sankey'") @@ -304,7 +304,7 @@ describe('Apple income statement Sankey composition', () => { function render(input: ConformanceInput) { return createChartRuntime().render( - sankeyDefinition(input), + createExampleChart(input), input, ) } diff --git a/benchmarks/conformance/cases/112-motion-entrance/example.tsx b/benchmarks/conformance/cases/112-motion-entrance/example.tsx index cbd66571..018ebf20 100644 --- a/benchmarks/conformance/cases/112-motion-entrance/example.tsx +++ b/benchmarks/conformance/cases/112-motion-entrance/example.tsx @@ -6,7 +6,6 @@ import { scaleBand, scaleLinear } from 'd3-scale' import { ControlBar, ControlButton, ControlField, RangeField } from './controls' import { entranceRows as rows } from './model' import type { ChartMotionTweenTransition } from '@tanstack/charts' -import type { MotionRow } from './model' export interface MotionSettings { duration: number @@ -98,10 +97,7 @@ export default function MotionEntranceExample({ const [replayCount, setReplayCount] = useState(1) - const renderer = useMemo( - () => motion(), - [replayCount], - ) + const renderer = useMemo(() => motion(), [replayCount]) const definition = useMemo( () => motionEntranceDefinition(settings), diff --git a/benchmarks/conformance/cases/113-motion-updates/example.tsx b/benchmarks/conformance/cases/113-motion-updates/example.tsx index 438b7557..30100d7b 100644 --- a/benchmarks/conformance/cases/113-motion-updates/example.tsx +++ b/benchmarks/conformance/cases/113-motion-updates/example.tsx @@ -177,10 +177,7 @@ export default function MotionUpdatesExample({ const [announcement, setAnnouncement] = useState('') - const renderer = useMemo( - () => motion(), - [replayCount], - ) + const renderer = useMemo(() => motion(), [replayCount]) const rows = stages[stage] ?? stages[0] diff --git a/benchmarks/conformance/cases/114-spring-line-motion/example.tsx b/benchmarks/conformance/cases/114-spring-line-motion/example.tsx index d6997a0f..53e1ffdf 100644 --- a/benchmarks/conformance/cases/114-spring-line-motion/example.tsx +++ b/benchmarks/conformance/cases/114-spring-line-motion/example.tsx @@ -92,10 +92,7 @@ export default function SpringLineMotionExample({ const [announcement, setAnnouncement] = useState('') - const renderer = useMemo( - () => motion(), - [replayCount], - ) + const renderer = useMemo(() => motion(), [replayCount]) const definition = useMemo( () => diff --git a/benchmarks/conformance/cases/115-definition-motion/example.tsx b/benchmarks/conformance/cases/115-definition-motion/example.tsx index 0631c044..e1ffb02c 100644 --- a/benchmarks/conformance/cases/115-definition-motion/example.tsx +++ b/benchmarks/conformance/cases/115-definition-motion/example.tsx @@ -123,10 +123,7 @@ export default function DefinitionMotionExample({ const [announcement, setAnnouncement] = useState('') - const renderer = useMemo( - () => motion(), - [replayCount], - ) + const renderer = useMemo(() => motion(), [replayCount]) const definition = useMemo( () => diff --git a/benchmarks/conformance/cases/116-geometry-morph/example.tsx b/benchmarks/conformance/cases/116-geometry-morph/example.tsx index 74192a21..9e355b81 100644 --- a/benchmarks/conformance/cases/116-geometry-morph/example.tsx +++ b/benchmarks/conformance/cases/116-geometry-morph/example.tsx @@ -315,10 +315,7 @@ export default function GeometryMorphExample({ const [announcement, setAnnouncement] = useState('') - const renderer = useMemo( - () => motion(), - [replayCount], - ) + const renderer = useMemo(() => motion(), [replayCount]) const definition = useMemo( () => geometryMorphDefinition(morphData, mode), diff --git a/benchmarks/conformance/cases/117-focus-cursor-motion/example.tsx b/benchmarks/conformance/cases/117-focus-cursor-motion/example.tsx index b42e59bb..b30d621f 100644 --- a/benchmarks/conformance/cases/117-focus-cursor-motion/example.tsx +++ b/benchmarks/conformance/cases/117-focus-cursor-motion/example.tsx @@ -146,10 +146,7 @@ export default function FocusCursorMotionExample({ readonly ChartPoint[] >([]) - const renderer = useMemo( - () => motion({ initial: false }), - [], - ) + const renderer = useMemo(() => motion({ initial: false }), []) const definition = useMemo(focusCursorMotionDefinition, []) diff --git a/benchmarks/conformance/cases/118-token-usage-calendar/example.tsx b/benchmarks/conformance/cases/118-token-usage-calendar/example.tsx index 9b056d3a..1d23c82c 100644 --- a/benchmarks/conformance/cases/118-token-usage-calendar/example.tsx +++ b/benchmarks/conformance/cases/118-token-usage-calendar/example.tsx @@ -19,7 +19,7 @@ import { calendarMargin, } from './layout' -export interface ExampleOptions { +export interface ChartOptions { width: number height: number revision: number @@ -46,12 +46,12 @@ export const exampleTooltip = { portal, } -export function createExampleChart(input: ExampleOptions) { +export function createExampleChart(input: ChartOptions) { const days = tokenUsageCalendar(input.revision) const monthTicks = calendarMonthTicks() return defineChart( - defineChart({ + { marks: [ cell(days, { x: 'week', @@ -103,7 +103,7 @@ export function createExampleChart(input: ExampleOptions) { ...calendarMargin, bottom: calendarBottomMargin(input.width, input.height), }, - }), + }, { keyboard: true, tooltip: { use: tooltip, ...exampleTooltip }, @@ -111,8 +111,6 @@ export function createExampleChart(input: ExampleOptions) { ) } -export const tokenUsageCalendarDefinition = createExampleChart - export const chart = createExampleChart({ width: 720, height: 300, diff --git a/benchmarks/conformance/cases/118-token-usage-calendar/tanstack.test.ts b/benchmarks/conformance/cases/118-token-usage-calendar/tanstack.test.ts index 1ee23fdc..a006bf4c 100644 --- a/benchmarks/conformance/cases/118-token-usage-calendar/tanstack.test.ts +++ b/benchmarks/conformance/cases/118-token-usage-calendar/tanstack.test.ts @@ -14,7 +14,7 @@ import { tokenUsageCalendar, type TokenUsageDay, } from './model' -import { tokenUsageCalendarDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ConformanceInput } from '../../types' type DefinitionDatum = @@ -23,7 +23,7 @@ type DefinitionDatum = describe('definition-owned token activity calendar', () => { it('keeps the exact day type, source identity, and 364 interactive cells', () => { const input = calendarInput(640) - const definition = tokenUsageCalendarDefinition(input) + const definition = createExampleChart(input) const first = render(definition, input) const second = render(definition, input) type Datum = DefinitionDatum @@ -46,7 +46,7 @@ describe('definition-owned token activity calendar', () => { it('owns month-label typography and leading-edge alignment in the axis definition', () => { const input = calendarInput(640) - const scene = render(tokenUsageCalendarDefinition(input), input) + const scene = render(createExampleChart(input), input) const nodes = flatten(scene.nodes) const labels = nodes.filter( (node): node is SceneLabel => @@ -80,7 +80,7 @@ describe('definition-owned token activity calendar', () => { 'keeps the edge alignment and cells responsive at %ipx', (width) => { const input = calendarInput(width) - const scene = render(tokenUsageCalendarDefinition(input), input) + const scene = render(createExampleChart(input), input) const nodes = flatten(scene.nodes) const firstLabel = nodes.find( (node): node is SceneLabel => @@ -135,7 +135,7 @@ function calendarInput(width: number): ConformanceInput { } function render( - definition: ReturnType, + definition: ReturnType, input: ConformanceInput, ) { return createChartRuntime().render( diff --git a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/example.tsx b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/example.tsx index 35685a77..8ceb5d3a 100644 --- a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/example.tsx +++ b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/example.tsx @@ -31,7 +31,7 @@ const cursorTransition = { } export const createStackedCursorRenderer = () => - motion({ + motion({ initial: false, transition: { type: 'spring', @@ -41,102 +41,94 @@ export const createStackedCursorRenderer = () => }, }) -export const stackedCursorDefinition = (rows: readonly StackedCursorRow[]) => - defineChart({ - marks: [ - crosshair({ - id: 'stacked-cursor-band', - x: { - band: { - fill: '#64748b', - fillOpacity: 0.26, - inset: stackedCursorBandInset, - radius: 3, +export const createExampleChart = (rows: readonly StackedCursorRow[]) => + defineChart( + { + marks: [ + crosshair({ + id: 'stacked-cursor-band', + x: { + band: { + fill: '#64748b', + fillOpacity: 0.26, + inset: stackedCursorBandInset, + radius: 3, + }, + label: { + format: String, + fill: 'CanvasText', + stroke: 'Canvas', + strokeWidth: 5, + fontSize: 11, + fontWeight: 700, + }, }, - label: { - format: String, - fill: 'CanvasText', - stroke: 'Canvas', - strokeWidth: 5, - fontSize: 11, - fontWeight: 700, + y: false, + motion: { transition: cursorTransition }, + }), + barY(rows, { + id: 'stacked-cursor-bars', + x: 'period', + y: 'deaths', + z: 'cause', + color: 'cause', + key: 'id', + layout: stack({ order: stackedCursorCauses }), + inset: stackedCursorBarInset, + radius: 2, + }), + crosshair({ + id: 'stacked-cursor-rule', + x: false, + y: { + stroke: '#475569', + strokeOpacity: 0.82, + strokeWidth: 1, + strokeDasharray: '4 4', + label: { + format: formatStackedCursorEndpoint, + fill: 'CanvasText', + stroke: 'Canvas', + strokeWidth: 16, + fontSize: 11, + fontWeight: 700, + }, }, - }, - y: false, - motion: { transition: cursorTransition }, - }), - barY(rows, { - id: 'stacked-cursor-bars', - x: 'period', - y: 'deaths', - z: 'cause', - color: 'cause', - key: 'id', - layout: stack({ order: stackedCursorCauses }), - inset: stackedCursorBarInset, - radius: 2, - }), - crosshair({ - id: 'stacked-cursor-rule', - x: false, - y: { - stroke: '#475569', - strokeOpacity: 0.82, - strokeWidth: 1, - strokeDasharray: '4 4', - label: { - format: formatStackedCursorEndpoint, - fill: 'CanvasText', - stroke: 'Canvas', - strokeWidth: 16, - fontSize: 11, - fontWeight: 700, - }, - }, - motion: { transition: cursorTransition }, - }), - ], - x: { - scale: scaleBand().domain(stackedCursorPeriods).padding(0.18), - }, - y: { - scale: scaleLinear().domain([0, stackedCursorMaximum]), - grid: true, - axis: { ticks: { count: 5 }, label: 'Deaths' }, - }, - color: { - domain: stackedCursorCauses, - range: stackedCursorColors, - legend: colorLegend({ label: 'Cause' }), + motion: { transition: cursorTransition }, + }), + ], + x: { + scale: scaleBand().domain(stackedCursorPeriods).padding(0.18), + }, + y: { + scale: scaleLinear().domain([0, stackedCursorMaximum]), + grid: true, + axis: { ticks: { count: 5 }, label: 'Deaths' }, + }, + color: { + domain: stackedCursorCauses, + range: stackedCursorColors, + legend: colorLegend({ label: 'Cause' }), + }, + focus: 'group-x', + focusRing: false, + maxFocusDistance: Number.POSITIVE_INFINITY, + tooltip: false, + keyboard: true, }, - focus: 'group-x', - focusRing: false, - maxFocusDistance: Number.POSITIVE_INFINITY, - tooltip: false, - keyboard: true, - }) + { svgAnimation: false }, + ) export default function StackedCursorCatalogView({ width = 640, height = 480, revision = 0, }: ExampleProps = {}) { - const input = { width, height, revision, preview: false, interactive: true } - const idPrefix = '119-stacked-bar-band-cursor' const renderer = useMemo(createStackedCursorRenderer, []) const definition = useMemo( - () => - defineChart( - stackedCursorDefinition(stackedCursorRowsForRevision(input.revision)), - { - svgAnimation: false, - ...(true ? {} : { focus: false }), - keyboard: true, - tooltip: false, - }, - ), - [true, input.revision], + () => createExampleChart(stackedCursorRowsForRevision(revision)), + [revision], ) const ariaLabel = 'Crimean War deaths with x band and y rule cursors' @@ -145,16 +137,13 @@ export default function StackedCursorCatalogView({ 'Move over a stacked bar. The x cursor highlights the full stack and the dotted y cursor marks the focused segment endpoint.' return ( -
+
diff --git a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/model.ts b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/model.ts index 450ebf4b..6101bed0 100644 --- a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/model.ts +++ b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/model.ts @@ -1,4 +1,4 @@ -import { crimeanWar } from '@charts-poc/demo-data/crimean-war' +import { crimeanWar } from '@tanstack/charts-data/crimean-war' export const stackedCursorCauses = ['disease', 'wounds', 'other'] as const export const stackedCursorColors = ['#4269d0', '#ff725c', '#efb118'] diff --git a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/tanstack.ts b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/tanstack.ts index 74013f25..a1ed0267 100644 --- a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/tanstack.ts +++ b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/tanstack.ts @@ -1,5 +1,5 @@ import { mountChartRenderer } from '@tanstack/charts/renderer' -import { createStackedCursorRenderer, stackedCursorDefinition } from './example' +import { createStackedCursorRenderer, createExampleChart } from './example' import { catalogPreviewDefinition } from '../../shared/preview' import { tanstackCase } from '../../shared/mount' import { @@ -17,8 +17,7 @@ import type { export { default as Example } from './example' export const catalogCase = tanstackCase( - (input) => - stackedCursorDefinition(stackedCursorRowsForRevision(input.revision)), + (input) => createExampleChart(stackedCursorRowsForRevision(input.revision)), 'Crimean War deaths with x band and y rule cursors', true, { @@ -44,8 +43,8 @@ export const mount: ConformanceMount = (container, input) => { return { definition: nextInput.preview === true - ? catalogPreviewDefinition(stackedCursorDefinition(rows)) - : stackedCursorDefinition(rows), + ? catalogPreviewDefinition(createExampleChart(rows)) + : createExampleChart(rows), renderer, width: nextInput.width, height: nextInput.height, diff --git a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/view.tsx b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/view.tsx index 86b6730c..7714e77f 100644 --- a/benchmarks/conformance/cases/119-stacked-bar-band-cursor/view.tsx +++ b/benchmarks/conformance/cases/119-stacked-bar-band-cursor/view.tsx @@ -1,7 +1,7 @@ import { forwardRef, useMemo } from 'react' import { defineChart } from '@tanstack/charts' import { Chart } from '@tanstack/charts/react/core' -import { createStackedCursorRenderer, stackedCursorDefinition } from './example' +import { createStackedCursorRenderer, createExampleChart } from './example' import { stackedCursorRowsForRevision } from './model' import type { ConformanceTestDriver } from '../../types' import type { ReactConformanceProps } from '../../shared/react-mount' @@ -14,7 +14,7 @@ const StackedCursorCatalogView = forwardRef< const definition = useMemo( () => defineChart( - stackedCursorDefinition(stackedCursorRowsForRevision(input.revision)), + createExampleChart(stackedCursorRowsForRevision(input.revision)), { svgAnimation: false, ...(input.interactive ? {} : { focus: false }), diff --git a/benchmarks/conformance/cases/120-themed-interactive-area/example.tsx b/benchmarks/conformance/cases/120-themed-interactive-area/example.tsx index e1e7670c..f7fabb1e 100644 --- a/benchmarks/conformance/cases/120-themed-interactive-area/example.tsx +++ b/benchmarks/conformance/cases/120-themed-interactive-area/example.tsx @@ -35,12 +35,162 @@ export function createExampleChart( revision: number, width: number, height: number, + previewMode = false, ) { + const rows = themedAreaRows(range, revision) + const input = { + width, + height, + preview: previewMode, + } + + const first = rows[0] + const last = rows.at(-1) + if (!first || !last) throw new TypeError('The themed area needs data') + + const maximum = Math.max(...rows.map((row) => row.visitors)) + const yMaximum = Math.max(500, Math.ceil((maximum * 1.08) / 100) * 100) + const preview = input.preview === true + const dateTicks = evenlySpacedDates(first.date, last.date, preview ? 3 : 5) + return defineChart( - themedInteractiveAreaDefinition(themedAreaRows(range, revision), { - width, - height, - }), + { + motion: { transition: themedAreaSpring }, + marks: [ + decorative( + areaY(rows, { + id: 'visitor-area', + x: 'date', + y: 'visitors', + key: 'id', + fill: 'url(#themed-area-fill)', + fillOpacity: 1, + curve: smooth, + }), + ), + decorative( + lineY(rows, { + id: 'visitor-line', + x: 'date', + y: 'visitors', + key: 'id', + stroke: accent, + strokeWidth: preview ? 2 : 2.4, + curve: smooth, + }), + ), + dot(rows, { + id: 'visitor-points', + x: 'date', + y: 'visitors', + key: 'id', + r: 3, + fill: accent, + fillOpacity: 0, + stroke: surface, + strokeOpacity: 0, + strokeWidth: 2, + states: [ + { + when: { focus: 'group' }, + style: { + fillOpacity: 1, + strokeOpacity: 1, + r: preview ? 3.75 : 4.5, + }, + transition: { + type: 'tween', + duration: 140, + easing: 'ease-out', + }, + }, + { + when: { focus: 'primary' }, + style: { + fillOpacity: 1, + strokeOpacity: 1, + r: preview ? 4.25 : 5, + }, + transition: { + type: 'tween', + duration: 140, + easing: 'ease-out', + }, + }, + ], + }), + crosshair({ + id: 'visitor-crosshair', + x: { + stroke: grid, + strokeOpacity: 0.34, + strokeWidth: 1, + strokeDasharray: '3 4', + }, + y: false, + motion: { transition: themedAreaSpring }, + }), + ], + x: { + scale: scaleUtc().domain([first.date, last.date]), + axis: { + line: false, + ticks: { + values: dateTicks, + size: 0, + padding: preview ? 5 : 8, + format: formatThemedAreaTick, + }, + tickLabels: { + fontSize: preview ? 8 : 10, + opacity: 0.62, + thin: { minGap: preview ? 5 : 12, priority: 'ends' }, + }, + }, + }, + y: { + scale: scaleLinear().domain([0, yMaximum]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, yMaximum / 3, (yMaximum * 2) / 3, yMaximum], + size: 0, + }, + tickLabels: false, + }, + }, + gradients: [ + { + id: 'themed-area-fill', + x1: 0, + y1: 0, + x2: 0, + y2: 1, + stops: [ + { offset: 0, color: accent, opacity: 0.34 }, + { offset: 0.58, color: accent, opacity: 0.13 }, + { offset: 1, color: accent, opacity: 0.015 }, + ], + }, + ], + theme: { + background: 'transparent', + foreground, + muted, + grid, + palette: [accent], + }, + focus: focusGroupX, + focusRing: false, + maxFocusDistance: Number.POSITIVE_INFINITY, + tooltip: false, + keyboard: true, + clip: true, + margin: preview + ? { top: 10, right: 18, bottom: 22, left: 18 } + : { top: 12, right: 18, bottom: 28, left: 18 }, + }, { keyboard: true, tooltip: { use: tooltip, ...themedAreaTooltip }, @@ -66,7 +216,7 @@ export default function Example({ ) const renderer = useMemo( () => - motion({ + motion({ initial: 'always', transition: themedAreaSpring, respectReducedMotion: true, @@ -139,158 +289,6 @@ const muted = 'var(--themed-area-muted, GrayText)' const grid = 'var(--themed-area-grid, CanvasText)' -export function themedInteractiveAreaDefinition( - rows: readonly ThemedAreaRow[], - input: ThemedAreaChartInput, -) { - const first = rows[0] - const last = rows.at(-1) - if (!first || !last) throw new TypeError('The themed area needs data') - - const maximum = Math.max(...rows.map((row) => row.visitors)) - const yMaximum = Math.max(500, Math.ceil((maximum * 1.08) / 100) * 100) - const preview = input.preview === true - const dateTicks = evenlySpacedDates(first.date, last.date, preview ? 3 : 5) - - return defineChart({ - motion: { transition: themedAreaSpring }, - marks: [ - decorative( - areaY(rows, { - id: 'visitor-area', - x: 'date', - y: 'visitors', - key: 'id', - fill: 'url(#themed-area-fill)', - fillOpacity: 1, - curve: smooth, - }), - ), - decorative( - lineY(rows, { - id: 'visitor-line', - x: 'date', - y: 'visitors', - key: 'id', - stroke: accent, - strokeWidth: preview ? 2 : 2.4, - curve: smooth, - }), - ), - dot(rows, { - id: 'visitor-points', - x: 'date', - y: 'visitors', - key: 'id', - r: 3, - fill: accent, - fillOpacity: 0, - stroke: surface, - strokeOpacity: 0, - strokeWidth: 2, - states: [ - { - when: { focus: 'group' }, - style: { - fillOpacity: 1, - strokeOpacity: 1, - r: preview ? 3.75 : 4.5, - }, - transition: { - type: 'tween', - duration: 140, - easing: 'ease-out', - }, - }, - { - when: { focus: 'primary' }, - style: { - fillOpacity: 1, - strokeOpacity: 1, - r: preview ? 4.25 : 5, - }, - transition: { - type: 'tween', - duration: 140, - easing: 'ease-out', - }, - }, - ], - }), - crosshair({ - id: 'visitor-crosshair', - x: { - stroke: grid, - strokeOpacity: 0.34, - strokeWidth: 1, - strokeDasharray: '3 4', - }, - y: false, - motion: { transition: themedAreaSpring }, - }), - ], - x: { - scale: scaleUtc().domain([first.date, last.date]), - axis: { - line: false, - ticks: { - values: dateTicks, - size: 0, - padding: preview ? 5 : 8, - format: formatThemedAreaTick, - }, - tickLabels: { - fontSize: preview ? 8 : 10, - opacity: 0.62, - thin: { minGap: preview ? 5 : 12, priority: 'ends' }, - }, - }, - }, - y: { - scale: scaleLinear().domain([0, yMaximum]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, yMaximum / 3, (yMaximum * 2) / 3, yMaximum], - size: 0, - }, - tickLabels: false, - }, - }, - gradients: [ - { - id: 'themed-area-fill', - x1: 0, - y1: 0, - x2: 0, - y2: 1, - stops: [ - { offset: 0, color: accent, opacity: 0.34 }, - { offset: 0.58, color: accent, opacity: 0.13 }, - { offset: 1, color: accent, opacity: 0.015 }, - ], - }, - ], - theme: { - background: 'transparent', - foreground, - muted, - grid, - palette: [accent], - }, - focus: focusGroupX, - focusRing: false, - maxFocusDistance: Number.POSITIVE_INFINITY, - tooltip: false, - keyboard: true, - clip: true, - margin: preview - ? { top: 10, right: 18, bottom: 22, left: 18 } - : { top: 12, right: 18, bottom: 28, left: 18 }, - }) -} - function evenlySpacedDates(first: Date, last: Date, count: number) { const start = first.getTime() const span = last.getTime() - start diff --git a/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.test.ts b/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.test.ts index 4e4cc1f4..155497ac 100644 --- a/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.test.ts +++ b/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.test.ts @@ -1,6 +1,6 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { themedInteractiveAreaDefinition } from './example' +import { createExampleChart } from './example' import { themedAreaRows } from './model' import { catalogCase, mount } from './tanstack' import type { ConformanceInput } from '../../types' @@ -22,11 +22,7 @@ describe('themed interactive area', () => { it('owns its gradient, smooth geometry, sparse guides, and focus cursor', () => { const rows = themedAreaRows('30d') - const definition = themedInteractiveAreaDefinition(rows, { - width: 288, - height: 192, - preview: true, - }) + const definition = createExampleChart('30d', 0, 288, 192, true) const scene = createChartRuntime< (typeof rows)[number], Date, diff --git a/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.ts b/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.ts index 6f8073d6..3105ab62 100644 --- a/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.ts +++ b/benchmarks/conformance/cases/120-themed-interactive-area/tanstack.ts @@ -6,7 +6,7 @@ import { mountChartRenderer } from '@tanstack/charts/renderer' import { tooltip } from '@tanstack/charts/tooltip' import { readChartMotionState, settleChartMotion } from '../../shared/motion' import { tanstackCase } from '../../shared/mount' -import { themedAreaSpring, themedInteractiveAreaDefinition } from './example' +import { themedAreaSpring, createExampleChart } from './example' import { themedAreaRanges, themedAreaRows, themedAreaRangeDays } from './model' import type { ChartPoint } from '@tanstack/charts' import type { ThemedAreaRange, ThemedAreaRow } from './model' @@ -23,11 +23,13 @@ let themedAreaMountId = 0 export const catalogCase = tanstackCase( (input) => - themedInteractiveAreaDefinition(themedAreaRows('30d', input.revision), { - width: input.width, - height: input.height, - preview: input.preview, - }), + createExampleChart( + '30d', + input.revision, + input.width, + input.height, + input.preview, + ), ariaLabel, themedAreaTooltip, { @@ -75,10 +77,12 @@ export const mount: ConformanceMount = (container, input) => { } const definition = () => defineChart( - themedInteractiveAreaDefinition(rows, { - width: currentInput.width, - height: chartHeight(), - }), + createExampleChart( + range, + currentInput.revision, + currentInput.width, + chartHeight(), + ), { svgAnimation: false, keyboard: true, diff --git a/benchmarks/conformance/cases/121-active-bar-dashboard/example.tsx b/benchmarks/conformance/cases/121-active-bar-dashboard/example.tsx index 6e0fba8a..dd0938e1 100644 --- a/benchmarks/conformance/cases/121-active-bar-dashboard/example.tsx +++ b/benchmarks/conformance/cases/121-active-bar-dashboard/example.tsx @@ -191,10 +191,7 @@ export default function ActiveBarDashboard({ const focusedId = useRef(null) - const renderer = useMemo( - () => motion({ initial: !false }), - [false], - ) + const renderer = useMemo(() => motion({ initial: !false }), [false]) const rows = dashboardRows(input.revision) diff --git a/benchmarks/conformance/cases/122-premium-kpi-sparklines/example.tsx b/benchmarks/conformance/cases/122-premium-kpi-sparklines/example.tsx index 485a5907..2b62fd2f 100644 --- a/benchmarks/conformance/cases/122-premium-kpi-sparklines/example.tsx +++ b/benchmarks/conformance/cases/122-premium-kpi-sparklines/example.tsx @@ -8,7 +8,7 @@ import { motion } from '@tanstack/charts/motion' import { scaleLinear } from '@tanstack/charts/scales/linear' import { scalePoint } from '@tanstack/charts/scales/point' import { curveMonotoneX } from 'd3-shape' -import type { PremiumKpiId, PremiumKpiPoint } from './model' +import type { PremiumKpiId } from './model' const fullGap = 12 function KpiCard({ @@ -281,7 +281,7 @@ export function premiumKpiDefinition(metric: PremiumKpiMetric) { : [line] return defineChart( - defineChart({ + { guides: false, marks, gradients: @@ -321,7 +321,7 @@ export function premiumKpiDefinition(metric: PremiumKpiMetric) { margin: { top: 4, right: 3, bottom: 3, left: 3 }, clip: true, motion: { transition: premiumKpiSpring }, - }), + }, { focus: false, pointer: false, @@ -333,7 +333,7 @@ export function premiumKpiDefinition(metric: PremiumKpiMetric) { } export function createPremiumKpiRenderer(initial = true) { - return motion({ + return motion({ initial, respectReducedMotion: true, transition: premiumKpiSpring, diff --git a/benchmarks/conformance/cases/123-active-donut-metric/example.tsx b/benchmarks/conformance/cases/123-active-donut-metric/example.tsx index f889cd4b..ecf04a2e 100644 --- a/benchmarks/conformance/cases/123-active-donut-metric/example.tsx +++ b/benchmarks/conformance/cases/123-active-donut-metric/example.tsx @@ -41,16 +41,14 @@ export interface DonutCenterRow { dy: number } -export type DonutDatum = PieDatum | DonutCenterRow +export type DonutDatum = PieDatum const tooltipOptions: ChartTooltipOptions = { anchor: 'point', placement: ['top', 'right', 'left', 'bottom'], className: 'active-donut-tooltip', format: (point) => - 'visitors' in point.datum - ? `${point.datum.label} · ${point.datum.visitors.toLocaleString('en-US')} visitors` - : point.datum.text, + `${point.datum.label} · ${point.datum.visitors.toLocaleString('en-US')} visitors`, } export function activeDonutDefinition( @@ -226,10 +224,7 @@ export default function ActiveDonutMetric({ const focusedId = useRef(null) - const renderer = useMemo( - () => motion({ initial: !false }), - [false], - ) + const renderer = useMemo(() => motion({ initial: !false }), [false]) const definition = useMemo( () => activeDonutDefinition(input, activeId), diff --git a/benchmarks/conformance/cases/124-theme-palette-matrix/example.tsx b/benchmarks/conformance/cases/124-theme-palette-matrix/example.tsx index e2b53757..fbdbead9 100644 --- a/benchmarks/conformance/cases/124-theme-palette-matrix/example.tsx +++ b/benchmarks/conformance/cases/124-theme-palette-matrix/example.tsx @@ -152,7 +152,7 @@ export default function ThemePaletteMatrix({ const renderer = useMemo( () => - motion({ + motion({ initial: true, respectReducedMotion: true, transition: { diff --git a/benchmarks/conformance/cases/125-sales-funnel/example.tsx b/benchmarks/conformance/cases/125-sales-funnel/example.tsx index da0d5690..c7dfa770 100644 --- a/benchmarks/conformance/cases/125-sales-funnel/example.tsx +++ b/benchmarks/conformance/cases/125-sales-funnel/example.tsx @@ -9,65 +9,63 @@ import { funnelLayout } from './model' const colors = ['#1e3a8a', '#1d4ed8', '#2563eb', '#3b82f6', '#60a5fa'] const firstStageValue = funnelStagesForRevision(0)[0]?.value ?? 1 -export const salesFunnelDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const stages = funnelStagesForRevision(input.revision) const layout = funnelLayout(stages) - return defineChart({ - marks: [ - areaX(layout.points, { - id: 'funnel-stages', - x1: 'x1', - x2: 'x2', - y: 'y', - z: 'id', - color: 'id', - key: (point) => `${point.id}:${point.boundary}`, - fillOpacity: 1, - }), - text(layout.labels, { - id: 'funnel-labels', - x: 'x', - y: 'y', - text: 'text', - key: 'id', - anchor: 'start', - fontSize: input.preview === true ? 8 : input.width < 400 ? 10 : 12, - fontWeight: 600, - }), - ], - x: { scale: scaleLinear().domain(layout.xDomain), axis: false }, - y: { scale: scaleLinear().domain(layout.yDomain), axis: false }, - color: { domain: stages.map((stage) => stage.id), range: colors }, - margin: 12, - }) + return defineChart( + { + marks: [ + areaX(layout.points, { + id: 'funnel-stages', + x1: 'x1', + x2: 'x2', + y: 'y', + z: 'id', + color: 'id', + key: (point) => `${point.id}:${point.boundary}`, + fillOpacity: 1, + }), + text(layout.labels, { + id: 'funnel-labels', + x: 'x', + y: 'y', + text: 'text', + key: 'id', + anchor: 'start', + fontSize: input.preview === true ? 8 : input.width < 400 ? 10 : 12, + fontWeight: 600, + }), + ], + x: { scale: scaleLinear().domain(layout.xDomain), axis: false }, + y: { scale: scaleLinear().domain(layout.yDomain), axis: false }, + color: { domain: stages.map((stage) => stage.id), range: colors }, + margin: 12, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.label} · ${datum.value.toLocaleString('en-US')} · ${Math.round( + (datum.value / firstStageValue) * 100, + )}% of visitors`, + }, + }, + }, + ) } -export interface ExampleOptions { +export interface ChartOptions { width: number - height: number revision: number preview?: boolean } export const exampleAriaLabel = 'Sales conversion funnel' -export const createExampleChart = (options: ExampleOptions) => - defineChart(salesFunnelDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.label} · ${datum.value.toLocaleString('en-US')} · ${Math.round( - (datum.value / firstStageValue) * 100, - )}% of visitors`, - }, - }, - }) - export const chart = createExampleChart({ width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/126-drillable-sunburst/example.tsx b/benchmarks/conformance/cases/126-drillable-sunburst/example.tsx index abf6860d..c3e53026 100644 --- a/benchmarks/conformance/cases/126-drillable-sunburst/example.tsx +++ b/benchmarks/conformance/cases/126-drillable-sunburst/example.tsx @@ -9,7 +9,7 @@ import { flarePreviewRootId, formatFlareValue, } from './model' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { ChartPoint } from '@tanstack/charts' import type { SunburstNode } from '@tanstack/charts/hierarchy/sunburst' import { defineChart } from '@tanstack/charts' @@ -95,10 +95,7 @@ export default function Example() { () => drillableSunburstDefinition(rootId), [rootId], ) - const renderer = useMemo( - () => motion({ initial: 'always' }), - [], - ) + const renderer = useMemo(() => motion({ initial: 'always' }), []) const parentId = flareParentId(rootId) const drill = (point: ChartPoint | null) => { diff --git a/benchmarks/conformance/cases/126-drillable-sunburst/model.ts b/benchmarks/conformance/cases/126-drillable-sunburst/model.ts index a06c23dc..13633e76 100644 --- a/benchmarks/conformance/cases/126-drillable-sunburst/model.ts +++ b/benchmarks/conformance/cases/126-drillable-sunburst/model.ts @@ -1,5 +1,5 @@ -import { flare } from '@charts-poc/demo-data/flare' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' export const flareRootId = '/flare' export const flarePreviewRootId = '/flare/analytics' diff --git a/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.test.ts b/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.test.ts index 08079d7e..f746ecb7 100644 --- a/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.test.ts +++ b/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.test.ts @@ -11,7 +11,7 @@ import { flareVisibleDepth, } from './model' import { drillableSunburstDefinition, mount } from './tanstack' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { SunburstNode } from '@tanstack/charts/hierarchy/sunburst' import type { ChartScene, SceneNode } from '@tanstack/charts' diff --git a/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.ts b/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.ts index 1046e6ea..a19ac65e 100644 --- a/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.ts +++ b/benchmarks/conformance/cases/126-drillable-sunburst/tanstack.ts @@ -16,7 +16,7 @@ import { flareParentId, flarePreviewRootId, } from './model' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { SunburstNode } from '@tanstack/charts/hierarchy/sunburst' import type { ChartPoint, ChartRendererHostOptions } from '@tanstack/charts' import type { ConformanceMount, ConformanceTestDriver } from '../../types' diff --git a/benchmarks/conformance/cases/127-shadcn-dashboard/example.tsx b/benchmarks/conformance/cases/127-shadcn-dashboard/example.tsx index 07bc9d65..0107c230 100644 --- a/benchmarks/conformance/cases/127-shadcn-dashboard/example.tsx +++ b/benchmarks/conformance/cases/127-shadcn-dashboard/example.tsx @@ -26,96 +26,6 @@ const primaryColor = 'var(--sd-primary, var(--ts-chart-1, #171717))' const mutedColor = 'var(--sd-muted-foreground, #737373)' const borderColor = 'var(--sd-border, #e5e5e5)' -export function shadcnDashboardChartDefinition( - data: readonly DashboardDatum[], - width = 288, -) { - const rows = dashboardAreaRows(data) - const tickValues = dashboardTickValues(data, width) - - return defineChart({ - marks: [ - areaY(rows, { - id: 'visitor-areas', - x: 'dateKey', - y: 'visitors', - z: 'series', - color: 'series', - key: (row) => `${row.dateKey}:${row.series}`, - layout: stack({ order: seriesOrder }), - curve: d3Curve(curveNatural), - fill: (row) => `url(#fill-${row.series})`, - fillOpacity: 0.6, - stroke: primaryColor, - strokeWidth: 1, - }), - ], - x: { - scale: scalePoint, - axis: { - line: false, - ticks: { - values: tickValues, - size: 0, - padding: 8, - format: formatDashboardDate, - }, - tickLabels: { - fontSize: 12, - opacity: 0.72, - dy: 5, - anchor: ({ value }) => - value === data.at(-1)?.date ? 'end' : 'middle', - dx: ({ value }) => (value === data.at(-1)?.date ? 5 : 0), - thin: { minGap: 32, priority: 'ends' }, - }, - }, - }, - y: { - scale: scaleLinear().domain([0, 1_200]), - grid: true, - axis: { - line: false, - ticks: { values: [0, 300, 600, 900, 1_200], size: 0 }, - tickLabels: false, - }, - }, - color: { domain: seriesOrder, range: [primaryColor, primaryColor] }, - gradients: [ - { - id: 'fill-mobile', - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: primaryColor, opacity: 0.1 }, - { offset: 0.95, color: primaryColor, opacity: 0.8 }, - ], - }, - { - id: 'fill-desktop', - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: primaryColor, opacity: 0.1 }, - { offset: 0.95, color: primaryColor, opacity: 1 }, - ], - }, - ], - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: { - foreground: mutedColor, - grid: borderColor, - background: 'transparent', - palette: [primaryColor], - }, - clip: true, - }) -} - const dashboardTooltip: ChartTooltipOptions = { className: 'sd-chart-tooltip', anchor: 'group-center', @@ -136,16 +46,102 @@ const dashboardTooltip: ChartTooltipOptions = { export function createExampleChart( data: readonly DashboardDatum[], - width: number, + width = 288, ) { - return defineChart(shadcnDashboardChartDefinition(data, width), { - svgAnimation: false, - focus: 'group-x', - focusRing: true, - maxFocusDistance: Number.POSITIVE_INFINITY, - keyboard: true, - tooltip: { use: tooltip, ...dashboardTooltip }, - }) + const rows = dashboardAreaRows(data) + const tickValues = dashboardTickValues(data, width) + + return defineChart( + { + marks: [ + areaY(rows, { + id: 'visitor-areas', + x: 'dateKey', + y: 'visitors', + z: 'series', + color: 'series', + key: (row) => `${row.dateKey}:${row.series}`, + layout: stack({ order: seriesOrder }), + curve: d3Curve(curveNatural), + fill: (row) => `url(#fill-${row.series})`, + fillOpacity: 0.6, + stroke: primaryColor, + strokeWidth: 1, + }), + ], + x: { + scale: scalePoint, + axis: { + line: false, + ticks: { + values: tickValues, + size: 0, + padding: 8, + format: formatDashboardDate, + }, + tickLabels: { + fontSize: 12, + opacity: 0.72, + dy: 5, + anchor: ({ value }) => + value === data.at(-1)?.date ? 'end' : 'middle', + dx: ({ value }) => (value === data.at(-1)?.date ? 5 : 0), + thin: { minGap: 32, priority: 'ends' }, + }, + }, + }, + y: { + scale: scaleLinear().domain([0, 1_200]), + grid: true, + axis: { + line: false, + ticks: { values: [0, 300, 600, 900, 1_200], size: 0 }, + tickLabels: false, + }, + }, + color: { domain: seriesOrder, range: [primaryColor, primaryColor] }, + gradients: [ + { + id: 'fill-mobile', + x1: 0, + y1: 1, + x2: 0, + y2: 0, + stops: [ + { offset: 0.05, color: primaryColor, opacity: 0.1 }, + { offset: 0.95, color: primaryColor, opacity: 0.8 }, + ], + }, + { + id: 'fill-desktop', + x1: 0, + y1: 1, + x2: 0, + y2: 0, + stops: [ + { offset: 0.05, color: primaryColor, opacity: 0.1 }, + { offset: 0.95, color: primaryColor, opacity: 1 }, + ], + }, + ], + margin: { top: 5, right: 5, bottom: 35, left: 5 }, + theme: { + foreground: mutedColor, + grid: borderColor, + background: 'transparent', + palette: [primaryColor], + }, + clip: true, + }, + { + svgAnimation: false, + focus: 'group-x', + focusRing: true, + maxFocusDistance: Number.POSITIVE_INFINITY, + keyboard: true, + tooltip: { use: tooltip, ...dashboardTooltip }, + }, + ) } export const definition = createExampleChart(filterDashboardData('90d'), 288) @@ -154,7 +150,7 @@ function DashboardChart({ data, input }: DashboardChartProps) { const width = dashboardChartWidth(input.width) const renderer = useMemo( () => - motion({ + motion({ initial: 'always', transition: { type: 'spring', diff --git a/benchmarks/conformance/cases/127-shadcn-dashboard/tanstack.test.ts b/benchmarks/conformance/cases/127-shadcn-dashboard/tanstack.test.ts index ae335638..8ef0f097 100644 --- a/benchmarks/conformance/cases/127-shadcn-dashboard/tanstack.test.ts +++ b/benchmarks/conformance/cases/127-shadcn-dashboard/tanstack.test.ts @@ -1,14 +1,14 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { filterDashboardData } from './data' -import { shadcnDashboardChartDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { SceneNode } from '@tanstack/charts' describe('shadcn dashboard TanStack chart', () => { it('renders two natural stacked areas with scoped gradients', () => { const runtime = createChartRuntime() const scene = runtime.render( - shadcnDashboardChartDefinition(filterDashboardData('90d')), + createExampleChart(filterDashboardData('90d')), { width: 900, height: 250 }, ) const areas = flatten(scene.nodes).filter((node) => node.kind === 'area') diff --git a/benchmarks/conformance/cases/128-shadcn-bar-multiple/example.tsx b/benchmarks/conformance/cases/128-shadcn-bar-multiple/example.tsx index 7e50311d..13214666 100644 --- a/benchmarks/conformance/cases/128-shadcn-bar-multiple/example.tsx +++ b/benchmarks/conformance/cases/128-shadcn-bar-multiple/example.tsx @@ -1,23 +1,12 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - group, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, group, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnSeriesRows } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnSeriesRows } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { - return groupedBarDefinition() -} -function groupedBarDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter( (row) => row.series === 'desktop' || row.series === 'mobile', ) @@ -25,25 +14,39 @@ function groupedBarDefinition() { .domain(twoSeries) .paddingInner(0.08) .paddingOuter(0) - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: group({ scale: groupScale }), - radius: 4, - }), - ], - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) + return defineChart( + { + marks: [ + barY(rows, { + id: 'visitor-bars', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: group({ scale: groupScale }), + radius: 4, + }), + ], + x: shadcnXAxis(), + y: { scale: scaleLinear, grid: true, axis: false }, + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: { top: 5, right: 5, bottom: 35, left: 5 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnXAxis() { return { @@ -86,70 +89,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -158,9 +110,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Multiple

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/128-shadcn-bar-multiple/styles.css b/benchmarks/conformance/cases/128-shadcn-bar-multiple/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/128-shadcn-bar-multiple/styles.css +++ b/benchmarks/conformance/cases/128-shadcn-bar-multiple/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/128-shadcn-bar-multiple/tanstack.ts b/benchmarks/conformance/cases/128-shadcn-bar-multiple/tanstack.ts index f1475c5f..4515d34c 100644 --- a/benchmarks/conformance/cases/128-shadcn-bar-multiple/tanstack.ts +++ b/benchmarks/conformance/cases/128-shadcn-bar-multiple/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -export const barMultipleDefinition = definition export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/example.tsx b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/example.tsx index 0292e522..950f5946 100644 --- a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/example.tsx +++ b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -16,10 +10,10 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -57,18 +51,32 @@ function createDefinition() { fontSize: 14, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -99,70 +107,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -171,9 +128,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Donut with Text

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/styles.css b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/styles.css +++ b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/tanstack.ts b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/tanstack.ts index e9c7f828..4f5172c1 100644 --- a/benchmarks/conformance/cases/129-shadcn-pie-donut-text/tanstack.ts +++ b/benchmarks/conformance/cases/129-shadcn-pie-donut-text/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -export const pieDonutTextDefinition = definition export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/13-interval-timeline/example.tsx b/benchmarks/conformance/cases/13-interval-timeline/example.tsx index dd4aed0f..65e9fc2c 100644 --- a/benchmarks/conformance/cases/13-interval-timeline/example.tsx +++ b/benchmarks/conformance/cases/13-interval-timeline/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { barX, colorLegend, defineChart } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' @@ -12,57 +12,51 @@ const date = new Intl.DateTimeFormat('en-US', { timeZone: 'UTC', }) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = aapl.slice(input.revision * 3, input.revision * 3 + 8) - return defineChart({ - marks: [ - barX(rows, { - x1: 'Open', - x2: 'Close', - y: 'Date', - color: (row) => (row.Close >= row.Open ? 'Gain' : 'Loss'), - inset: 1, - radius: 3, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Share price ($)' } }, - y: { - scale: () => scaleBand().paddingInner(0.16), - axis: { ticks: { format: (value) => date.format(value) } }, + return defineChart( + { + marks: [ + barX(rows, { + x1: 'Open', + x2: 'Close', + y: 'Date', + color: (row) => (row.Close >= row.Open ? 'Gain' : 'Loss'), + inset: 1, + radius: 3, + }), + ], + x: { scale: scaleLinear, grid: true, axis: { label: 'Share price ($)' } }, + y: { + scale: () => scaleBand().paddingInner(0.16), + axis: { ticks: { format: (value) => date.format(value) } }, + }, + color: { + range: colors, + legend: colorLegend({ label: 'Session' }), + }, }, - color: { - range: colors, - legend: colorLegend({ label: 'Session' }), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `${date.format(point.datum.Date)} · Open $${point.datum.Open.toFixed(2)} · Close $${point.datum.Close.toFixed(2)}`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Apple daily open-to-close price ranges' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `${date.format(point.datum.Date)} · Open $${point.datum.Open.toFixed(2)} · Close $${point.datum.Close.toFixed(2)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/13-interval-timeline/plot.ts b/benchmarks/conformance/cases/13-interval-timeline/plot.ts index a39f4256..4925cae3 100644 --- a/benchmarks/conformance/cases/13-interval-timeline/plot.ts +++ b/benchmarks/conformance/cases/13-interval-timeline/plot.ts @@ -1,4 +1,4 @@ -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/130-shadcn-radar-multiple/example.tsx b/benchmarks/conformance/cases/130-shadcn-radar-multiple/example.tsx index e73ec961..785f6e3e 100644 --- a/benchmarks/conformance/cases/130-shadcn-radar-multiple/example.tsx +++ b/benchmarks/conformance/cases/130-shadcn-radar-multiple/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarMultiple } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarMultiple } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarMultiple const months = rows.map((row) => row.month) const radiusMax = 320 @@ -34,8 +28,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -47,48 +39,61 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 1, - stroke: shadcnColors[1], - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 1, + stroke: shadcnColors[1], + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -111,68 +116,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -181,9 +137,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Multiple

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/130-shadcn-radar-multiple/styles.css b/benchmarks/conformance/cases/130-shadcn-radar-multiple/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/130-shadcn-radar-multiple/styles.css +++ b/benchmarks/conformance/cases/130-shadcn-radar-multiple/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/130-shadcn-radar-multiple/tanstack.ts b/benchmarks/conformance/cases/130-shadcn-radar-multiple/tanstack.ts index 2c14f3b5..990842f7 100644 --- a/benchmarks/conformance/cases/130-shadcn-radar-multiple/tanstack.ts +++ b/benchmarks/conformance/cases/130-shadcn-radar-multiple/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -export const radarMultipleDefinition = definition export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/131-shadcn-radial-text/example.tsx b/benchmarks/conformance/cases/131-shadcn-radial-text/example.tsx index 90e4e3e7..e5d2fbba 100644 --- a/benchmarks/conformance/cases/131-shadcn-radial-text/example.tsx +++ b/benchmarks/conformance/cases/131-shadcn-radial-text/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -17,72 +11,62 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { - return buildSingleRadialDefinition({ - id: 'text', - visitors: 200, - endDegrees: 250, - innerRadius: 80, - outerRadius: 90, - backgroundInnerRadius: 80, - backgroundOuterRadius: 90, - cornerRadius: 10, - total: '200', - }) -} -function buildSingleRadialDefinition(options: { - id: string - visitors: number - endDegrees: number - innerRadius: number - outerRadius: number - backgroundInnerRadius: number - backgroundOuterRadius: number - cornerRadius: number - total: string -}) { - const rows = [ - { browser: 'safari', visitors: options.visitors, ring: 'visitors' }, - ] +export function createExampleChart() { + const rows = [{ browser: 'safari', visitors: 200, ring: 'visitors' }] const background = pie([{ id: 'background', value: 1 }], { value: 'value' }) - return defineChart({ - marks: [ - polar({ - marks: [ - radialArc(background, { - id: `${options.id}-background`, - key: 'id', - innerRadius: options.backgroundInnerRadius, - outerRadius: options.backgroundOuterRadius, - fill: 'var(--muted)', - }), - ], - }), - polar({ - startAngle: rechartsPolarAngle(0), - endAngle: rechartsPolarAngle(options.endDegrees), - angle: { scale: scaleLinear().domain([0, options.visitors]) }, - radius: { - scale: scaleBand().domain(['visitors']), - range: [options.innerRadius, options.outerRadius], - }, - marks: [ - radialBarAngle(rows, { - id: `${options.id}-value`, - angle: 'visitors', - radius: 'ring', - key: 'browser', - fill: shadcnColors[1], - cornerRadius: options.cornerRadius, - }), - ], - }), - radialCenterLabels(options.total, 36, 0, 24), - ], - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + marks: [ + radialArc(background, { + id: `${'text'}-background`, + key: 'id', + innerRadius: 80, + outerRadius: 90, + fill: 'var(--muted)', + }), + ], + }), + polar({ + startAngle: rechartsPolarAngle(0), + endAngle: rechartsPolarAngle(250), + angle: { scale: scaleLinear().domain([0, 200]) }, + radius: { + scale: scaleBand().domain(['visitors']), + range: [80, 90], + }, + marks: [ + radialBarAngle(rows, { + id: `${'text'}-value`, + angle: 'visitors', + radius: 'ring', + key: 'browser', + fill: shadcnColors[1], + cornerRadius: 10, + }), + ], + }), + radialCenterLabels('200', 36, 0, 24), + ], + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function radialCenterLabels( total: string, @@ -150,70 +134,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -222,9 +155,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart - Text

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/131-shadcn-radial-text/styles.css b/benchmarks/conformance/cases/131-shadcn-radial-text/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/131-shadcn-radial-text/styles.css +++ b/benchmarks/conformance/cases/131-shadcn-radial-text/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/131-shadcn-radial-text/tanstack.ts b/benchmarks/conformance/cases/131-shadcn-radial-text/tanstack.ts index 1fe4bc1c..d74f3128 100644 --- a/benchmarks/conformance/cases/131-shadcn-radial-text/tanstack.ts +++ b/benchmarks/conformance/cases/131-shadcn-radial-text/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -export const radialTextDefinition = definition export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/example.tsx b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/example.tsx index 4d58e376..1e51c05c 100644 --- a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/example.tsx +++ b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Advanced

Tooltip with custom formatter and total.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/styles.css b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/styles.css +++ b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/tanstack.ts b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/tanstack.ts index 3beb7f8c..59299f09 100644 --- a/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/tanstack.ts +++ b/benchmarks/conformance/cases/132-shadcn-tooltip-advanced/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -export const advancedTooltipDefinition = definition export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/133-shadcn-area-axes/example.tsx b/benchmarks/conformance/cases/133-shadcn-area-axes/example.tsx index 00521ba0..8718aee3 100644 --- a/benchmarks/conformance/cases/133-shadcn-area-axes/example.tsx +++ b/benchmarks/conformance/cases/133-shadcn-area-axes/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,47 +14,60 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['mobile', 'desktop'], - ...{}, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['mobile', 'desktop'], + }), + curve: d3Curve(curve), + fill: undefined, + fillOpacity: 0.4, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: undefined, - fillOpacity: 0.4, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 600]), - grid: true, - axis: { line: false, ticks: { size: 0, values: [0, 300, 600] } }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 600]), + grid: true, + axis: { line: false, ticks: { size: 0, values: [0, 300, 600] } }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 12, right: 12, bottom: 28, left: 40 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 12, right: 12, bottom: 28, left: 40 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -100,68 +110,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -170,9 +131,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Axes

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/133-shadcn-area-axes/styles.css b/benchmarks/conformance/cases/133-shadcn-area-axes/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/133-shadcn-area-axes/styles.css +++ b/benchmarks/conformance/cases/133-shadcn-area-axes/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/133-shadcn-area-axes/tanstack.ts b/benchmarks/conformance/cases/133-shadcn-area-axes/tanstack.ts index 05668287..c93c4489 100644 --- a/benchmarks/conformance/cases/133-shadcn-area-axes/tanstack.ts +++ b/benchmarks/conformance/cases/133-shadcn-area-axes/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/134-shadcn-area-default/example.tsx b/benchmarks/conformance/cases/134-shadcn-area-default/example.tsx index 259bfb66..8f0b4e75 100644 --- a/benchmarks/conformance/cases/134-shadcn-area-default/example.tsx +++ b/benchmarks/conformance/cases/134-shadcn-area-default/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - areaY, - d3Curve, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { areaY, d3Curve, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,39 +8,53 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-area', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - fill: shadcnColors[0], - fillOpacity: 0.4, - stroke: shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-area', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + fill: shadcnColors[0], + fillOpacity: 0.4, + stroke: shadcnColors[0], + strokeWidth: 1.5, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -91,68 +97,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -161,9 +118,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/134-shadcn-area-default/styles.css b/benchmarks/conformance/cases/134-shadcn-area-default/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/134-shadcn-area-default/styles.css +++ b/benchmarks/conformance/cases/134-shadcn-area-default/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/134-shadcn-area-default/tanstack.ts b/benchmarks/conformance/cases/134-shadcn-area-default/tanstack.ts index 44b41a4d..646d62b1 100644 --- a/benchmarks/conformance/cases/134-shadcn-area-default/tanstack.ts +++ b/benchmarks/conformance/cases/134-shadcn-area-default/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/135-shadcn-area-gradient/example.tsx b/benchmarks/conformance/cases/135-shadcn-area-gradient/example.tsx index ef569b82..5a633cae 100644 --- a/benchmarks/conformance/cases/135-shadcn-area-gradient/example.tsx +++ b/benchmarks/conformance/cases/135-shadcn-area-gradient/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,58 +14,71 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['mobile', 'desktop'], - ...{}, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['mobile', 'desktop'], + }), + curve: d3Curve(curve), + fill: (row) => `url(#shadcn-area-${row.series})`, + fillOpacity: 0.4, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: (row) => `url(#shadcn-area-${row.series})`, - fillOpacity: 0.4, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: twoSeries.map((series, index) => ({ + id: `shadcn-area-${series}`, + x1: 0, + y1: 1, + x2: 0, + y2: 0, + stops: [ + { offset: 0.05, color: shadcnColors[index], opacity: 0.08 }, + { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, + ], + })), + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: twoSeries.map((series, index) => ({ - id: `shadcn-area-${series}`, - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: shadcnColors[index], opacity: 0.08 }, - { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, - ], - })), - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -111,68 +121,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -181,9 +142,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Gradient

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/135-shadcn-area-gradient/styles.css b/benchmarks/conformance/cases/135-shadcn-area-gradient/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/135-shadcn-area-gradient/styles.css +++ b/benchmarks/conformance/cases/135-shadcn-area-gradient/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/135-shadcn-area-gradient/tanstack.ts b/benchmarks/conformance/cases/135-shadcn-area-gradient/tanstack.ts index c38602c7..a69b2835 100644 --- a/benchmarks/conformance/cases/135-shadcn-area-gradient/tanstack.ts +++ b/benchmarks/conformance/cases/135-shadcn-area-gradient/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/136-shadcn-area-icons/example.tsx b/benchmarks/conformance/cases/136-shadcn-area-icons/example.tsx index 042aa6b6..de079524 100644 --- a/benchmarks/conformance/cases/136-shadcn-area-icons/example.tsx +++ b/benchmarks/conformance/cases/136-shadcn-area-icons/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,47 +14,60 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['mobile', 'desktop'], - ...{}, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['mobile', 'desktop'], + }), + curve: d3Curve(curve), + fill: undefined, + fillOpacity: 0.4, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: undefined, - fillOpacity: 0.4, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -100,68 +110,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - 27 - const headerAction = null - const legend = - const footer = return (
@@ -170,9 +131,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Icons

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/136-shadcn-area-icons/styles.css b/benchmarks/conformance/cases/136-shadcn-area-icons/styles.css index 7d46886a..8af5ed2a 100644 --- a/benchmarks/conformance/cases/136-shadcn-area-icons/styles.css +++ b/benchmarks/conformance/cases/136-shadcn-area-icons/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -116,11 +113,6 @@ align-items: center; gap: 6px; } -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} .sc-legend-icon { width: 12px; height: 12px; @@ -130,22 +122,6 @@ stroke-linecap: round; stroke-linejoin: round; } -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +143,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +163,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/136-shadcn-area-icons/tanstack.ts b/benchmarks/conformance/cases/136-shadcn-area-icons/tanstack.ts index a1d91fc5..df76afce 100644 --- a/benchmarks/conformance/cases/136-shadcn-area-icons/tanstack.ts +++ b/benchmarks/conformance/cases/136-shadcn-area-icons/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/137-shadcn-area-interactive/example.tsx b/benchmarks/conformance/cases/137-shadcn-area-interactive/example.tsx index f9a24907..f4101280 100644 --- a/benchmarks/conformance/cases/137-shadcn-area-interactive/example.tsx +++ b/benchmarks/conformance/cases/137-shadcn-area-interactive/example.tsx @@ -5,8 +5,6 @@ import { defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -16,8 +14,8 @@ import { curveNatural } from 'd3-shape' import { shadcnColors, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' -import interactiveAreaData from '@charts-poc/demo-data/shadcn-area-interactive-data' +} from '@tanstack/charts-data/shadcn' +import interactiveAreaData from '@tanstack/charts-data/shadcn-area-interactive-data' import './styles.css' type InteractiveTimeRange = '90d' | '30d' | '7d' const twoSeries = ['desktop', 'mobile'] as const @@ -26,71 +24,85 @@ const interactiveAreaRows = interactiveAreaData as readonly { desktop: number mobile: number }[] -function createDefinition(timeRange: InteractiveTimeRange = '90d') { +export function createExampleChart(timeRange: InteractiveTimeRange = '90d') { const filteredRows = filterInteractiveAreaRows(timeRange) const rows: ShadcnSeriesDatum[] = filteredRows.flatMap((row) => [ { month: row.date, series: 'mobile', value: row.mobile }, { month: row.date, series: 'desktop', value: row.desktop }, ]) - return defineChart(({ width }) => ({ - marks: [ - areaY(rows, { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ order: ['mobile', 'desktop'] }), - curve: d3Curve(curveNatural), - fill: (row) => `url(#shadcn-interactive-${row.series})`, - fillOpacity: 1, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1, - }), - ], - x: { - scale: scalePoint, - axis: { - line: false, - ticks: { - values: interactiveDateTicks(timeRange), - size: 0, - padding: 10, - format: formatMonthDay, + return defineChart( + ({ width }) => ({ + marks: [ + areaY(rows, { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ order: ['mobile', 'desktop'] }), + curve: d3Curve(curveNatural), + fill: (row) => `url(#shadcn-interactive-${row.series})`, + fillOpacity: 1, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1, + }), + ], + x: { + scale: scalePoint, + axis: { + line: false, + ticks: { + values: interactiveDateTicks(timeRange), + size: 0, + padding: 10, + format: formatMonthDay, + }, }, }, - }, - y: { - scale: scaleLinear().domain([0, 1200]), - grid: true, - axis: { - line: false, - ticks: { values: [0, 300, 600, 900, 1200], size: 0 }, - tickLabels: false, + y: { + scale: scaleLinear().domain([0, 1200]), + grid: true, + axis: { + line: false, + ticks: { values: [0, 300, 600, 900, 1200], size: 0 }, + tickLabels: false, + }, + }, + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + gradients: twoSeries.map((series, index) => ({ + id: `shadcn-interactive-${series}`, + x1: 0, + y1: 1, + x2: 0, + y2: 0, + stops: [ + { offset: 0.05, color: shadcnColors[index], opacity: 0.1 }, + { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, + ], + })), + margin: { + top: 32, + right: width < 400 ? 14 : 5, + bottom: 35, + left: 5, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - gradients: twoSeries.map((series, index) => ({ - id: `shadcn-interactive-${series}`, - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: shadcnColors[index], opacity: 0.1 }, - { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, - ], - })), - margin: { - top: 32, - right: width < 400 ? 14 : 5, - bottom: 35, - left: 5, - }, - theme: shadcnTheme(), - })) + ) } function filterInteractiveAreaRows(timeRange: InteractiveTimeRange) { const days = timeRange === '30d' ? 30 : timeRange === '7d' ? 7 : 90 @@ -158,48 +170,11 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart(timeRange: InteractiveTimeRange = '90d') { - return defineChart(createDefinition(timeRange), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number @@ -210,30 +185,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) { () => createExampleChart(timeRange), [timeRange], ) - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = 250 - const headerAction = ( - setTimeRange(value as InteractiveTimeRange)} - options={[ - { value: '90d', label: 'Last 3 months' }, - { value: '30d', label: 'Last 30 days' }, - { value: '7d', label: 'Last 7 days' }, - ]} - /> - ) - const legend = - const footer = null return (
@@ -242,9 +196,17 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Interactive

Showing total visitors for the last 3 months

- {headerAction ? ( -
{headerAction}
- ) : null} +
+ setTimeRange(value as InteractiveTimeRange)} + options={[ + { value: '90d', label: 'Last 3 months' }, + { value: '30d', label: 'Last 30 days' }, + { value: '7d', label: 'Last 7 days' }, + ]} + /> +
- {legend ?
{legend}
: null} +
+ +
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/137-shadcn-area-interactive/styles.css b/benchmarks/conformance/cases/137-shadcn-area-interactive/styles.css index 7d46886a..f4525bdf 100644 --- a/benchmarks/conformance/cases/137-shadcn-area-interactive/styles.css +++ b/benchmarks/conformance/cases/137-shadcn-area-interactive/styles.css @@ -90,18 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} .sc-chart-footer { display: flex; flex-wrap: wrap; @@ -121,55 +109,9 @@ height: 8px; border-radius: 2px; } -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,108 +132,6 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} .sc-interactive-area { gap: 0; padding-top: 0; @@ -314,75 +154,6 @@ .sc-interactive-area .sc-chart-footer { margin-top: 8px; } -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} .sc-card-action { margin-left: auto; } @@ -429,33 +200,3 @@ flex: none; border-radius: 3px; } -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/137-shadcn-area-interactive/tanstack.ts b/benchmarks/conformance/cases/137-shadcn-area-interactive/tanstack.ts index 7dda24f1..5e58ee14 100644 --- a/benchmarks/conformance/cases/137-shadcn-area-interactive/tanstack.ts +++ b/benchmarks/conformance/cases/137-shadcn-area-interactive/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/138-shadcn-area-legend/example.tsx b/benchmarks/conformance/cases/138-shadcn-area-legend/example.tsx index b472b488..1ea23914 100644 --- a/benchmarks/conformance/cases/138-shadcn-area-legend/example.tsx +++ b/benchmarks/conformance/cases/138-shadcn-area-legend/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,47 +14,60 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['mobile', 'desktop'], - ...{}, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['mobile', 'desktop'], + }), + curve: d3Curve(curve), + fill: undefined, + fillOpacity: 0.4, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: undefined, - fillOpacity: 0.4, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -100,68 +110,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - 27 - const headerAction = null - const legend = - const footer = return (
@@ -170,9 +131,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Legend

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/138-shadcn-area-legend/styles.css b/benchmarks/conformance/cases/138-shadcn-area-legend/styles.css index 7d46886a..f31115f0 100644 --- a/benchmarks/conformance/cases/138-shadcn-area-legend/styles.css +++ b/benchmarks/conformance/cases/138-shadcn-area-legend/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -121,31 +118,6 @@ height: 8px; border-radius: 2px; } -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +139,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +159,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/138-shadcn-area-legend/tanstack.ts b/benchmarks/conformance/cases/138-shadcn-area-legend/tanstack.ts index 7638145b..d820ee55 100644 --- a/benchmarks/conformance/cases/138-shadcn-area-legend/tanstack.ts +++ b/benchmarks/conformance/cases/138-shadcn-area-legend/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/139-shadcn-area-linear/example.tsx b/benchmarks/conformance/cases/139-shadcn-area-linear/example.tsx index 26b4dfcd..46b279e2 100644 --- a/benchmarks/conformance/cases/139-shadcn-area-linear/example.tsx +++ b/benchmarks/conformance/cases/139-shadcn-area-linear/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - areaY, - d3Curve, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { areaY, d3Curve, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,39 +8,53 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveLinear - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-area', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - fill: shadcnColors[0], - fillOpacity: 0.4, - stroke: shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-area', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + fill: shadcnColors[0], + fillOpacity: 0.4, + stroke: shadcnColors[0], + strokeWidth: 1.5, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -91,68 +97,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -161,9 +118,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Linear

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/139-shadcn-area-linear/styles.css b/benchmarks/conformance/cases/139-shadcn-area-linear/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/139-shadcn-area-linear/styles.css +++ b/benchmarks/conformance/cases/139-shadcn-area-linear/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/139-shadcn-area-linear/tanstack.ts b/benchmarks/conformance/cases/139-shadcn-area-linear/tanstack.ts index aa513338..16bed6a6 100644 --- a/benchmarks/conformance/cases/139-shadcn-area-linear/tanstack.ts +++ b/benchmarks/conformance/cases/139-shadcn-area-linear/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/14-error-bars/example.tsx b/benchmarks/conformance/cases/14-error-bars/example.tsx index f5b15d97..e8f78d27 100644 --- a/benchmarks/conformance/cases/14-error-bars/example.tsx +++ b/benchmarks/conformance/cases/14-error-bars/example.tsx @@ -1,8 +1,8 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' import { defineChart, deviation, @@ -22,7 +22,7 @@ const estimate = new Intl.NumberFormat('en-US', { export const sampleDeviation = (context: TransformReduceContext) => context.values.length < 2 ? 0 : deviation(context) -export const errorBarsDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const observations = penguins .slice(input.revision * 8) .filter( @@ -37,72 +37,66 @@ export const errorBarsDefinition = (input: ExampleOptions) => { }, }) - return defineChart({ - marks: [ - link(rows, { - id: 'error-interval', - x1: 'species', - y1: ({ mean, deviation: spread }) => mean - spread, - x2: 'species', - y2: ({ mean, deviation: spread }) => mean + spread, - stroke: '#2563eb', - strokeWidth: 1.5, - }), - tickY(rows, { - id: 'error-low', - x: 'species', - y: ({ mean, deviation: spread }) => mean - spread, - stroke: '#2563eb', - strokeWidth: 1.5, - }), - tickY(rows, { - id: 'error-high', - x: 'species', - y: ({ mean, deviation: spread }) => mean + spread, - stroke: '#2563eb', - strokeWidth: 1.5, - }), - dot(rows, { - id: 'error-mean', - x: 'species', - y: 'mean', - key: 'species', - fill: '#2563eb', - r: 3.5, - }), - ], - x: { - scale: () => scaleBand().padding(0.22), + return defineChart( + { + marks: [ + link(rows, { + id: 'error-interval', + x1: 'species', + y1: ({ mean, deviation: spread }) => mean - spread, + x2: 'species', + y2: ({ mean, deviation: spread }) => mean + spread, + stroke: '#2563eb', + strokeWidth: 1.5, + }), + tickY(rows, { + id: 'error-low', + x: 'species', + y: ({ mean, deviation: spread }) => mean - spread, + stroke: '#2563eb', + strokeWidth: 1.5, + }), + tickY(rows, { + id: 'error-high', + x: 'species', + y: ({ mean, deviation: spread }) => mean + spread, + stroke: '#2563eb', + strokeWidth: 1.5, + }), + dot(rows, { + id: 'error-mean', + x: 'species', + y: 'mean', + key: 'species', + fill: '#2563eb', + r: 3.5, + }), + ], + x: { + scale: () => scaleBand().padding(0.22), + }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Body mass (g)' } }, }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Body mass (g)' } }, - }) + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `${point.datum.species} · Mean: ${estimate.format(point.datum.mean)} g · Range: ${estimate.format(point.datum.mean - point.datum.deviation)}–${estimate.format(point.datum.mean + point.datum.deviation)} g`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Point estimates with error bars' -export const createExampleChart = (options: ExampleOptions) => - defineChart(errorBarsDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `${point.datum.species} · Mean: ${estimate.format(point.datum.mean)} g · Range: ${estimate.format(point.datum.mean - point.datum.deviation)}–${estimate.format(point.datum.mean + point.datum.deviation)} g`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/14-error-bars/plot.ts b/benchmarks/conformance/cases/14-error-bars/plot.ts index 0491392d..72693730 100644 --- a/benchmarks/conformance/cases/14-error-bars/plot.ts +++ b/benchmarks/conformance/cases/14-error-bars/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { deviation, mean } from 'd3-array' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/14-error-bars/tanstack.test.ts b/benchmarks/conformance/cases/14-error-bars/tanstack.test.ts index 3ca74dab..52f3172e 100644 --- a/benchmarks/conformance/cases/14-error-bars/tanstack.test.ts +++ b/benchmarks/conformance/cases/14-error-bars/tanstack.test.ts @@ -1,15 +1,15 @@ import { existsSync, readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { penguins } from '@charts-poc/demo-data/penguins' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' import { createChartRuntime } from '@tanstack/charts' import type { ChartSpecDatum } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { errorBarsDefinition, sampleDeviation } from './tanstack' +import { createExampleChart, sampleDeviation } from './tanstack' import type { ConformanceInput } from '../../types' type PenguinWithMass = PenguinsRow & { body_mass_g: number } -type ErrorBarDatum = ChartSpecDatum> +type ErrorBarDatum = ChartSpecDatum> const expected = [ { @@ -148,7 +148,7 @@ function render(revision: number) { interactive: true, } return createChartRuntime().render( - errorBarsDefinition(input), + createExampleChart(input), input, ) } diff --git a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/example.tsx b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/example.tsx index 78173b29..4cd2fc7e 100644 --- a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/example.tsx +++ b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,9 +14,9 @@ import { shadcnColors, shadcnMonths, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { +export function createExampleChart() { const expandedRows = shadcnMonths.flatMap((row, index) => [ { month: row.month, @@ -31,48 +28,62 @@ function createDefinition() { ]) const rows = expandedRows const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['other', 'mobile', 'desktop'], - ...{ offset: 'normalize' }, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['other', 'mobile', 'desktop'], + ...{ offset: 'normalize' }, + }), + curve: d3Curve(curve), + fill: (row) => + row.series === 'other' + ? `color-mix(in oklch, ${shadcnColors[2]} 10%, transparent)` + : `color-mix(in oklch, ${row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0]} 40%, transparent)`, + fillOpacity: 1, + stroke: (row) => + row.series === 'other' + ? shadcnColors[2] + : row.series === 'mobile' + ? shadcnColors[1] + : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: (row) => - row.series === 'other' - ? `color-mix(in oklch, ${shadcnColors[2]} 10%, transparent)` - : `color-mix(in oklch, ${row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0]} 40%, transparent)`, - fillOpacity: 1, - stroke: (row) => - row.series === 'other' - ? shadcnColors[2] - : row.series === 'mobile' - ? shadcnColors[1] - : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 1]), - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 1]), + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: ['other', 'mobile', 'desktop'], + range: [shadcnColors[2], shadcnColors[1], shadcnColors[0]], + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: ['other', 'mobile', 'desktop'], - range: [shadcnColors[2], shadcnColors[1], shadcnColors[0]], + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -115,68 +126,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -185,9 +147,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Stacked Expanded

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/styles.css b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/styles.css +++ b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/tanstack.ts b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/tanstack.ts index 42d6b419..afe04172 100644 --- a/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/tanstack.ts +++ b/benchmarks/conformance/cases/140-shadcn-area-stacked-expand/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/141-shadcn-area-stacked/example.tsx b/benchmarks/conformance/cases/141-shadcn-area-stacked/example.tsx index c4790fef..15e870cd 100644 --- a/benchmarks/conformance/cases/141-shadcn-area-stacked/example.tsx +++ b/benchmarks/conformance/cases/141-shadcn-area-stacked/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { areaY, d3Curve, defineChart, stack, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,47 +14,60 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveNatural - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: ['mobile', 'desktop'], - ...{}, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-areas', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ + order: ['mobile', 'desktop'], + }), + curve: d3Curve(curve), + fill: undefined, + fillOpacity: 0.4, + stroke: (row) => + row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], + strokeWidth: 1.5, }), - curve: d3Curve(curve), - fill: undefined, - fillOpacity: 0.4, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -100,68 +110,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -170,9 +131,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Stacked

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/141-shadcn-area-stacked/styles.css b/benchmarks/conformance/cases/141-shadcn-area-stacked/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/141-shadcn-area-stacked/styles.css +++ b/benchmarks/conformance/cases/141-shadcn-area-stacked/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/141-shadcn-area-stacked/tanstack.ts b/benchmarks/conformance/cases/141-shadcn-area-stacked/tanstack.ts index dfd044bc..bc752fd3 100644 --- a/benchmarks/conformance/cases/141-shadcn-area-stacked/tanstack.ts +++ b/benchmarks/conformance/cases/141-shadcn-area-stacked/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/142-shadcn-area-step/example.tsx b/benchmarks/conformance/cases/142-shadcn-area-step/example.tsx index 31026c0d..52ab5e60 100644 --- a/benchmarks/conformance/cases/142-shadcn-area-step/example.tsx +++ b/benchmarks/conformance/cases/142-shadcn-area-step/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - areaY, - d3Curve, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { areaY, d3Curve, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,39 +8,53 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const monthSeries = ['desktop', 'mobile', 'tablet'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveStep - return defineChart({ - marks: [ - areaY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-area', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - fill: shadcnColors[0], - fillOpacity: 0.4, - stroke: shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear, - grid: true, - axis: { line: false, ticks: false, tickLabels: false }, + return defineChart( + { + marks: [ + areaY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-area', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + fill: shadcnColors[0], + fillOpacity: 0.4, + stroke: shadcnColors[0], + strokeWidth: 1.5, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear, + grid: true, + axis: { line: false, ticks: false, tickLabels: false }, + }, + color: { + domain: monthSeries, + range: shadcnColors.slice(0, 3), + }, + gradients: undefined, + margin: { top: 5, right: 12, bottom: 35, left: 12 }, + theme: shadcnTheme(), }, - color: { - domain: monthSeries, - range: shadcnColors.slice(0, 3), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - gradients: undefined, - margin: { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) + ) } function shadcnPointXAxis() { return { @@ -91,68 +97,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = return (
@@ -161,9 +118,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Area Chart - Step

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/142-shadcn-area-step/styles.css b/benchmarks/conformance/cases/142-shadcn-area-step/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/142-shadcn-area-step/styles.css +++ b/benchmarks/conformance/cases/142-shadcn-area-step/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/142-shadcn-area-step/tanstack.ts b/benchmarks/conformance/cases/142-shadcn-area-step/tanstack.ts index eb2edc0f..54331c9e 100644 --- a/benchmarks/conformance/cases/142-shadcn-area-step/tanstack.ts +++ b/benchmarks/conformance/cases/142-shadcn-area-step/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/143-shadcn-bar-active/example.tsx b/benchmarks/conformance/cases/143-shadcn-bar-active/example.tsx index f18f5a96..389c15b9 100644 --- a/benchmarks/conformance/cases/143-shadcn-bar-active/example.tsx +++ b/benchmarks/conformance/cases/143-shadcn-bar-active/example.tsx @@ -1,19 +1,12 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const rows = shadcnBrowsers.map((row) => row.browser === 'chrome' ? { ...row, visitors: 187 } @@ -21,29 +14,45 @@ function createDefinition() { ? { ...row, visitors: 275 } : row, ) - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'browser', - y: 'visitors', - color: 'browser', - fill: (row) => - row.browser === 'firefox' - ? `color-mix(in srgb, ${shadcnColors[2]} 80%, transparent)` - : shadcnColors[browserNames.indexOf(row.browser)]!, - stroke: (row) => (row.browser === 'firefox' ? shadcnColors[2] : 'none'), - strokeWidth: 2, - strokeDasharray: (row) => (row.browser === 'firefox' ? '4 4' : 'none'), - radius: 8, - }), - ], - x: shadcnBrowserXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: browserNames, range: shadcnColors }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) + return defineChart( + { + marks: [ + barY(rows, { + id: 'visitor-bars', + x: 'browser', + y: 'visitors', + color: 'browser', + fill: (row) => + row.browser === 'firefox' + ? `color-mix(in srgb, ${shadcnColors[2]} 80%, transparent)` + : shadcnColors[browserNames.indexOf(row.browser)]!, + stroke: (row) => + row.browser === 'firefox' ? shadcnColors[2] : 'none', + strokeWidth: 2, + strokeDasharray: (row) => + row.browser === 'firefox' ? '4 4' : 'none', + radius: 8, + }), + ], + x: shadcnBrowserXAxis(), + y: { scale: scaleLinear, grid: true, axis: false }, + color: { domain: browserNames, range: shadcnColors }, + margin: { top: 5, right: 5, bottom: 35, left: 5 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnBrowserXAxis() { return { @@ -86,70 +95,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -158,9 +116,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Active

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/143-shadcn-bar-active/styles.css b/benchmarks/conformance/cases/143-shadcn-bar-active/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/143-shadcn-bar-active/styles.css +++ b/benchmarks/conformance/cases/143-shadcn-bar-active/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/143-shadcn-bar-active/tanstack.ts b/benchmarks/conformance/cases/143-shadcn-bar-active/tanstack.ts index d7a1b080..06b42635 100644 --- a/benchmarks/conformance/cases/143-shadcn-bar-active/tanstack.ts +++ b/benchmarks/conformance/cases/143-shadcn-bar-active/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/144-shadcn-bar-default/example.tsx b/benchmarks/conformance/cases/144-shadcn-bar-default/example.tsx index 8cff7136..e78115fb 100644 --- a/benchmarks/conformance/cases/144-shadcn-bar-default/example.tsx +++ b/benchmarks/conformance/cases/144-shadcn-bar-default/example.tsx @@ -1,18 +1,11 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnMonths } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnMonths } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const marks = [ barY(rows, { @@ -24,13 +17,27 @@ function createDefinition() { radius: 8, }), ] - return defineChart({ - marks, - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) + return defineChart( + { + marks, + x: shadcnXAxis(), + y: { scale: scaleLinear, grid: true, axis: false }, + margin: { top: 5, right: 5, bottom: 35, left: 5 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnXAxis() { return { @@ -73,70 +80,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -145,9 +101,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/144-shadcn-bar-default/styles.css b/benchmarks/conformance/cases/144-shadcn-bar-default/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/144-shadcn-bar-default/styles.css +++ b/benchmarks/conformance/cases/144-shadcn-bar-default/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/144-shadcn-bar-default/tanstack.ts b/benchmarks/conformance/cases/144-shadcn-bar-default/tanstack.ts index 141b0c28..24a627d8 100644 --- a/benchmarks/conformance/cases/144-shadcn-bar-default/tanstack.ts +++ b/benchmarks/conformance/cases/144-shadcn-bar-default/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/example.tsx b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/example.tsx index 877e3946..d8099aed 100644 --- a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/example.tsx +++ b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/example.tsx @@ -1,18 +1,11 @@ -import { useMemo } from 'react' -import { - barX, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barX, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnMonths } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnMonths } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const marks = [ barX(rows, { @@ -23,16 +16,30 @@ function createDefinition() { radius: 5, }), ] - return defineChart({ - marks, - x: { scale: scaleLinear, axis: false }, - y: { - scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), - axis: { line: false, ticks: { size: 0 } }, + return defineChart( + { + marks, + x: { scale: scaleLinear, axis: false }, + y: { + scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), + axis: { line: false, ticks: { size: 0 } }, + }, + margin: { top: 5, right: 5, bottom: 5, left: 72 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - margin: { top: 5, right: 5, bottom: 5, left: 72 }, - theme: shadcnTheme(), - }) + ) } function shadcnTheme() { return { @@ -62,70 +69,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -134,9 +90,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Horizontal

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/styles.css b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/styles.css +++ b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/tanstack.ts b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/tanstack.ts index 10e3b1f5..ceda6bc8 100644 --- a/benchmarks/conformance/cases/145-shadcn-bar-horizontal/tanstack.ts +++ b/benchmarks/conformance/cases/145-shadcn-bar-horizontal/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/146-shadcn-bar-interactive/example.tsx b/benchmarks/conformance/cases/146-shadcn-bar-interactive/example.tsx index 515da8d7..3962f208 100644 --- a/benchmarks/conformance/cases/146-shadcn-bar-interactive/example.tsx +++ b/benchmarks/conformance/cases/146-shadcn-bar-interactive/example.tsx @@ -1,11 +1,5 @@ import { useMemo, useState } from 'react' -import { - barY, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -13,8 +7,8 @@ import { scaleBand, scaleLinear } from 'd3-scale' import { shadcnColors, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' -import interactiveAreaData from '@charts-poc/demo-data/shadcn-area-interactive-data' +} from '@tanstack/charts-data/shadcn' +import interactiveAreaData from '@tanstack/charts-data/shadcn-area-interactive-data' import './styles.css' type InteractiveSeries = 'desktop' | 'mobile' const twoSeries = ['desktop', 'mobile'] as const @@ -31,45 +25,61 @@ const interactiveBarRows: readonly ShadcnMonthDatum[] = interactiveAreaRows.map( tablet: 0, }), ) -function createDefinition(activeSeries: InteractiveSeries = 'desktop') { - return defineChart({ - marks: [ - barY(interactiveBarRows, { - id: 'daily-bars', - x: 'month', - y: (row) => row[activeSeries], - z: () => activeSeries, - key: 'month', - fill: activeSeries === 'desktop' ? shadcnColors[1] : shadcnColors[0], - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { - values: [ - '2024-04-01', - '2024-04-11', - '2024-04-22', - '2024-05-03', - '2024-05-14', - '2024-05-26', - '2024-06-06', - '2024-06-17', - '2024-06-29', - ], - size: 0, - padding: 10, - format: formatMonthDay, +export function createExampleChart( + activeSeries: InteractiveSeries = 'desktop', +) { + return defineChart( + { + marks: [ + barY(interactiveBarRows, { + id: 'daily-bars', + x: 'month', + y: (row) => row[activeSeries], + z: () => activeSeries, + key: 'month', + fill: activeSeries === 'desktop' ? shadcnColors[1] : shadcnColors[0], + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { + values: [ + '2024-04-01', + '2024-04-11', + '2024-04-22', + '2024-05-03', + '2024-05-14', + '2024-05-26', + '2024-06-06', + '2024-06-17', + '2024-06-29', + ], + size: 0, + padding: 10, + format: formatMonthDay, + }, }, }, + y: { scale: scaleLinear, grid: true, axis: false }, + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: { top: 5, right: 12, bottom: 25, left: 12 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 12, bottom: 25, left: 12 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function formatMonthDay(value: string) { return new Intl.DateTimeFormat('en-US', { @@ -106,50 +116,11 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart( - activeSeries: InteractiveSeries = 'desktop', -) { - return defineChart(createDefinition(activeSeries), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number @@ -160,22 +131,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) { () => createExampleChart(activeSeries), [activeSeries], ) - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = 250 - const headerAction = ( - - ) - const legend = null - const footer = null return (
@@ -184,9 +142,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Interactive

Showing total visitors for the last 3 months

- {headerAction ? ( -
{headerAction}
- ) : null} +
+ +
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/146-shadcn-bar-interactive/styles.css b/benchmarks/conformance/cases/146-shadcn-bar-interactive/styles.css index 7d46886a..bdcad3f4 100644 --- a/benchmarks/conformance/cases/146-shadcn-bar-interactive/styles.css +++ b/benchmarks/conformance/cases/146-shadcn-bar-interactive/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,130 +113,6 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} .sc-interactive-bar { gap: 0; padding: 0 0 30px; @@ -339,96 +138,9 @@ .sc-interactive-bar .sc-card-content { padding: 43px 24px 0; } -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} .sc-card-action { margin-left: auto; } -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} .sc-bar-metric { display: grid; width: 168px; diff --git a/benchmarks/conformance/cases/146-shadcn-bar-interactive/tanstack.ts b/benchmarks/conformance/cases/146-shadcn-bar-interactive/tanstack.ts index 5ac0262a..02739337 100644 --- a/benchmarks/conformance/cases/146-shadcn-bar-interactive/tanstack.ts +++ b/benchmarks/conformance/cases/146-shadcn-bar-interactive/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/example.tsx b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/example.tsx index bb98a5c6..d97c4482 100644 --- a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/example.tsx +++ b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/example.tsx @@ -1,57 +1,63 @@ -import { useMemo } from 'react' -import { - barX, - defineChart, - text, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barX, defineChart, text, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnMonths } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnMonths } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { - return defineChart({ - marks: [ - barX(shadcnMonths, { - id: 'visitor-bars', - x: 'desktop', - y: 'month', - fill: shadcnColors[1], - radius: 4, - }), - text(shadcnMonths, { - id: 'month-labels', - x: () => 0, - y: 'month', - text: 'month', - dx: 8, - anchor: 'start', - fill: 'var(--background)', - fontSize: 12, - }), - text(shadcnMonths, { - id: 'visitor-labels', - x: 'desktop', - y: 'month', - text: (row) => row.desktop.toLocaleString('en-US'), - dx: 8, - anchor: 'start', - fill: 'var(--foreground)', - fontSize: 12, - }), - ], - x: { scale: scaleLinear, grid: true, axis: false }, - y: { - scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), - axis: false, +export function createExampleChart() { + return defineChart( + { + marks: [ + barX(shadcnMonths, { + id: 'visitor-bars', + x: 'desktop', + y: 'month', + fill: shadcnColors[1], + radius: 4, + }), + text(shadcnMonths, { + id: 'month-labels', + x: () => 0, + y: 'month', + text: 'month', + dx: 8, + anchor: 'start', + fill: 'var(--background)', + fontSize: 12, + }), + text(shadcnMonths, { + id: 'visitor-labels', + x: 'desktop', + y: 'month', + text: (row) => row.desktop.toLocaleString('en-US'), + dx: 8, + anchor: 'start', + fill: 'var(--foreground)', + fontSize: 12, + }), + ], + x: { scale: scaleLinear, grid: true, axis: false }, + y: { + scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), + axis: false, + }, + margin: { top: 5, right: 36, bottom: 5, left: 0 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, }, - margin: { top: 5, right: 36, bottom: 5, left: 0 }, - theme: shadcnTheme(), - }) + ) } function shadcnTheme() { return { @@ -81,70 +87,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -153,9 +108,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Custom Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/styles.css b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/styles.css +++ b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/tanstack.ts b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/tanstack.ts index 1dc4cf3b..336219f4 100644 --- a/benchmarks/conformance/cases/147-shadcn-bar-label-custom/tanstack.ts +++ b/benchmarks/conformance/cases/147-shadcn-bar-label-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/148-shadcn-bar-label/example.tsx b/benchmarks/conformance/cases/148-shadcn-bar-label/example.tsx index 41ed111a..171e25a6 100644 --- a/benchmarks/conformance/cases/148-shadcn-bar-label/example.tsx +++ b/benchmarks/conformance/cases/148-shadcn-bar-label/example.tsx @@ -1,19 +1,11 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - text, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, text, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnMonths } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnMonths } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const marks = [ barY(rows, { @@ -36,13 +28,27 @@ function createDefinition() { }, }), ] - return defineChart({ - marks, - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - margin: { top: 24, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) + return defineChart( + { + marks, + x: shadcnXAxis(), + y: { scale: scaleLinear, grid: true, axis: false }, + margin: { top: 24, right: 5, bottom: 35, left: 5 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnXAxis() { return { @@ -85,70 +91,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -157,9 +112,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/148-shadcn-bar-label/styles.css b/benchmarks/conformance/cases/148-shadcn-bar-label/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/148-shadcn-bar-label/styles.css +++ b/benchmarks/conformance/cases/148-shadcn-bar-label/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/148-shadcn-bar-label/tanstack.ts b/benchmarks/conformance/cases/148-shadcn-bar-label/tanstack.ts index 84069216..24def477 100644 --- a/benchmarks/conformance/cases/148-shadcn-bar-label/tanstack.ts +++ b/benchmarks/conformance/cases/148-shadcn-bar-label/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/149-shadcn-bar-mixed/example.tsx b/benchmarks/conformance/cases/149-shadcn-bar-mixed/example.tsx index 40b74985..1714ec0e 100644 --- a/benchmarks/conformance/cases/149-shadcn-bar-mixed/example.tsx +++ b/benchmarks/conformance/cases/149-shadcn-bar-mixed/example.tsx @@ -1,35 +1,42 @@ -import { useMemo } from 'react' -import { - barX, - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barX, defineChart, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { - return defineChart({ - marks: [ - barX(shadcnBrowsers, { - id: 'visitor-bars', - x: 'visitors', - y: 'browser', - color: 'browser', - radius: 5, - }), - ], - x: { scale: scaleLinear, axis: false }, - y: shadcnBrowserYAxis(), - color: { domain: browserNames, range: shadcnColors }, - margin: { top: 5, right: 5, bottom: 5, left: 60 }, - theme: shadcnTheme(), - }) +export function createExampleChart() { + return defineChart( + { + marks: [ + barX(shadcnBrowsers, { + id: 'visitor-bars', + x: 'visitors', + y: 'browser', + color: 'browser', + radius: 5, + }), + ], + x: { scale: scaleLinear, axis: false }, + y: shadcnBrowserYAxis(), + color: { domain: browserNames, range: shadcnColors }, + margin: { top: 5, right: 5, bottom: 5, left: 60 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnBrowserYAxis() { return { @@ -68,70 +75,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -140,9 +96,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Mixed

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/149-shadcn-bar-mixed/styles.css b/benchmarks/conformance/cases/149-shadcn-bar-mixed/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/149-shadcn-bar-mixed/styles.css +++ b/benchmarks/conformance/cases/149-shadcn-bar-mixed/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/149-shadcn-bar-mixed/tanstack.ts b/benchmarks/conformance/cases/149-shadcn-bar-mixed/tanstack.ts index 51135e26..8c1dec41 100644 --- a/benchmarks/conformance/cases/149-shadcn-bar-mixed/tanstack.ts +++ b/benchmarks/conformance/cases/149-shadcn-bar-mixed/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/15-boxplot/example.tsx b/benchmarks/conformance/cases/15-boxplot/example.tsx index 55917a9e..dbac5488 100644 --- a/benchmarks/conformance/cases/15-boxplot/example.tsx +++ b/benchmarks/conformance/cases/15-boxplot/example.tsx @@ -3,62 +3,62 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { boxY, defineChart } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' -import { morley } from '@charts-poc/demo-data/morley' - -export const boxplotDefinition = () => - defineChart({ - marks: [ - boxY(morley, { - id: 'morley-boxplot', - x: 'Expt', - y: 'Speed', - key: (row) => `${row.Expt}:${row.Run}`, - fill: '#bfdbfe', - stroke: '#2563eb', - inset: 18, - r: 2.5, - }), - ], - x: { - scale: () => scaleBand().padding(0.22), - axis: { label: 'Experiment' }, - }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Speed of light (km/s minus 299,000)' }, - }, - }) - -export const exampleAriaLabel = 'Grouped boxplots' +import { morley } from '@tanstack/charts-data/morley' export const createExampleChart = () => - defineChart(boxplotDefinition(), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - datum.kind === 'summary' - ? `Experiment ${datum.category} · median ${datum.median.toLocaleString( - 'en-US', - { + defineChart( + { + marks: [ + boxY(morley, { + id: 'morley-boxplot', + x: 'Expt', + y: 'Speed', + key: (row) => `${row.Expt}:${row.Run}`, + fill: '#bfdbfe', + stroke: '#2563eb', + inset: 18, + r: 2.5, + }), + ], + x: { + scale: () => scaleBand().padding(0.22), + axis: { label: 'Experiment' }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Speed of light (km/s minus 299,000)' }, + }, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + datum.kind === 'summary' + ? `Experiment ${datum.category} · median ${datum.median.toLocaleString( + 'en-US', + { + maximumFractionDigits: 1, + }, + )} · IQR ${datum.q1.toLocaleString('en-US', { maximumFractionDigits: 1, - }, - )} · IQR ${datum.q1.toLocaleString('en-US', { - maximumFractionDigits: 1, - })}–${datum.q3.toLocaleString('en-US', { - maximumFractionDigits: 1, - })}` - : `Experiment ${datum.category} outlier · ${datum.value.toLocaleString( - 'en-US', - { + })}–${datum.q3.toLocaleString('en-US', { maximumFractionDigits: 1, - }, - )}`, + })}` + : `Experiment ${datum.category} outlier · ${datum.value.toLocaleString( + 'en-US', + { + maximumFractionDigits: 1, + }, + )}`, + }, }, }, - }) + ) + +export const exampleAriaLabel = 'Grouped boxplots' export const chart = createExampleChart() diff --git a/benchmarks/conformance/cases/15-boxplot/plot.ts b/benchmarks/conformance/cases/15-boxplot/plot.ts index 3dcd89d4..9889dfb1 100644 --- a/benchmarks/conformance/cases/15-boxplot/plot.ts +++ b/benchmarks/conformance/cases/15-boxplot/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { morley } from '@charts-poc/demo-data/morley' +import { morley } from '@tanstack/charts-data/morley' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/15-boxplot/tanstack.test.ts b/benchmarks/conformance/cases/15-boxplot/tanstack.test.ts index bb6ae7bd..16562d5b 100644 --- a/benchmarks/conformance/cases/15-boxplot/tanstack.test.ts +++ b/benchmarks/conformance/cases/15-boxplot/tanstack.test.ts @@ -1,18 +1,18 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { morley } from '@charts-poc/demo-data/morley' -import type { MorleyRow } from '@charts-poc/demo-data/morley' +import { morley } from '@tanstack/charts-data/morley' +import type { MorleyRow } from '@tanstack/charts-data/morley' import { createChartRuntime } from '@tanstack/charts' import type { BoxDatum, ChartSpecDatum } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { boxplotDefinition } from './tanstack' +import { createExampleChart } from './tanstack' -type Datum = ChartSpecDatum> +type Datum = ChartSpecDatum> describe('native boxplot definition', () => { it('derives Tukey summaries and raw-linked outliers inside boxY', () => { const scene = createChartRuntime().render( - boxplotDefinition(), + createExampleChart(), { width: 640, height: 400 }, ) const summaries = scene.points.flatMap(({ datum }) => diff --git a/benchmarks/conformance/cases/150-shadcn-bar-negative/example.tsx b/benchmarks/conformance/cases/150-shadcn-bar-negative/example.tsx index a0005f94..343ee81b 100644 --- a/benchmarks/conformance/cases/150-shadcn-bar-negative/example.tsx +++ b/benchmarks/conformance/cases/150-shadcn-bar-negative/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - text, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, text, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -14,9 +6,9 @@ import { scaleBand, scaleLinear } from 'd3-scale' import { shadcnColors, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { +export function createExampleChart() { const negativeRows = [ { month: 'January', desktop: 186, mobile: 0, tablet: 0 }, { month: 'February', desktop: 205, mobile: 0, tablet: 0 }, @@ -47,16 +39,30 @@ function createDefinition() { }, }), ] - return defineChart({ - marks, - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: false, + return defineChart( + { + marks, + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: false, + }, + y: { scale: scaleLinear, grid: true, axis: false }, + margin: { top: 24, right: 5, bottom: 24, left: 5 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear, grid: true, axis: false }, - margin: { top: 24, right: 5, bottom: 24, left: 5 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTheme() { return { @@ -86,70 +92,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -158,9 +113,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Negative

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/150-shadcn-bar-negative/styles.css b/benchmarks/conformance/cases/150-shadcn-bar-negative/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/150-shadcn-bar-negative/styles.css +++ b/benchmarks/conformance/cases/150-shadcn-bar-negative/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/150-shadcn-bar-negative/tanstack.ts b/benchmarks/conformance/cases/150-shadcn-bar-negative/tanstack.ts index 752d0e1a..8e19e84c 100644 --- a/benchmarks/conformance/cases/150-shadcn-bar-negative/tanstack.ts +++ b/benchmarks/conformance/cases/150-shadcn-bar-negative/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/151-shadcn-bar-stacked/example.tsx b/benchmarks/conformance/cases/151-shadcn-bar-stacked/example.tsx index 9dc63994..19f525bd 100644 --- a/benchmarks/conformance/cases/151-shadcn-bar-stacked/example.tsx +++ b/benchmarks/conformance/cases/151-shadcn-bar-stacked/example.tsx @@ -1,40 +1,46 @@ -import { useMemo } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors, shadcnSeriesRows } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnSeriesRows } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ order: twoSeries }), - radius: 4, - }), - ], - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) + return defineChart( + { + marks: [ + barY(rows, { + id: 'visitor-bars', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + layout: stack({ order: twoSeries }), + radius: 4, + }), + ], + x: shadcnXAxis(), + y: { scale: scaleLinear, grid: true, axis: false }, + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: { top: 5, right: 5, bottom: 35, left: 5 }, + theme: shadcnTheme(), + }, + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnXAxis() { return { @@ -77,70 +83,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - 27 - const headerAction = null - const legend = - const footer = ( - - ) return (
@@ -149,9 +104,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Bar Chart - Stacked + Legend

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/151-shadcn-bar-stacked/styles.css b/benchmarks/conformance/cases/151-shadcn-bar-stacked/styles.css index 7d46886a..f31115f0 100644 --- a/benchmarks/conformance/cases/151-shadcn-bar-stacked/styles.css +++ b/benchmarks/conformance/cases/151-shadcn-bar-stacked/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -121,31 +118,6 @@ height: 8px; border-radius: 2px; } -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +139,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +159,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/151-shadcn-bar-stacked/tanstack.ts b/benchmarks/conformance/cases/151-shadcn-bar-stacked/tanstack.ts index 67ebd8de..92cebf75 100644 --- a/benchmarks/conformance/cases/151-shadcn-bar-stacked/tanstack.ts +++ b/benchmarks/conformance/cases/151-shadcn-bar-stacked/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/152-shadcn-line-default/example.tsx b/benchmarks/conformance/cases/152-shadcn-line-default/example.tsx index 7e110793..d2a94a99 100644 --- a/benchmarks/conformance/cases/152-shadcn-line-default/example.tsx +++ b/benchmarks/conformance/cases/152-shadcn-line-default/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - d3Curve, - defineChart, - lineY, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { d3Curve, defineChart, lineY, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,48 +8,62 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveNatural - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -100,70 +106,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -172,9 +127,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/152-shadcn-line-default/styles.css b/benchmarks/conformance/cases/152-shadcn-line-default/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/152-shadcn-line-default/styles.css +++ b/benchmarks/conformance/cases/152-shadcn-line-default/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/152-shadcn-line-default/tanstack.ts b/benchmarks/conformance/cases/152-shadcn-line-default/tanstack.ts index 83d5fc7b..d8cbc36f 100644 --- a/benchmarks/conformance/cases/152-shadcn-line-default/tanstack.ts +++ b/benchmarks/conformance/cases/152-shadcn-line-default/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/example.tsx b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/example.tsx index 2ae15a38..82571584 100644 --- a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/example.tsx +++ b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { d3Curve, defineChart, dot, lineY, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,10 +14,10 @@ import { shadcnBrowsers, shadcnColors, type ShadcnBrowserDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const rows = shadcnBrowsers const curve = curveNatural const dotMarks = [ @@ -32,38 +29,52 @@ function createDefinition() { r: 5, }), ] - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnBrowserDatum[], { - id: 'visitor-line', - x: 'browser', - y: 'visitors', - curve: d3Curve(curve), - stroke: shadcnColors[1], - strokeWidth: 2, - }), - ...dotMarks, - ], - x: { scale: scalePoint, axis: false }, - y: { - scale: scaleLinear().domain([0, 300]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 75, 150, 225, 300], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnBrowserDatum[], { + id: 'visitor-line', + x: 'browser', + y: 'visitors', + curve: d3Curve(curve), + stroke: shadcnColors[1], + strokeWidth: 2, + }), + ...dotMarks, + ], + x: { scale: scalePoint, axis: false }, + y: { + scale: scaleLinear().domain([0, 300]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 75, 150, 225, 300], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: browserNames, + range: shadcnColors, + }, + margin: { top: 24, right: 24, bottom: 5, left: 24 }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: browserNames, - range: shadcnColors, - }, - margin: { top: 24, right: 24, bottom: 5, left: 24 }, - theme: shadcnTheme(), - })) + ) } function shadcnTheme() { return { @@ -93,70 +104,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -165,9 +125,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Dots Colors

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/styles.css b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/styles.css +++ b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/tanstack.ts b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/tanstack.ts index d0838e4d..1a66fcc4 100644 --- a/benchmarks/conformance/cases/153-shadcn-line-dots-colors/tanstack.ts +++ b/benchmarks/conformance/cases/153-shadcn-line-dots-colors/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/example.tsx b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/example.tsx index 0592a635..dd219114 100644 --- a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/example.tsx +++ b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/example.tsx @@ -1,4 +1,3 @@ -import { useMemo } from 'react' import { d3Curve, defineChart, @@ -6,8 +5,6 @@ import { lineY, text, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -18,10 +15,10 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveNatural const dotMarks = [ @@ -43,43 +40,57 @@ function createDefinition() { strokeWidth: 2, }), ] - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ...dotMarks, - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ...dotMarks, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: true && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: true && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -122,70 +133,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -194,9 +154,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Custom Dots

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/styles.css b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/styles.css +++ b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/tanstack.ts b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/tanstack.ts index 6c009c17..e2a5d585 100644 --- a/benchmarks/conformance/cases/154-shadcn-line-dots-custom/tanstack.ts +++ b/benchmarks/conformance/cases/154-shadcn-line-dots-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/155-shadcn-line-dots/example.tsx b/benchmarks/conformance/cases/155-shadcn-line-dots/example.tsx index 3127a7dd..3ff6da79 100644 --- a/benchmarks/conformance/cases/155-shadcn-line-dots/example.tsx +++ b/benchmarks/conformance/cases/155-shadcn-line-dots/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { d3Curve, defineChart, dot, lineY, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,10 +14,10 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveNatural const dotMarks = [ @@ -34,43 +31,57 @@ function createDefinition() { strokeWidth: 1, }), ] - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ...dotMarks, - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ...dotMarks, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -113,70 +124,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -185,9 +145,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Dots

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/155-shadcn-line-dots/styles.css b/benchmarks/conformance/cases/155-shadcn-line-dots/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/155-shadcn-line-dots/styles.css +++ b/benchmarks/conformance/cases/155-shadcn-line-dots/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/155-shadcn-line-dots/tanstack.ts b/benchmarks/conformance/cases/155-shadcn-line-dots/tanstack.ts index 64b93c57..263530bf 100644 --- a/benchmarks/conformance/cases/155-shadcn-line-dots/tanstack.ts +++ b/benchmarks/conformance/cases/155-shadcn-line-dots/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/156-shadcn-line-interactive/example.tsx b/benchmarks/conformance/cases/156-shadcn-line-interactive/example.tsx index eacaf275..3c8314f9 100644 --- a/benchmarks/conformance/cases/156-shadcn-line-interactive/example.tsx +++ b/benchmarks/conformance/cases/156-shadcn-line-interactive/example.tsx @@ -1,12 +1,5 @@ import { useMemo, useState } from 'react' -import { - d3Curve, - defineChart, - lineY, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { d3Curve, defineChart, lineY, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,8 +8,8 @@ import { curveMonotoneX } from 'd3-shape' import { shadcnColors, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' -import interactiveAreaData from '@charts-poc/demo-data/shadcn-area-interactive-data' +} from '@tanstack/charts-data/shadcn' +import interactiveAreaData from '@tanstack/charts-data/shadcn-area-interactive-data' import './styles.css' type InteractiveSeries = 'desktop' | 'mobile' const twoSeries = ['desktop', 'mobile'] as const @@ -33,59 +26,76 @@ const interactiveBarRows: readonly ShadcnMonthDatum[] = interactiveAreaRows.map( tablet: 0, }), ) -function createDefinition(activeSeries: InteractiveSeries = 'desktop') { - return defineChart(({ width }) => ({ - marks: [ - lineY(interactiveBarRows, { - id: 'daily-line', - x: 'month', - y: (row) => row[activeSeries], - z: () => activeSeries, - key: 'month', - curve: d3Curve(curveMonotoneX), - stroke: activeSeries === 'desktop' ? shadcnColors[0] : shadcnColors[1], - strokeWidth: 2, - }), - ], - x: { - scale: scalePoint, - axis: { - line: false, - ticks: { - values: [ - '2024-04-10', - '2024-04-21', - '2024-05-02', - '2024-05-13', - '2024-05-25', - '2024-06-05', - '2024-06-16', - '2024-06-29', - ], - size: 0, - padding: 10, - format: formatMonthDay, +export function createExampleChart( + activeSeries: InteractiveSeries = 'desktop', +) { + return defineChart( + ({ width }) => ({ + marks: [ + lineY(interactiveBarRows, { + id: 'daily-line', + x: 'month', + y: (row) => row[activeSeries], + z: () => activeSeries, + key: 'month', + curve: d3Curve(curveMonotoneX), + stroke: + activeSeries === 'desktop' ? shadcnColors[0] : shadcnColors[1], + strokeWidth: 2, + }), + ], + x: { + scale: scalePoint, + axis: { + line: false, + ticks: { + values: [ + '2024-04-10', + '2024-04-21', + '2024-05-02', + '2024-05-13', + '2024-05-25', + '2024-06-05', + '2024-06-16', + '2024-06-29', + ], + size: 0, + padding: 10, + format: formatMonthDay, + }, }, }, - }, - y: { - scale: scaleLinear().domain([0, 600]), - grid: true, - axis: { - line: false, - ticks: { values: [0, 150, 300, 450, 600], size: 0 }, - tickLabels: false, + y: { + scale: scaleLinear().domain([0, 600]), + grid: true, + axis: { + line: false, + ticks: { values: [0, 150, 300, 450, 600], size: 0 }, + tickLabels: false, + }, + }, + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: { + top: 5, + right: width < 400 ? 24 : 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { - top: 5, - right: width < 400 ? 24 : 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function formatMonthDay(value: string) { return new Intl.DateTimeFormat('en-US', { @@ -122,50 +132,11 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart( - activeSeries: InteractiveSeries = 'desktop', -) { - return defineChart(createDefinition(activeSeries), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number @@ -176,22 +147,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) { () => createExampleChart(activeSeries), [activeSeries], ) - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = 250 - const headerAction = ( - - ) - const legend = null - const footer = null return (
@@ -200,9 +158,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Interactive

Showing total visitors for the last 3 months

- {headerAction ? ( -
{headerAction}
- ) : null} +
+ +
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/156-shadcn-line-interactive/styles.css b/benchmarks/conformance/cases/156-shadcn-line-interactive/styles.css index 7d46886a..50913391 100644 --- a/benchmarks/conformance/cases/156-shadcn-line-interactive/styles.css +++ b/benchmarks/conformance/cases/156-shadcn-line-interactive/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,155 +113,6 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} .sc-interactive-line { gap: 0; padding: 0; @@ -364,71 +138,9 @@ .sc-interactive-line .sc-card-content { padding: 43px 24px 0; } -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} .sc-card-action { margin-left: auto; } -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} .sc-bar-metric { display: grid; width: 168px; diff --git a/benchmarks/conformance/cases/156-shadcn-line-interactive/tanstack.ts b/benchmarks/conformance/cases/156-shadcn-line-interactive/tanstack.ts index 1d0523e7..9ac7b2b5 100644 --- a/benchmarks/conformance/cases/156-shadcn-line-interactive/tanstack.ts +++ b/benchmarks/conformance/cases/156-shadcn-line-interactive/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/157-shadcn-line-label-custom/example.tsx b/benchmarks/conformance/cases/157-shadcn-line-label-custom/example.tsx index 64d2601f..55b49bc2 100644 --- a/benchmarks/conformance/cases/157-shadcn-line-label-custom/example.tsx +++ b/benchmarks/conformance/cases/157-shadcn-line-label-custom/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { d3Curve, defineChart, lineY, text, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,10 +14,10 @@ import { shadcnBrowsers, shadcnColors, type ShadcnBrowserDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const rows = shadcnBrowsers const curve = curveNatural const labelMarks = [ @@ -34,38 +31,52 @@ function createDefinition() { fontSize: 12, }), ] - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnBrowserDatum[], { - id: 'visitor-line', - x: 'browser', - y: 'visitors', - curve: d3Curve(curve), - stroke: shadcnColors[1], - strokeWidth: 2, - }), - ...labelMarks, - ], - x: { scale: scalePoint, axis: false }, - y: { - scale: scaleLinear().domain([0, 300]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 75, 150, 225, 300], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnBrowserDatum[], { + id: 'visitor-line', + x: 'browser', + y: 'visitors', + curve: d3Curve(curve), + stroke: shadcnColors[1], + strokeWidth: 2, + }), + ...labelMarks, + ], + x: { scale: scalePoint, axis: false }, + y: { + scale: scaleLinear().domain([0, 300]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 75, 150, 225, 300], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: browserNames, + range: shadcnColors, + }, + margin: { top: 24, right: 24, bottom: 5, left: 24 }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: browserNames, - range: shadcnColors, - }, - margin: { top: 24, right: 24, bottom: 5, left: 24 }, - theme: shadcnTheme(), - })) + ) } function shadcnTheme() { return { @@ -95,70 +106,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -167,9 +127,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Custom Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/157-shadcn-line-label-custom/styles.css b/benchmarks/conformance/cases/157-shadcn-line-label-custom/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/157-shadcn-line-label-custom/styles.css +++ b/benchmarks/conformance/cases/157-shadcn-line-label-custom/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/157-shadcn-line-label-custom/tanstack.ts b/benchmarks/conformance/cases/157-shadcn-line-label-custom/tanstack.ts index 09b64e7e..de90f571 100644 --- a/benchmarks/conformance/cases/157-shadcn-line-label-custom/tanstack.ts +++ b/benchmarks/conformance/cases/157-shadcn-line-label-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/158-shadcn-line-label/example.tsx b/benchmarks/conformance/cases/158-shadcn-line-label/example.tsx index be8b0515..98126500 100644 --- a/benchmarks/conformance/cases/158-shadcn-line-label/example.tsx +++ b/benchmarks/conformance/cases/158-shadcn-line-label/example.tsx @@ -1,12 +1,9 @@ -import { useMemo } from 'react' import { d3Curve, defineChart, lineY, text, type ChartPoint, - type ChartValue, - type DomChartDefinition, } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -17,10 +14,10 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveNatural const labelMarks = [ @@ -34,43 +31,57 @@ function createDefinition() { fontSize: 12, }), ] - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ...labelMarks, - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ...labelMarks, + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 24, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 24, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -113,70 +124,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -185,9 +145,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/158-shadcn-line-label/styles.css b/benchmarks/conformance/cases/158-shadcn-line-label/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/158-shadcn-line-label/styles.css +++ b/benchmarks/conformance/cases/158-shadcn-line-label/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/158-shadcn-line-label/tanstack.ts b/benchmarks/conformance/cases/158-shadcn-line-label/tanstack.ts index f2c4b3f1..66659291 100644 --- a/benchmarks/conformance/cases/158-shadcn-line-label/tanstack.ts +++ b/benchmarks/conformance/cases/158-shadcn-line-label/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/159-shadcn-line-linear/example.tsx b/benchmarks/conformance/cases/159-shadcn-line-linear/example.tsx index ca115127..3b016950 100644 --- a/benchmarks/conformance/cases/159-shadcn-line-linear/example.tsx +++ b/benchmarks/conformance/cases/159-shadcn-line-linear/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - d3Curve, - defineChart, - lineY, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { d3Curve, defineChart, lineY, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,48 +8,62 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveLinear - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -100,70 +106,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -172,9 +127,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Linear

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/159-shadcn-line-linear/styles.css b/benchmarks/conformance/cases/159-shadcn-line-linear/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/159-shadcn-line-linear/styles.css +++ b/benchmarks/conformance/cases/159-shadcn-line-linear/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/159-shadcn-line-linear/tanstack.ts b/benchmarks/conformance/cases/159-shadcn-line-linear/tanstack.ts index a2c1a9cf..5cc7da0d 100644 --- a/benchmarks/conformance/cases/159-shadcn-line-linear/tanstack.ts +++ b/benchmarks/conformance/cases/159-shadcn-line-linear/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/16-lollipop/example.tsx b/benchmarks/conformance/cases/16-lollipop/example.tsx index 9fab3cca..2258bcfe 100644 --- a/benchmarks/conformance/cases/16-lollipop/example.tsx +++ b/benchmarks/conformance/cases/16-lollipop/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { defineChart, dot, link } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' @@ -10,64 +10,53 @@ const percent = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1, }) -export const definition = (_input: ExampleOptions) => { - return defineChart({ - marks: [ - link(alphabet, { - x1: 'letter', - y1: () => 0, - x2: 'letter', - y2: 'frequency', - stroke: '#94a3b8', - strokeWidth: 1.5, - }), - dot(alphabet, { - x: 'letter', - y: 'frequency', - fill: '#2563eb', - r: 4, - }), - ], - x: { - scale: () => scaleBand().padding(0.3), +export const createExampleChart = () => { + return defineChart( + { + marks: [ + link(alphabet, { + x1: 'letter', + y1: () => 0, + x2: 'letter', + y2: 'frequency', + stroke: '#94a3b8', + strokeWidth: 1.5, + }), + dot(alphabet, { + x: 'letter', + y: 'frequency', + fill: '#2563eb', + r: 4, + }), + ], + x: { + scale: () => scaleBand().padding(0.3), + }, + y: { + scale: scaleLinear, + grid: true, + axis: { + ticks: { format: (value) => percent.format(value) }, + label: 'Frequency', + }, + }, }, - y: { - scale: scaleLinear, - grid: true, - axis: { - ticks: { format: (value) => percent.format(value) }, - label: 'Frequency', + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.letter} · ${percent.format(datum.frequency)} frequency`, + }, }, }, - }) -} -export interface ExampleOptions { - width: number - height: number - revision: number - preview?: boolean + ) } export const exampleAriaLabel = 'Ranked lollipop chart' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.letter} · ${percent.format(datum.frequency)} frequency`, - }, - }, - }) - -export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, - preview: false, -}) +export const chart = createExampleChart() export default function Example() { return diff --git a/benchmarks/conformance/cases/16-lollipop/plot.ts b/benchmarks/conformance/cases/16-lollipop/plot.ts index 0f74b6cf..8f0614b6 100644 --- a/benchmarks/conformance/cases/16-lollipop/plot.ts +++ b/benchmarks/conformance/cases/16-lollipop/plot.ts @@ -1,4 +1,4 @@ -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/160-shadcn-line-multiple/example.tsx b/benchmarks/conformance/cases/160-shadcn-line-multiple/example.tsx index 4f091f34..3780eb59 100644 --- a/benchmarks/conformance/cases/160-shadcn-line-multiple/example.tsx +++ b/benchmarks/conformance/cases/160-shadcn-line-multiple/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - d3Curve, - defineChart, - lineY, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { d3Curve, defineChart, lineY, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,50 +8,64 @@ import { shadcnColors, shadcnSeriesRows, type ShadcnSeriesDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') const curve = curveMonotoneX - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-lines', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - curve: d3Curve(curve), - strokeWidth: 2, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnSeriesDatum[], { + id: 'visitor-lines', + x: 'month', + y: 'value', + z: 'series', + color: 'series', + key: (row) => `${row.month}:${row.series}`, + curve: d3Curve(curve), + strokeWidth: 2, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -102,70 +108,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -174,9 +129,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Multiple

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/160-shadcn-line-multiple/styles.css b/benchmarks/conformance/cases/160-shadcn-line-multiple/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/160-shadcn-line-multiple/styles.css +++ b/benchmarks/conformance/cases/160-shadcn-line-multiple/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/160-shadcn-line-multiple/tanstack.ts b/benchmarks/conformance/cases/160-shadcn-line-multiple/tanstack.ts index b7b4531c..c7315f2e 100644 --- a/benchmarks/conformance/cases/160-shadcn-line-multiple/tanstack.ts +++ b/benchmarks/conformance/cases/160-shadcn-line-multiple/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/161-shadcn-line-step/example.tsx b/benchmarks/conformance/cases/161-shadcn-line-step/example.tsx index 8c04bed4..ecfa7333 100644 --- a/benchmarks/conformance/cases/161-shadcn-line-step/example.tsx +++ b/benchmarks/conformance/cases/161-shadcn-line-step/example.tsx @@ -1,12 +1,4 @@ -import { useMemo } from 'react' -import { - d3Curve, - defineChart, - lineY, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { d3Curve, defineChart, lineY, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -16,48 +8,62 @@ import { shadcnColors, shadcnMonths, type ShadcnMonthDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnMonths const curve = curveStep - return defineChart(({ width }) => ({ - marks: [ - lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, 320]), - grid: true, - axis: { - line: false, - ticks: { - values: [0, 80, 160, 240, 320], - size: 0, + return defineChart( + ({ width }) => ({ + marks: [ + lineY(rows as readonly ShadcnMonthDatum[], { + id: 'visitor-line', + x: 'month', + y: 'desktop', + curve: d3Curve(curve), + stroke: shadcnColors[0], + strokeWidth: 2, + }), + ], + x: shadcnPointXAxis(), + y: { + scale: scaleLinear().domain([0, 320]), + grid: true, + axis: { + line: false, + ticks: { + values: [0, 80, 160, 240, 320], + size: 0, + }, + tickLabels: false, }, - tickLabels: false, + }, + color: { + domain: twoSeries, + range: shadcnColors.slice(0, 2), + }, + margin: { + top: false && width < 400 ? 16 : 8, + right: 12, + bottom: 35, + left: 12, + }, + theme: shadcnTheme(), + }), + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), }, }, - color: { - domain: twoSeries, - range: shadcnColors.slice(0, 2), - }, - margin: { - top: false && width < 400 ? 16 : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) + ) } function shadcnPointXAxis() { return { @@ -100,70 +106,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { })), } } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -172,9 +127,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Line Chart - Step

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} +
+ +
) diff --git a/benchmarks/conformance/cases/161-shadcn-line-step/styles.css b/benchmarks/conformance/cases/161-shadcn-line-step/styles.css index 7d46886a..a768f3d8 100644 --- a/benchmarks/conformance/cases/161-shadcn-line-step/styles.css +++ b/benchmarks/conformance/cases/161-shadcn-line-step/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,50 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} .sc-trend { display: flex; align-items: center; @@ -167,9 +120,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +140,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/161-shadcn-line-step/tanstack.ts b/benchmarks/conformance/cases/161-shadcn-line-step/tanstack.ts index 3ec224fa..fd5b71b3 100644 --- a/benchmarks/conformance/cases/161-shadcn-line-step/tanstack.ts +++ b/benchmarks/conformance/cases/161-shadcn-line-step/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/example.tsx b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/example.tsx index 6905967d..3c797295 100644 --- a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/example.tsx +++ b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/example.tsx @@ -1,19 +1,13 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -39,18 +33,32 @@ function createDefinition() { strokeWidth: 5, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -81,70 +89,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -153,9 +110,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Donut Active

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/styles.css b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/styles.css +++ b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/tanstack.ts b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/tanstack.ts index 21731977..c9692f21 100644 --- a/benchmarks/conformance/cases/162-shadcn-pie-donut-active/tanstack.ts +++ b/benchmarks/conformance/cases/162-shadcn-pie-donut-active/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/163-shadcn-pie-donut/example.tsx b/benchmarks/conformance/cases/163-shadcn-pie-donut/example.tsx index 8c774192..4077c7a1 100644 --- a/benchmarks/conformance/cases/163-shadcn-pie-donut/example.tsx +++ b/benchmarks/conformance/cases/163-shadcn-pie-donut/example.tsx @@ -1,19 +1,13 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -30,18 +24,32 @@ function createDefinition() { strokeWidth: separator, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -72,70 +80,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -144,9 +101,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Donut

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/163-shadcn-pie-donut/styles.css b/benchmarks/conformance/cases/163-shadcn-pie-donut/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/163-shadcn-pie-donut/styles.css +++ b/benchmarks/conformance/cases/163-shadcn-pie-donut/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/163-shadcn-pie-donut/tanstack.ts b/benchmarks/conformance/cases/163-shadcn-pie-donut/tanstack.ts index 05f8bc10..1bf463fc 100644 --- a/benchmarks/conformance/cases/163-shadcn-pie-donut/tanstack.ts +++ b/benchmarks/conformance/cases/163-shadcn-pie-donut/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/164-shadcn-pie-interactive/example.tsx b/benchmarks/conformance/cases/164-shadcn-pie-interactive/example.tsx index ab0d6246..1fc5cbe5 100644 --- a/benchmarks/conformance/cases/164-shadcn-pie-interactive/example.tsx +++ b/benchmarks/conformance/cases/164-shadcn-pie-interactive/example.tsx @@ -1,10 +1,5 @@ import { useMemo, useState } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -19,7 +14,7 @@ import { scaleLinear } from 'd3-scale' import { shadcnColors, type ShadcnBrowserDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const interactivePieRows: readonly ShadcnBrowserDatum[] = [ { browser: 'january', visitors: 186 }, @@ -28,7 +23,7 @@ const interactivePieRows: readonly ShadcnBrowserDatum[] = [ { browser: 'april', visitors: 173 }, { browser: 'may', visitors: 209 }, ] -function createDefinition(activeMonth = 'january') { +export function createExampleChart(activeMonth = 'january') { const arcs = pie(interactivePieRows, { value: 'visitors', startAngle: Math.PI / 2, @@ -41,79 +36,96 @@ function createDefinition(activeMonth = 'january') { const activeRow = interactivePieRows[activeIndex]! const active = arcs.filter((row) => row.browser === activeRow.browser) const activeColor = shadcnColors[activeIndex]! - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(arcs, { - id: 'month-slices', - key: 'browser', - innerRadius: 60, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - radialArc(active, { - id: 'active-month', - key: 'browser', - innerRadius: 60, - outerRadius: ({ radius }) => radius + 10, - fill: activeColor, - stroke: 'var(--background)', - strokeWidth: 5, - }), - radialArc(active, { - id: 'active-month-ring', - key: 'browser', - innerRadius: ({ radius }) => radius + 12, - outerRadius: ({ radius }) => radius + 25, - fill: activeColor, - stroke: 'var(--background)', - strokeWidth: 3, - }), - radialText( - [ + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks: [ + radialArc(arcs, { + id: 'month-slices', + key: 'browser', + innerRadius: 60, + color: 'browser', + stroke: 'var(--background)', + strokeWidth: 1, + }), + radialArc(active, { + id: 'active-month', + key: 'browser', + innerRadius: 60, + outerRadius: ({ radius }) => radius + 10, + fill: activeColor, + stroke: 'var(--background)', + strokeWidth: 5, + }), + radialArc(active, { + id: 'active-month-ring', + key: 'browser', + innerRadius: ({ radius }) => radius + 12, + outerRadius: ({ radius }) => radius + 25, + fill: activeColor, + stroke: 'var(--background)', + strokeWidth: 3, + }), + radialText( + [ + { + id: 'total', + angle: 0, + radius: 0, + text: String(activeRow.visitors), + }, + ], { - id: 'total', - angle: 0, - radius: 0, - text: String(activeRow.visitors), + id: 'active-total', + angle: 'angle', + radius: 'radius', + key: 'id', + text: 'text', + dy: -5, + fill: 'var(--foreground)', + fontSize: 30, + fontWeight: 700, }, - ], - { - id: 'active-total', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: -5, - fill: 'var(--foreground)', - fontSize: 30, - fontWeight: 700, - }, - ), - radialText([{ id: 'label', angle: 0, radius: 0, text: 'Visitors' }], { - id: 'active-label', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: 20, - fill: 'var(--muted-foreground)', - fontSize: 12, - }), - ], - }), - ], - color: { - domain: interactivePieRows.map((row) => row.browser), - range: shadcnColors, + ), + radialText( + [{ id: 'label', angle: 0, radius: 0, text: 'Visitors' }], + { + id: 'active-label', + angle: 'angle', + radius: 'radius', + key: 'id', + text: 'text', + dy: 20, + fill: 'var(--muted-foreground)', + fontSize: 12, + }, + ), + ], + }), + ], + color: { + domain: interactivePieRows.map((row) => row.browser), + range: shadcnColors, + }, + margin: 0, }, - margin: 0, - }) + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { const point = points.find((candidate) => browserMetric(candidate.datum)) @@ -144,48 +156,11 @@ function browserMetric(datum: unknown) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart(activeMonth: string = 'january') { - return defineChart(createDefinition(activeMonth), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number @@ -196,30 +171,9 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) { () => createExampleChart(activeMonth), [activeMonth], ) - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(300, contentWidth) const chartHeight = chartWidth - const headerAction = ( - ({ - value: row.browser, - label: titleCase(row.browser), - swatch: shadcnColors[index], - }))} - /> - ) - const legend = null - const footer = null return (
@@ -228,9 +182,17 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Interactive

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null} +
+ ({ + value: row.browser, + label: titleCase(row.browser), + swatch: shadcnColors[index], + }))} + /> +
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} ) diff --git a/benchmarks/conformance/cases/164-shadcn-pie-interactive/styles.css b/benchmarks/conformance/cases/164-shadcn-pie-interactive/styles.css index 7d46886a..38b00bb1 100644 --- a/benchmarks/conformance/cases/164-shadcn-pie-interactive/styles.css +++ b/benchmarks/conformance/cases/164-shadcn-pie-interactive/styles.css @@ -90,86 +90,14 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; text-align: center; } -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,180 +118,6 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} .sc-interactive-pie .sc-card-header { display: flex; align-items: flex-start; @@ -429,33 +183,3 @@ flex: none; border-radius: 3px; } -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/164-shadcn-pie-interactive/tanstack.ts b/benchmarks/conformance/cases/164-shadcn-pie-interactive/tanstack.ts index aa41c8aa..b31367f1 100644 --- a/benchmarks/conformance/cases/164-shadcn-pie-interactive/tanstack.ts +++ b/benchmarks/conformance/cases/164-shadcn-pie-interactive/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/example.tsx b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/example.tsx index 8fad7cbc..46af83db 100644 --- a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/example.tsx +++ b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -16,10 +10,10 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -48,18 +42,32 @@ function createDefinition() { fontWeight: undefined, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -90,70 +98,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -162,9 +119,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Custom Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/styles.css b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/styles.css +++ b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/tanstack.ts b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/tanstack.ts index 660c5d9e..127900b2 100644 --- a/benchmarks/conformance/cases/165-shadcn-pie-label-custom/tanstack.ts +++ b/benchmarks/conformance/cases/165-shadcn-pie-label-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/166-shadcn-pie-label-list/example.tsx b/benchmarks/conformance/cases/166-shadcn-pie-label-list/example.tsx index 46c0afc9..04651724 100644 --- a/benchmarks/conformance/cases/166-shadcn-pie-label-list/example.tsx +++ b/benchmarks/conformance/cases/166-shadcn-pie-label-list/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -16,10 +10,10 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -48,18 +42,32 @@ function createDefinition() { fontWeight: 400, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -90,70 +98,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -162,9 +119,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Label List

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/166-shadcn-pie-label-list/styles.css b/benchmarks/conformance/cases/166-shadcn-pie-label-list/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/166-shadcn-pie-label-list/styles.css +++ b/benchmarks/conformance/cases/166-shadcn-pie-label-list/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/166-shadcn-pie-label-list/tanstack.ts b/benchmarks/conformance/cases/166-shadcn-pie-label-list/tanstack.ts index 411cab41..811aa476 100644 --- a/benchmarks/conformance/cases/166-shadcn-pie-label-list/tanstack.ts +++ b/benchmarks/conformance/cases/166-shadcn-pie-label-list/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/167-shadcn-pie-label/example.tsx b/benchmarks/conformance/cases/167-shadcn-pie-label/example.tsx index decb7c10..df36d4e0 100644 --- a/benchmarks/conformance/cases/167-shadcn-pie-label/example.tsx +++ b/benchmarks/conformance/cases/167-shadcn-pie-label/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -17,10 +11,10 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -58,18 +52,32 @@ function createDefinition() { fontWeight: undefined, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -100,70 +108,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -172,9 +129,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/167-shadcn-pie-label/styles.css b/benchmarks/conformance/cases/167-shadcn-pie-label/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/167-shadcn-pie-label/styles.css +++ b/benchmarks/conformance/cases/167-shadcn-pie-label/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/167-shadcn-pie-label/tanstack.ts b/benchmarks/conformance/cases/167-shadcn-pie-label/tanstack.ts index f1dc1e9e..a67c4d9a 100644 --- a/benchmarks/conformance/cases/167-shadcn-pie-label/tanstack.ts +++ b/benchmarks/conformance/cases/167-shadcn-pie-label/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/168-shadcn-pie-legend/example.tsx b/benchmarks/conformance/cases/168-shadcn-pie-legend/example.tsx index 340ff746..6c7007ff 100644 --- a/benchmarks/conformance/cases/168-shadcn-pie-legend/example.tsx +++ b/benchmarks/conformance/cases/168-shadcn-pie-legend/example.tsx @@ -1,19 +1,13 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -30,18 +24,32 @@ function createDefinition() { strokeWidth: separator, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -72,68 +80,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = - const footer = null return (
@@ -142,9 +101,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Legend

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ? ( -
{footer}
- ) : null} ) diff --git a/benchmarks/conformance/cases/168-shadcn-pie-legend/styles.css b/benchmarks/conformance/cases/168-shadcn-pie-legend/styles.css index 7d46886a..cc9b9905 100644 --- a/benchmarks/conformance/cases/168-shadcn-pie-legend/styles.css +++ b/benchmarks/conformance/cases/168-shadcn-pie-legend/styles.css @@ -90,18 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} .sc-chart-footer { display: flex; flex-wrap: wrap; @@ -121,55 +109,14 @@ height: 8px; border-radius: 2px; } -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; text-align: center; } -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +137,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/168-shadcn-pie-legend/tanstack.ts b/benchmarks/conformance/cases/168-shadcn-pie-legend/tanstack.ts index 67a884d3..521097cb 100644 --- a/benchmarks/conformance/cases/168-shadcn-pie-legend/tanstack.ts +++ b/benchmarks/conformance/cases/168-shadcn-pie-legend/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/example.tsx b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/example.tsx index 1f402121..ae539697 100644 --- a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/example.tsx +++ b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/example.tsx @@ -1,19 +1,13 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -30,18 +24,32 @@ function createDefinition() { strokeWidth: separator, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -72,70 +80,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -144,9 +101,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Separator None

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/styles.css b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/styles.css +++ b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/tanstack.ts b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/tanstack.ts index a982baee..5ec9f2ef 100644 --- a/benchmarks/conformance/cases/169-shadcn-pie-separator-none/tanstack.ts +++ b/benchmarks/conformance/cases/169-shadcn-pie-separator-none/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/17-dumbbell/example.tsx b/benchmarks/conformance/cases/17-dumbbell/example.tsx index 97064057..4b306f11 100644 --- a/benchmarks/conformance/cases/17-dumbbell/example.tsx +++ b/benchmarks/conformance/cases/17-dumbbell/example.tsx @@ -1,73 +1,67 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import { defineChart, dot, link } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = citywages.slice(input.revision * 4, input.revision * 4 + 8) - return defineChart({ - marks: [ - link(rows, { - x1: 'R90_10_1980', - y1: 'nyt_display', - x2: 'R90_10_2015', - y2: 'nyt_display', - stroke: '#94a3b8', - strokeWidth: 2, - }), - dot(rows, { - x: 'R90_10_1980', - y: 'nyt_display', - fill: '#2563eb', - r: 4, - }), - dot(rows, { - x: 'R90_10_2015', - y: 'nyt_display', - fill: '#f97316', - r: 4, - }), - ], - x: { - scale: scaleLinear, - grid: true, - axis: { label: '90th/10th percentile wage ratio' }, + return defineChart( + { + marks: [ + link(rows, { + x1: 'R90_10_1980', + y1: 'nyt_display', + x2: 'R90_10_2015', + y2: 'nyt_display', + stroke: '#94a3b8', + strokeWidth: 2, + }), + dot(rows, { + x: 'R90_10_1980', + y: 'nyt_display', + fill: '#2563eb', + r: 4, + }), + dot(rows, { + x: 'R90_10_2015', + y: 'nyt_display', + fill: '#f97316', + r: 4, + }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: '90th/10th percentile wage ratio' }, + }, + y: { + scale: () => scaleBand().padding(0.22), + }, }, - y: { - scale: () => scaleBand().padding(0.22), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.nyt_display} · 1980 ${datum.R90_10_1980.toLocaleString( + 'en-US', + )} · 2015 ${datum.R90_10_2015.toLocaleString('en-US')}`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Metropolitan wage inequality in 1980 and 2015' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.nyt_display} · 1980 ${datum.R90_10_1980.toLocaleString( - 'en-US', - )} · 2015 ${datum.R90_10_2015.toLocaleString('en-US')}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/17-dumbbell/plot.ts b/benchmarks/conformance/cases/17-dumbbell/plot.ts index 2373e0bd..f472bc63 100644 --- a/benchmarks/conformance/cases/17-dumbbell/plot.ts +++ b/benchmarks/conformance/cases/17-dumbbell/plot.ts @@ -1,4 +1,4 @@ -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/170-shadcn-pie-simple/example.tsx b/benchmarks/conformance/cases/170-shadcn-pie-simple/example.tsx index 14c5fe72..8bcc6c2a 100644 --- a/benchmarks/conformance/cases/170-shadcn-pie-simple/example.tsx +++ b/benchmarks/conformance/cases/170-shadcn-pie-simple/example.tsx @@ -1,19 +1,13 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const arcs = pie(shadcnBrowsers, { value: 'visitors', startAngle: Math.PI / 2, @@ -30,18 +24,32 @@ function createDefinition() { strokeWidth: separator, }), ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.78, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks, + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -72,70 +80,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -144,9 +101,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/170-shadcn-pie-simple/styles.css b/benchmarks/conformance/cases/170-shadcn-pie-simple/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/170-shadcn-pie-simple/styles.css +++ b/benchmarks/conformance/cases/170-shadcn-pie-simple/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/170-shadcn-pie-simple/tanstack.ts b/benchmarks/conformance/cases/170-shadcn-pie-simple/tanstack.ts index 9ab8569e..b8b06cbd 100644 --- a/benchmarks/conformance/cases/170-shadcn-pie-simple/tanstack.ts +++ b/benchmarks/conformance/cases/170-shadcn-pie-simple/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/171-shadcn-pie-stacked/example.tsx b/benchmarks/conformance/cases/171-shadcn-pie-stacked/example.tsx index 0438763c..fe4bcca7 100644 --- a/benchmarks/conformance/cases/171-shadcn-pie-stacked/example.tsx +++ b/benchmarks/conformance/cases/171-shadcn-pie-stacked/example.tsx @@ -1,21 +1,12 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, polar, radialArc } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' -import { shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { - return buildStackedPieDefinition() -} -function buildStackedPieDefinition() { +export function createExampleChart() { const desktopRows = [186, 305, 237, 173, 209].map((visitors, index) => ({ browser: ['january', 'february', 'march', 'april', 'may'][index]!, visitors, @@ -35,36 +26,50 @@ function buildStackedPieDefinition() { endAngle: (-Math.PI * 3) / 2, }) const months = desktopRows.map((row) => row.browser) - return defineChart({ - marks: [ - polar({ - radiusRatio: 1, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(desktopArcs, { - id: 'desktop-slices', - key: 'browser', - outerRadius: 60, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - radialArc(mobileArcs, { - id: 'mobile-slices', - key: 'browser', - innerRadius: 70, - outerRadius: 90, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: months, range: shadcnColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 1, + angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks: [ + radialArc(desktopArcs, { + id: 'desktop-slices', + key: 'browser', + outerRadius: 60, + color: 'browser', + stroke: 'var(--background)', + strokeWidth: 1, + }), + radialArc(mobileArcs, { + id: 'mobile-slices', + key: 'browser', + innerRadius: 70, + outerRadius: 90, + color: 'browser', + stroke: 'var(--background)', + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: months, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) @@ -95,70 +100,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -167,9 +121,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Pie Chart - Stacked

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/171-shadcn-pie-stacked/styles.css b/benchmarks/conformance/cases/171-shadcn-pie-stacked/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/171-shadcn-pie-stacked/styles.css +++ b/benchmarks/conformance/cases/171-shadcn-pie-stacked/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/171-shadcn-pie-stacked/tanstack.ts b/benchmarks/conformance/cases/171-shadcn-pie-stacked/tanstack.ts index bc9df805..489e1823 100644 --- a/benchmarks/conformance/cases/171-shadcn-pie-stacked/tanstack.ts +++ b/benchmarks/conformance/cases/171-shadcn-pie-stacked/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/172-shadcn-radar-default/example.tsx b/benchmarks/conformance/cases/172-shadcn-radar-default/example.tsx index 8f82f491..880e9aec 100644 --- a/benchmarks/conformance/cases/172-shadcn-radar-default/example.tsx +++ b/benchmarks/conformance/cases/172-shadcn-radar-default/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault const months = rows.map((row) => row.month) const radiusMax = 320 @@ -34,8 +28,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -47,35 +39,48 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -98,68 +103,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -168,9 +124,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/172-shadcn-radar-default/styles.css b/benchmarks/conformance/cases/172-shadcn-radar-default/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/172-shadcn-radar-default/styles.css +++ b/benchmarks/conformance/cases/172-shadcn-radar-default/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/172-shadcn-radar-default/tanstack.ts b/benchmarks/conformance/cases/172-shadcn-radar-default/tanstack.ts index 8de58daa..1efcee15 100644 --- a/benchmarks/conformance/cases/172-shadcn-radar-default/tanstack.ts +++ b/benchmarks/conformance/cases/172-shadcn-radar-default/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/173-shadcn-radar-dots/example.tsx b/benchmarks/conformance/cases/173-shadcn-radar-dots/example.tsx index 97969703..93004de8 100644 --- a/benchmarks/conformance/cases/173-shadcn-radar-dots/example.tsx +++ b/benchmarks/conformance/cases/173-shadcn-radar-dots/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -18,10 +12,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault const months = rows.map((row) => row.month) const radiusMax = 320 @@ -35,8 +29,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -48,44 +40,57 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialDot(rows, { - id: 'radar-dots', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - r: 4, - fill: shadcnColors[0], - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialDot(rows, { + id: 'radar-dots', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + r: 4, + fill: shadcnColors[0], + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -108,68 +113,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -178,9 +134,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Dots

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/173-shadcn-radar-dots/styles.css b/benchmarks/conformance/cases/173-shadcn-radar-dots/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/173-shadcn-radar-dots/styles.css +++ b/benchmarks/conformance/cases/173-shadcn-radar-dots/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/173-shadcn-radar-dots/tanstack.ts b/benchmarks/conformance/cases/173-shadcn-radar-dots/tanstack.ts index bf86d2f8..ca9cc494 100644 --- a/benchmarks/conformance/cases/173-shadcn-radar-dots/tanstack.ts +++ b/benchmarks/conformance/cases/173-shadcn-radar-dots/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/example.tsx b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/example.tsx index 551025ce..43d9a67d 100644 --- a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/example.tsx +++ b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarFilled } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarFilled } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarFilled const months = rows.map((row) => row.month) const radiusMax = 300 @@ -35,7 +29,6 @@ function createDefinition() { stroke: 'transparent', strokeOpacity: 0, ...{ fill: shadcnColors[0], fillOpacity: 0.2 }, - ...{}, }), angleGrid({ values: months, @@ -47,35 +40,48 @@ function createDefinition() { strokeOpacity: 0, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.5, - stroke: shadcnColors[0], - strokeOpacity: 0, - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.5, + stroke: shadcnColors[0], + strokeOpacity: 0, + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -98,68 +104,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -168,9 +125,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid Circle Filled

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/styles.css b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/styles.css +++ b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/tanstack.ts b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/tanstack.ts index 73704643..0a49fd4b 100644 --- a/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/tanstack.ts +++ b/benchmarks/conformance/cases/174-shadcn-radar-grid-circle-fill/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/example.tsx b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/example.tsx index b17e6d3f..36b4e304 100644 --- a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/example.tsx +++ b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -18,10 +12,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault.map((row) => row.month === 'April' ? { ...row, desktop: 203 } : row, ) @@ -37,8 +31,6 @@ function createDefinition() { shape: 'circle', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -50,44 +42,57 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialDot(rows, { - id: 'radar-dots', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - r: 4, - fill: shadcnColors[0], - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialDot(rows, { + id: 'radar-dots', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + r: 4, + fill: shadcnColors[0], + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -110,68 +115,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -180,9 +136,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid Circle - No lines

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/styles.css b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/styles.css +++ b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/tanstack.ts b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/tanstack.ts index e4e145d3..a46f3f15 100644 --- a/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/tanstack.ts +++ b/benchmarks/conformance/cases/175-shadcn-radar-grid-circle-no-lines/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/example.tsx b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/example.tsx index 9015acb3..d80b78b3 100644 --- a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/example.tsx +++ b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -18,10 +12,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault const months = rows.map((row) => row.month) const radiusMax = 320 @@ -35,8 +29,6 @@ function createDefinition() { shape: 'circle', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -48,44 +40,57 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialDot(rows, { - id: 'radar-dots', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - r: 4, - fill: shadcnColors[0], - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialDot(rows, { + id: 'radar-dots', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + r: 4, + fill: shadcnColors[0], + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -108,68 +113,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -178,9 +134,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid Circle

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/styles.css b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/styles.css +++ b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/tanstack.ts b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/tanstack.ts index baacdce8..1acd1de7 100644 --- a/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/tanstack.ts +++ b/benchmarks/conformance/cases/176-shadcn-radar-grid-circle/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/example.tsx b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/example.tsx index 6e1f3a9b..f66d8d56 100644 --- a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/example.tsx +++ b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault const months = rows.map((row) => row.month) const radiusMax = 320 @@ -31,8 +25,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -44,35 +36,48 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -95,68 +100,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -165,9 +121,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid Custom

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/styles.css b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/styles.css +++ b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/tanstack.ts b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/tanstack.ts index c68b8d24..58eb9347 100644 --- a/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/tanstack.ts +++ b/benchmarks/conformance/cases/177-shadcn-radar-grid-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/example.tsx b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/example.tsx index 4cadba27..03a55010 100644 --- a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/example.tsx +++ b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarFilled } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarFilled } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarFilled const months = rows.map((row) => row.month) const radiusMax = 300 @@ -35,7 +29,6 @@ function createDefinition() { stroke: 'transparent', strokeOpacity: 0, ...{ fill: shadcnColors[0], fillOpacity: 0.2 }, - ...{}, }), angleGrid({ values: months, @@ -47,35 +40,48 @@ function createDefinition() { strokeOpacity: 0, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.5, - stroke: shadcnColors[0], - strokeOpacity: 0, - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.5, + stroke: shadcnColors[0], + strokeOpacity: 0, + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -98,68 +104,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -168,9 +125,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid Filled

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/styles.css b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/styles.css +++ b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/tanstack.ts b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/tanstack.ts index dc7e9bc7..8d2902a2 100644 --- a/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/tanstack.ts +++ b/benchmarks/conformance/cases/178-shadcn-radar-grid-fill/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/example.tsx b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/example.tsx index 02f3e29d..25dc787c 100644 --- a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/example.tsx +++ b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarDefault } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarDefault } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarDefault const months = rows.map((row) => row.month) const radiusMax = 320 @@ -36,44 +30,57 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialDot(rows, { - id: 'radar-dots', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - r: 4, - fill: shadcnColors[0], - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialDot(rows, { + id: 'radar-dots', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + r: 4, + fill: shadcnColors[0], + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -96,68 +103,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -166,9 +124,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Grid None

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/styles.css b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/styles.css +++ b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/tanstack.ts b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/tanstack.ts index 7fe418ab..3c56a4c0 100644 --- a/benchmarks/conformance/cases/179-shadcn-radar-grid-none/tanstack.ts +++ b/benchmarks/conformance/cases/179-shadcn-radar-grid-none/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/18-cumulative-histogram/example.tsx b/benchmarks/conformance/cases/18-cumulative-histogram/example.tsx index 9f09e73f..9d6e9142 100644 --- a/benchmarks/conformance/cases/18-cumulative-histogram/example.tsx +++ b/benchmarks/conformance/cases/18-cumulative-histogram/example.tsx @@ -1,18 +1,18 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { olympians } from '@charts-poc/demo-data/olympians' +import { olympians } from '@tanstack/charts-data/olympians' import { binX, cumulative, defineChart, rect } from '@tanstack/charts' import { thresholdScott } from 'd3-array' import { scaleLinear } from 'd3-scale' -import type { OlympiansRow } from '@charts-poc/demo-data/olympians' +import type { OlympiansRow } from '@tanstack/charts-data/olympians' type OlympianWithWeight = OlympiansRow & { weight: number } const completeOlympians = olympians.filter( (row): row is OlympianWithWeight => row.weight !== null, ) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const bins = binX(completeOlympians.slice(input.revision * 8), { value: 'weight', thresholds: thresholdScott, @@ -23,41 +23,36 @@ export const definition = (input: ExampleOptions) => { outputs: { cumulativeCount: { value: 'count', reduce: 'sum' } }, }) - return defineChart({ - marks: [ - rect(cumulativeBins, { - x1: 'x1', - x2: 'x2', - y1: () => 0, - y2: 'cumulativeCount', - fill: '#2563eb', - inset: 1, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Weight (kg)' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Cumulative count' } }, - }) + return defineChart( + { + marks: [ + rect(cumulativeBins, { + x1: 'x1', + x2: 'x2', + y1: () => 0, + y2: 'cumulativeCount', + fill: '#2563eb', + inset: 1, + }), + ], + x: { scale: scaleLinear, grid: true, axis: { label: 'Weight (kg)' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Cumulative count' }, + }, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Cumulative histogram' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/18-cumulative-histogram/plot.ts b/benchmarks/conformance/cases/18-cumulative-histogram/plot.ts index 6165a4d7..0c965d61 100644 --- a/benchmarks/conformance/cases/18-cumulative-histogram/plot.ts +++ b/benchmarks/conformance/cases/18-cumulative-histogram/plot.ts @@ -1,4 +1,4 @@ -import { olympians } from '@charts-poc/demo-data/olympians' +import { olympians } from '@tanstack/charts-data/olympians' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/180-shadcn-radar-icons/example.tsx b/benchmarks/conformance/cases/180-shadcn-radar-icons/example.tsx index 7526d58b..93bdf396 100644 --- a/benchmarks/conformance/cases/180-shadcn-radar-icons/example.tsx +++ b/benchmarks/conformance/cases/180-shadcn-radar-icons/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarMultiple } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarMultiple } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarMultiple const months = rows.map((row) => row.month) const radiusMax = 320 @@ -34,8 +28,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -47,48 +39,61 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 1, - stroke: shadcnColors[1], - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 1, + stroke: shadcnColors[1], + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -111,68 +116,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = - const footer = return (
@@ -181,9 +137,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Icons

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/180-shadcn-radar-icons/styles.css b/benchmarks/conformance/cases/180-shadcn-radar-icons/styles.css index 7d46886a..c406779b 100644 --- a/benchmarks/conformance/cases/180-shadcn-radar-icons/styles.css +++ b/benchmarks/conformance/cases/180-shadcn-radar-icons/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -116,11 +113,6 @@ align-items: center; gap: 6px; } -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} .sc-legend-icon { width: 12px; height: 12px; @@ -130,17 +122,6 @@ stroke-linecap: round; stroke-linejoin: round; } -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +148,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +168,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/180-shadcn-radar-icons/tanstack.ts b/benchmarks/conformance/cases/180-shadcn-radar-icons/tanstack.ts index fbf5489a..93a2b218 100644 --- a/benchmarks/conformance/cases/180-shadcn-radar-icons/tanstack.ts +++ b/benchmarks/conformance/cases/180-shadcn-radar-icons/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/example.tsx b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/example.tsx index c7abc5f7..ceca04b2 100644 --- a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/example.tsx +++ b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -18,10 +12,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarMultiple } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarMultiple } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarMultiple const months = rows.map((row) => row.month) const radiusMax = 320 @@ -35,8 +29,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -48,75 +40,88 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 1, - stroke: shadcnColors[1], - strokeWidth: 1, - }), - radialText(rows, { - id: 'radar-values', - angle: 'month', - radius: () => radiusMax, - key: 'month', - z: () => 'desktop', - text: (row) => `${row.desktop}/${row.mobile ?? 0}`, - anchor: 'outside', - radiusOffset: 15, - dy: -7, - fill: 'var(--foreground)', - fontSize: 12, - fontWeight: 500, - }), - radialText(rows, { - id: 'radar-months', - angle: 'month', - radius: () => radiusMax, - key: 'month', - z: () => 'desktop', - text: 'month', - anchor: 'outside', - radiusOffset: 15, - dy: 10, - fill: 'var(--muted-foreground)', - fontSize: 12, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(({ height }) => chartSpec(height < 220 ? 0.64 : 0.76)) + return defineChart( + ({ height }) => ({ + marks: [ + polar({ + radiusRatio: height < 220 ? 0.64 : 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 1, + stroke: shadcnColors[1], + strokeWidth: 1, + }), + radialText(rows, { + id: 'radar-values', + angle: 'month', + radius: () => radiusMax, + key: 'month', + z: () => 'desktop', + text: (row) => `${row.desktop}/${row.mobile ?? 0}`, + anchor: 'outside', + radiusOffset: 15, + dy: -7, + fill: 'var(--foreground)', + fontSize: 12, + fontWeight: 500, + }), + radialText(rows, { + id: 'radar-months', + angle: 'month', + radius: () => radiusMax, + key: 'month', + z: () => 'desktop', + text: 'month', + anchor: 'outside', + radiusOffset: 15, + dy: 10, + fill: 'var(--muted-foreground)', + fontSize: 12, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }), + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -139,68 +144,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -209,9 +165,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Custom Label

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/styles.css b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/styles.css index 7d46886a..9c6d6acb 100644 --- a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/styles.css +++ b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/styles.css @@ -102,45 +102,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +128,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +148,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/tanstack.ts b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/tanstack.ts index a852315f..25febb10 100644 --- a/benchmarks/conformance/cases/181-shadcn-radar-label-custom/tanstack.ts +++ b/benchmarks/conformance/cases/181-shadcn-radar-label-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/182-shadcn-radar-legend/example.tsx b/benchmarks/conformance/cases/182-shadcn-radar-legend/example.tsx index 245b8422..ada8687c 100644 --- a/benchmarks/conformance/cases/182-shadcn-radar-legend/example.tsx +++ b/benchmarks/conformance/cases/182-shadcn-radar-legend/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarMultiple } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarMultiple } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarMultiple const months = rows.map((row) => row.month) const radiusMax = 320 @@ -34,8 +28,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -47,48 +39,61 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 1, - stroke: shadcnColors[1], - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 1, + stroke: shadcnColors[1], + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -111,68 +116,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = - const footer = return (
@@ -181,9 +137,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Legend

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/182-shadcn-radar-legend/styles.css b/benchmarks/conformance/cases/182-shadcn-radar-legend/styles.css index 7d46886a..20ce4e57 100644 --- a/benchmarks/conformance/cases/182-shadcn-radar-legend/styles.css +++ b/benchmarks/conformance/cases/182-shadcn-radar-legend/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -121,26 +118,6 @@ height: 8px; border-radius: 2px; } -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +144,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +164,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/182-shadcn-radar-legend/tanstack.ts b/benchmarks/conformance/cases/182-shadcn-radar-legend/tanstack.ts index e528a9e8..55bcd699 100644 --- a/benchmarks/conformance/cases/182-shadcn-radar-legend/tanstack.ts +++ b/benchmarks/conformance/cases/182-shadcn-radar-legend/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/example.tsx b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/example.tsx index 755a992c..347f1e95 100644 --- a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/example.tsx +++ b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -17,10 +11,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarLines } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarLines } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarLines const months = rows.map((row) => row.month) const radiusMax = 220 @@ -34,8 +28,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, - ...{}, }), angleGrid({ values: months, @@ -47,48 +39,61 @@ function createDefinition() { strokeOpacity: 1, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 2, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 0, - stroke: shadcnColors[1], - strokeWidth: 2, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 2, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 0, + stroke: shadcnColors[1], + strokeWidth: 2, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -111,68 +116,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -181,9 +137,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Lines Only

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/styles.css b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/styles.css +++ b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/tanstack.ts b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/tanstack.ts index 7978393c..0bea0289 100644 --- a/benchmarks/conformance/cases/183-shadcn-radar-lines-only/tanstack.ts +++ b/benchmarks/conformance/cases/183-shadcn-radar-lines-only/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/184-shadcn-radar-radius/example.tsx b/benchmarks/conformance/cases/184-shadcn-radar-radius/example.tsx index f4346dae..957d33b7 100644 --- a/benchmarks/conformance/cases/184-shadcn-radar-radius/example.tsx +++ b/benchmarks/conformance/cases/184-shadcn-radar-radius/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, polar, @@ -16,10 +10,10 @@ import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' -import { shadcnColors, shadcnRadarMultiple } from '@charts-poc/demo-data/shadcn' +import { shadcnColors, shadcnRadarMultiple } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { +export function createExampleChart() { const rows = shadcnRadarMultiple const months = rows.map((row) => row.month) const radiusMax = 320 @@ -29,7 +23,6 @@ function createDefinition() { shape: 'polygon', stroke: 'var(--border)', strokeOpacity: 1, - ...{}, ...{ labels: true, labelAngle: Math.PI / 6, @@ -40,48 +33,61 @@ function createDefinition() { }, }), ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: 0.6, - stroke: shadcnColors[0], - strokeOpacity: 1, - strokeWidth: 1, - }), - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: 1, - stroke: shadcnColors[1], - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return defineChart(chartSpec(0.76)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.76, + angle: { scale: scalePoint().domain(months), wrap: true }, + radius: { scale: scaleLinear().domain([0, radiusMax]) }, + guides, + marks: [ + radialArea(rows, { + id: 'desktop-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'desktop', + key: 'month', + z: () => 'desktop', + curve: curveLinearClosed, + fill: shadcnColors[0], + fillOpacity: 0.6, + stroke: shadcnColors[0], + strokeOpacity: 1, + strokeWidth: 1, + }), + radialArea(rows, { + id: 'mobile-radar', + className: 'ts-chart__radar', + angle: 'month', + radius: 'mobile', + key: 'month', + z: () => 'mobile', + curve: curveLinearClosed, + fill: shadcnColors[1], + fillOpacity: 1, + stroke: shadcnColors[1], + strokeWidth: 1, + }), + ], + }), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function shadcnTooltipContent(points: readonly ChartPoint[]) { return { @@ -104,68 +110,19 @@ function shadcnTooltipContent(points: readonly ChartPoint[]) { function titleCase(value: string) { return value.charAt(0).toUpperCase() + value.slice(1) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = return (
@@ -174,9 +131,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radar Chart - Radius Axis

Showing total visitors for the last 6 months

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/184-shadcn-radar-radius/styles.css b/benchmarks/conformance/cases/184-shadcn-radar-radius/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/184-shadcn-radar-radius/styles.css +++ b/benchmarks/conformance/cases/184-shadcn-radar-radius/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/184-shadcn-radar-radius/tanstack.ts b/benchmarks/conformance/cases/184-shadcn-radar-radius/tanstack.ts index 67976f63..8dc5a1e3 100644 --- a/benchmarks/conformance/cases/184-shadcn-radar-radius/tanstack.ts +++ b/benchmarks/conformance/cases/184-shadcn-radar-radius/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/185-shadcn-radial-grid/example.tsx b/benchmarks/conformance/cases/185-shadcn-radial-grid/example.tsx index b4b1f401..fab6e6b4 100644 --- a/benchmarks/conformance/cases/185-shadcn-radial-grid/example.tsx +++ b/benchmarks/conformance/cases/185-shadcn-radial-grid/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { angleGrid, focusGroupAngle, @@ -16,50 +10,64 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const startAngle = rechartsPolarAngle(0) const endAngle = rechartsPolarAngle(360) - const chartSpec = (radiusFactor: number) => ({ - marks: [ - polar({ - radiusRatio: 0.8, - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleBand().domain(browserNames).paddingInner(0.2), - range: [30 * radiusFactor, 100 * radiusFactor], - }, - guides: [ - radialGrid({ - values: browserNames, - shape: 'circle', - stroke: 'var(--border)', - }), - angleGrid({ - values: Array.from({ length: 12 }, (_, index) => index * 25), - labels: false, - stroke: 'var(--border)', - }), - ], - marks: [ - radialBarAngle(shadcnBrowsers, { - id: 'radial-values', - angle: 'visitors', - radius: 'browser', - key: 'browser', - fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, - }), - ], - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) - return defineChart(chartSpec(1)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.8, + startAngle, + endAngle, + angle: { scale: scaleLinear().domain([0, 300]) }, + radius: { + scale: scaleBand().domain(browserNames).paddingInner(0.2), + range: [30, 100], + }, + guides: [ + radialGrid({ + values: browserNames, + shape: 'circle', + stroke: 'var(--border)', + }), + angleGrid({ + values: Array.from({ length: 12 }, (_, index) => index * 25), + labels: false, + stroke: 'var(--border)', + }), + ], + marks: [ + radialBarAngle(shadcnBrowsers, { + id: 'radial-values', + angle: 'visitors', + radius: 'browser', + key: 'browser', + fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, + }), + ], + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function rechartsPolarAngle(degrees: number) { return ((90 - degrees) * Math.PI) / 180 @@ -93,70 +101,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -165,9 +122,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart - Grid

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/185-shadcn-radial-grid/styles.css b/benchmarks/conformance/cases/185-shadcn-radial-grid/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/185-shadcn-radial-grid/styles.css +++ b/benchmarks/conformance/cases/185-shadcn-radial-grid/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/185-shadcn-radial-grid/tanstack.ts b/benchmarks/conformance/cases/185-shadcn-radial-grid/tanstack.ts index 37a5b0b5..92474d22 100644 --- a/benchmarks/conformance/cases/185-shadcn-radial-grid/tanstack.ts +++ b/benchmarks/conformance/cases/185-shadcn-radial-grid/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/186-shadcn-radial-label/example.tsx b/benchmarks/conformance/cases/186-shadcn-radial-label/example.tsx index ea78f9ff..6083fa76 100644 --- a/benchmarks/conformance/cases/186-shadcn-radial-label/example.tsx +++ b/benchmarks/conformance/cases/186-shadcn-radial-label/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, polar, @@ -15,78 +9,95 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const startAngle = rechartsPolarAngle(-90) const endAngle = rechartsPolarAngle(380) const backgroundRows = shadcnBrowsers.map((row) => ({ ...row, background: 300, })) - const chartSpec = (radiusFactor: number) => ({ - marks: [ - polar({ - radiusRatio: 1, - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleBand().domain(browserNames).paddingInner(0.2), - range: [30 * radiusFactor, 110 * radiusFactor], - }, - guides: [], - marks: [ - radialBarAngle(backgroundRows, { - id: 'radial-backgrounds', - angle: 'background', - radius: 'browser', - key: 'browser', - fill: 'var(--muted)', - }), - radialBarAngle(shadcnBrowsers, { - id: 'radial-values', - angle: 'visitors', - radius: 'browser', - key: 'browser', - fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, - }), - ], - }), - polar({ - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleLinear().domain([0, 110]), - range: [0, 110 * radiusFactor], - }, - marks: [ - radialText( - shadcnBrowsers.map((row, index) => ({ - ...row, - angle: 10, - labelRadius: 38 + index * 16, - })), - { - id: 'radial-labels', - angle: 'angle', - radius: 'labelRadius', + return defineChart( + ({ height }) => ({ + marks: [ + polar({ + radiusRatio: 1, + startAngle, + endAngle, + angle: { scale: scaleLinear().domain([0, 300]) }, + radius: { + scale: scaleBand().domain(browserNames).paddingInner(0.2), + range: [ + 30 * (height < 220 ? 0.8 : 1), + 110 * (height < 220 ? 0.8 : 1), + ], + }, + guides: [], + marks: [ + radialBarAngle(backgroundRows, { + id: 'radial-backgrounds', + angle: 'background', + radius: 'browser', key: 'browser', - text: (row) => titleCase(row.browser), - fill: 'white', - fontSize: 11, - rotate: -25, - }, - ), - ], - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) - return defineChart(({ height }) => chartSpec(height < 220 ? 0.8 : 1)) + fill: 'var(--muted)', + }), + radialBarAngle(shadcnBrowsers, { + id: 'radial-values', + angle: 'visitors', + radius: 'browser', + key: 'browser', + fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, + }), + ], + }), + polar({ + startAngle, + endAngle, + angle: { scale: scaleLinear().domain([0, 300]) }, + radius: { + scale: scaleLinear().domain([0, 110]), + range: [0, 110 * (height < 220 ? 0.8 : 1)], + }, + marks: [ + radialText( + shadcnBrowsers.map((row, index) => ({ + ...row, + angle: 10, + labelRadius: 38 + index * 16, + })), + { + id: 'radial-labels', + angle: 'angle', + radius: 'labelRadius', + key: 'browser', + text: (row) => titleCase(row.browser), + fill: 'white', + fontSize: 11, + rotate: -25, + }, + ), + ], + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }), + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function rechartsPolarAngle(degrees: number) { return ((90 - degrees) * Math.PI) / 180 @@ -120,70 +131,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -192,9 +152,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart - Label

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/186-shadcn-radial-label/styles.css b/benchmarks/conformance/cases/186-shadcn-radial-label/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/186-shadcn-radial-label/styles.css +++ b/benchmarks/conformance/cases/186-shadcn-radial-label/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/186-shadcn-radial-label/tanstack.ts b/benchmarks/conformance/cases/186-shadcn-radial-label/tanstack.ts index 91ecf90a..7745f8ed 100644 --- a/benchmarks/conformance/cases/186-shadcn-radial-label/tanstack.ts +++ b/benchmarks/conformance/cases/186-shadcn-radial-label/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/187-shadcn-radial-shape/example.tsx b/benchmarks/conformance/cases/187-shadcn-radial-shape/example.tsx index e46f7817..4a2f87a8 100644 --- a/benchmarks/conformance/cases/187-shadcn-radial-shape/example.tsx +++ b/benchmarks/conformance/cases/187-shadcn-radial-shape/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, pie, @@ -17,72 +11,62 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' -function createDefinition() { - return buildSingleRadialDefinition({ - id: 'shape', - visitors: 1260, - endDegrees: 100, - innerRadius: 65, - outerRadius: 95, - backgroundInnerRadius: 74, - backgroundOuterRadius: 86, - cornerRadius: 0, - total: '1,260', - }) -} -function buildSingleRadialDefinition(options: { - id: string - visitors: number - endDegrees: number - innerRadius: number - outerRadius: number - backgroundInnerRadius: number - backgroundOuterRadius: number - cornerRadius: number - total: string -}) { - const rows = [ - { browser: 'safari', visitors: options.visitors, ring: 'visitors' }, - ] +export function createExampleChart() { + const rows = [{ browser: 'safari', visitors: 1260, ring: 'visitors' }] const background = pie([{ id: 'background', value: 1 }], { value: 'value' }) - return defineChart({ - marks: [ - polar({ - marks: [ - radialArc(background, { - id: `${options.id}-background`, - key: 'id', - innerRadius: options.backgroundInnerRadius, - outerRadius: options.backgroundOuterRadius, - fill: 'var(--muted)', - }), - ], - }), - polar({ - startAngle: rechartsPolarAngle(0), - endAngle: rechartsPolarAngle(options.endDegrees), - angle: { scale: scaleLinear().domain([0, options.visitors]) }, - radius: { - scale: scaleBand().domain(['visitors']), - range: [options.innerRadius, options.outerRadius], - }, - marks: [ - radialBarAngle(rows, { - id: `${options.id}-value`, - angle: 'visitors', - radius: 'ring', - key: 'browser', - fill: shadcnColors[1], - cornerRadius: options.cornerRadius, - }), - ], - }), - radialCenterLabels(options.total, 36, 0, 24), - ], - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + marks: [ + radialArc(background, { + id: `${'shape'}-background`, + key: 'id', + innerRadius: 74, + outerRadius: 86, + fill: 'var(--muted)', + }), + ], + }), + polar({ + startAngle: rechartsPolarAngle(0), + endAngle: rechartsPolarAngle(100), + angle: { scale: scaleLinear().domain([0, 1260]) }, + radius: { + scale: scaleBand().domain(['visitors']), + range: [65, 95], + }, + marks: [ + radialBarAngle(rows, { + id: `${'shape'}-value`, + angle: 'visitors', + radius: 'ring', + key: 'browser', + fill: shadcnColors[1], + cornerRadius: 0, + }), + ], + }), + radialCenterLabels('1,260', 36, 0, 24), + ], + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function radialCenterLabels( total: string, @@ -150,70 +134,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -222,9 +155,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart - Shape

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/187-shadcn-radial-shape/styles.css b/benchmarks/conformance/cases/187-shadcn-radial-shape/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/187-shadcn-radial-shape/styles.css +++ b/benchmarks/conformance/cases/187-shadcn-radial-shape/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/187-shadcn-radial-shape/tanstack.ts b/benchmarks/conformance/cases/187-shadcn-radial-shape/tanstack.ts index 8f448cad..ab07cb91 100644 --- a/benchmarks/conformance/cases/187-shadcn-radial-shape/tanstack.ts +++ b/benchmarks/conformance/cases/187-shadcn-radial-shape/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/188-shadcn-radial-simple/example.tsx b/benchmarks/conformance/cases/188-shadcn-radial-simple/example.tsx index 1e272f81..eb9b0978 100644 --- a/benchmarks/conformance/cases/188-shadcn-radial-simple/example.tsx +++ b/benchmarks/conformance/cases/188-shadcn-radial-simple/example.tsx @@ -1,59 +1,67 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, polar, radialBarAngle } from '@tanstack/charts/polar' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnBrowsers, shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnBrowsers, shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const browserNames = shadcnBrowsers.map((row) => row.browser) -function createDefinition() { +export function createExampleChart() { const startAngle = rechartsPolarAngle(0) const endAngle = rechartsPolarAngle(360) const backgroundRows = shadcnBrowsers.map((row) => ({ ...row, background: 300, })) - const chartSpec = (radiusFactor: number) => ({ - marks: [ - polar({ - radiusRatio: 1, - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleBand().domain(browserNames).paddingInner(0.2), - range: [30 * radiusFactor, 110 * radiusFactor], - }, - guides: [], - marks: [ - radialBarAngle(backgroundRows, { - id: 'radial-backgrounds', - angle: 'background', - radius: 'browser', - key: 'browser', - fill: 'var(--muted)', - }), - radialBarAngle(shadcnBrowsers, { - id: 'radial-values', - angle: 'visitors', - radius: 'browser', - key: 'browser', - fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, - }), - ], - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) - return defineChart(chartSpec(1)) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 1, + startAngle, + endAngle, + angle: { scale: scaleLinear().domain([0, 300]) }, + radius: { + scale: scaleBand().domain(browserNames).paddingInner(0.2), + range: [30, 110], + }, + guides: [], + marks: [ + radialBarAngle(backgroundRows, { + id: 'radial-backgrounds', + angle: 'background', + radius: 'browser', + key: 'browser', + fill: 'var(--muted)', + }), + radialBarAngle(shadcnBrowsers, { + id: 'radial-values', + angle: 'visitors', + radius: 'browser', + key: 'browser', + fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, + }), + ], + }), + ], + color: { domain: browserNames, range: shadcnColors }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function rechartsPolarAngle(degrees: number) { return ((90 - degrees) * Math.PI) / 180 @@ -87,70 +95,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -159,9 +116,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/188-shadcn-radial-simple/styles.css b/benchmarks/conformance/cases/188-shadcn-radial-simple/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/188-shadcn-radial-simple/styles.css +++ b/benchmarks/conformance/cases/188-shadcn-radial-simple/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/188-shadcn-radial-simple/tanstack.ts b/benchmarks/conformance/cases/188-shadcn-radial-simple/tanstack.ts index b8e788be..f13a3183 100644 --- a/benchmarks/conformance/cases/188-shadcn-radial-simple/tanstack.ts +++ b/benchmarks/conformance/cases/188-shadcn-radial-simple/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/189-shadcn-radial-stacked/example.tsx b/benchmarks/conformance/cases/189-shadcn-radial-stacked/example.tsx index ab59078d..552e794f 100644 --- a/benchmarks/conformance/cases/189-shadcn-radial-stacked/example.tsx +++ b/benchmarks/conformance/cases/189-shadcn-radial-stacked/example.tsx @@ -1,10 +1,4 @@ -import { useMemo } from 'react' -import { - defineChart, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { defineChart, type ChartPoint } from '@tanstack/charts' import { focusGroupAngle, polar, @@ -15,13 +9,10 @@ import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' import { scaleBand, scaleLinear } from 'd3-scale' -import { shadcnColors } from '@charts-poc/demo-data/shadcn' +import { shadcnColors } from '@tanstack/charts-data/shadcn' import './styles.css' const twoSeries = ['desktop', 'mobile'] as const -function createDefinition() { - return buildStackedRadialDefinition() -} -function buildStackedRadialDefinition() { +export function createExampleChart() { const rows = [ { id: 'mobile', @@ -38,36 +29,51 @@ function buildStackedRadialDefinition() { fill: shadcnColors[0], }, ] - return defineChart({ - marks: [ - polar({ - startAngle: rechartsPolarAngle(0), - endAngle: rechartsPolarAngle(180), - angle: { scale: scaleLinear().domain([0, 1260]) }, - radius: { - scale: scaleBand().domain(['visitors']), - range: [80, 110], - }, - marks: [ - radialBarAngle(rows, { - id: 'stacked-values', - angle1: 'start', - angle2: 'end', - angle: 'end', - radius: 'ring', - key: 'id', - fill: (row) => row.fill, - cornerRadius: 5, - stroke: 'transparent', - strokeWidth: 2, - }), - ], - }), - radialCenterLabels('1,830', 24, -16, 4), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + startAngle: rechartsPolarAngle(0), + endAngle: rechartsPolarAngle(180), + angle: { scale: scaleLinear().domain([0, 1260]) }, + radius: { + scale: scaleBand().domain(['visitors']), + range: [80, 110], + }, + marks: [ + radialBarAngle(rows, { + id: 'stacked-values', + angle1: 'start', + angle2: 'end', + angle: 'end', + radius: 'ring', + key: 'id', + fill: (row) => row.fill, + cornerRadius: 5, + stroke: 'transparent', + strokeWidth: 2, + }), + ], + }), + radialCenterLabels('1,830', 24, -16, 4), + ], + color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, + margin: 0, + }, + { + svgAnimation: false, + focus: focusGroupAngle, + keyboard: false, + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: 'group-center', + placement: 'auto', + sort: 'color-domain', + content: (points) => shadcnTooltipContent(points), + }, + }, + ) } function radialCenterLabels( total: string, @@ -135,70 +141,19 @@ function browserMetric(datum: unknown) { ? { browser, visitors } : undefined } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: focusGroupAngle, - keyboard: false, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: 'group-center', - placement: 'auto', - offset: undefined, - sort: 'color-domain', - content: (points) => shadcnTooltipContent(points), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = Math.min(250, contentWidth) const chartHeight = chartWidth - const headerAction = null - const legend = null - const footer = ( - - ) return (
@@ -207,9 +162,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Radial Chart - Stacked

January - June 2024

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ? ( -
{footer}
- ) : null} +
+ +
) diff --git a/benchmarks/conformance/cases/189-shadcn-radial-stacked/styles.css b/benchmarks/conformance/cases/189-shadcn-radial-stacked/styles.css index 7d46886a..26428b5f 100644 --- a/benchmarks/conformance/cases/189-shadcn-radial-stacked/styles.css +++ b/benchmarks/conformance/cases/189-shadcn-radial-stacked/styles.css @@ -90,9 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} .sc-card-footer { display: flex; flex-direction: column; @@ -102,45 +99,6 @@ font-size: 14px; line-height: 1; } -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} .sc-centered { justify-content: center; align-items: center; @@ -167,9 +125,6 @@ .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -190,272 +145,3 @@ box-shadow: 0 2px 6px rgb(0 0 0 / 8%); font-size: 12px; } -.sc-advanced-tooltip { - display: grid; - width: 158px; - gap: 6px; -} -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} -.sc-shadcn-tooltip { - display: grid; - gap: 5px; -} -.sc-tooltip-label { - color: var(--foreground); - font-weight: 500; -} -.sc-shadcn-tooltip-row { - display: grid; - grid-template-columns: 9px minmax(0, 1fr) auto; - align-items: center; - gap: 7px; - color: var(--muted-foreground); -} -.sc-tooltip-no-indicator .sc-shadcn-tooltip-row { - grid-template-columns: minmax(0, 1fr) auto; -} -.sc-tooltip-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-tooltip-line { - width: 3px; - height: 16px; - border-radius: 2px; -} -.sc-tooltip-icon { - width: 11px; - height: 11px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-tooltip-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-tooltip-value span { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-tooltip-total { - display: flex; - justify-content: space-between; - margin-top: 1px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/189-shadcn-radial-stacked/tanstack.ts b/benchmarks/conformance/cases/189-shadcn-radial-stacked/tanstack.ts index 433666b5..f61bcb9c 100644 --- a/benchmarks/conformance/cases/189-shadcn-radial-stacked/tanstack.ts +++ b/benchmarks/conformance/cases/189-shadcn-radial-stacked/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/19-moving-average-line/example.tsx b/benchmarks/conformance/cases/19-moving-average-line/example.tsx index 8ca5c3c0..2d312966 100644 --- a/benchmarks/conformance/cases/19-moving-average-line/example.tsx +++ b/benchmarks/conformance/cases/19-moving-average-line/example.tsx @@ -3,11 +3,11 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, lineY, ruleY, rollingWindow } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { sfTemperatures } from '@charts-poc/demo-data/sf-temperatures' +import { sfTemperatures } from '@tanstack/charts-data/sf-temperatures' const windowSize = 14 -export const definition = () => { +export const createExampleChart = () => { const completeRows = rollingWindow(sfTemperatures, { size: windowSize, partial: false, @@ -18,42 +18,39 @@ export const definition = () => { }) const rows = completeRows - return defineChart({ - marks: [ - lineY(rows, { - x: 'date', - y: 'low', - stroke: '#4e79a7', - strokeWidth: 2.25, - }), - lineY(rows, { - x: 'date', - y: 'high', - stroke: '#e15759', - strokeWidth: 2.25, - }), - ruleY([32], { - stroke: '#64748b', - strokeDasharray: '4 4', - }), - ], - x: { scale: scaleUtc, axis: { label: 'Date' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Fourteen-day average temperature (°F)' }, + return defineChart( + { + marks: [ + lineY(rows, { + x: 'date', + y: 'low', + stroke: '#4e79a7', + strokeWidth: 2.25, + }), + lineY(rows, { + x: 'date', + y: 'high', + stroke: '#e15759', + strokeWidth: 2.25, + }), + ruleY([32], { + stroke: '#64748b', + strokeDasharray: '4 4', + }), + ], + x: { scale: scaleUtc, axis: { label: 'Date' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Fourteen-day average temperature (°F)' }, + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } export const exampleAriaLabel = 'Fourteen-day average high and low temperature in San Francisco' -export const createExampleChart = () => - defineChart(definition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/19-moving-average-line/plot.ts b/benchmarks/conformance/cases/19-moving-average-line/plot.ts index 477cfc52..0f2d0760 100644 --- a/benchmarks/conformance/cases/19-moving-average-line/plot.ts +++ b/benchmarks/conformance/cases/19-moving-average-line/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { sfTemperatures } from '@charts-poc/demo-data/sf-temperatures' +import { sfTemperatures } from '@tanstack/charts-data/sf-temperatures' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/190-shadcn-tooltip-default/example.tsx b/benchmarks/conformance/cases/190-shadcn-tooltip-default/example.tsx index 9fef5f69..625607a3 100644 --- a/benchmarks/conformance/cases/190-shadcn-tooltip-default/example.tsx +++ b/benchmarks/conformance/cases/190-shadcn-tooltip-default/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Default

Default tooltip with ChartTooltipContent.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/190-shadcn-tooltip-default/styles.css b/benchmarks/conformance/cases/190-shadcn-tooltip-default/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/190-shadcn-tooltip-default/styles.css +++ b/benchmarks/conformance/cases/190-shadcn-tooltip-default/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/190-shadcn-tooltip-default/tanstack.ts b/benchmarks/conformance/cases/190-shadcn-tooltip-default/tanstack.ts index 24509d5e..c93f70eb 100644 --- a/benchmarks/conformance/cases/190-shadcn-tooltip-default/tanstack.ts +++ b/benchmarks/conformance/cases/190-shadcn-tooltip-default/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/example.tsx b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/example.tsx index be8179c2..abf74c3c 100644 --- a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/example.tsx +++ b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Formatter

Tooltip with custom formatter.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/styles.css b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/styles.css +++ b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/tanstack.ts b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/tanstack.ts index 47fef1fc..d19c2ee4 100644 --- a/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/tanstack.ts +++ b/benchmarks/conformance/cases/191-shadcn-tooltip-formatter/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/example.tsx b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/example.tsx index ac54cd21..024f3d1d 100644 --- a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/example.tsx +++ b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - 27 - const headerAction = null - const legend = - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Icons

Tooltip with icons.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null} +
+ +
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/styles.css b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/styles.css index 7d46886a..ee699a02 100644 --- a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/styles.css +++ b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/styles.css @@ -90,18 +90,6 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} .sc-chart-footer { display: flex; flex-wrap: wrap; @@ -116,11 +104,6 @@ align-items: center; gap: 6px; } -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} .sc-legend-icon { width: 12px; height: 12px; @@ -130,46 +113,9 @@ stroke-linecap: round; stroke-linejoin: round; } -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +141,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +201,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/tanstack.ts b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/tanstack.ts index 13ccc89a..fd7960fe 100644 --- a/benchmarks/conformance/cases/192-shadcn-tooltip-icons/tanstack.ts +++ b/benchmarks/conformance/cases/192-shadcn-tooltip-icons/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/example.tsx b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/example.tsx index d0c63aae..11f304a8 100644 --- a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/example.tsx +++ b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Line Indicator

Tooltip with line indicator.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/styles.css b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/styles.css +++ b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/tanstack.ts b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/tanstack.ts index 5a0103bd..ea8b2d5a 100644 --- a/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/tanstack.ts +++ b/benchmarks/conformance/cases/193-shadcn-tooltip-indicator-line/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/example.tsx b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/example.tsx index cbfdf1d9..3a0ae86d 100644 --- a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/example.tsx +++ b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - No Indicator

Tooltip with no indicator.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/styles.css b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/styles.css +++ b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/tanstack.ts b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/tanstack.ts index 0220bb10..dc3ea609 100644 --- a/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/tanstack.ts +++ b/benchmarks/conformance/cases/194-shadcn-tooltip-indicator-none/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/example.tsx b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/example.tsx index 249fbaf9..05e98d15 100644 --- a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/example.tsx +++ b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Custom label

Tooltip with custom label from chartConfig.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/styles.css b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/styles.css +++ b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/tanstack.ts b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/tanstack.ts index c1f35651..70016906 100644 --- a/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/tanstack.ts +++ b/benchmarks/conformance/cases/195-shadcn-tooltip-label-custom/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/example.tsx b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/example.tsx index 17cbc6c8..6748bf9f 100644 --- a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/example.tsx +++ b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - Label Formatter

Tooltip with label formatter.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/styles.css b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/styles.css +++ b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/tanstack.ts b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/tanstack.ts index bf3510bf..73c95364 100644 --- a/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/tanstack.ts +++ b/benchmarks/conformance/cases/196-shadcn-tooltip-label-formatter/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/example.tsx b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/example.tsx index 31df34fe..b122afc6 100644 --- a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/example.tsx +++ b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/example.tsx @@ -1,12 +1,5 @@ -import { useMemo, useRef } from 'react' -import { - barY, - defineChart, - stack, - type ChartPoint, - type ChartValue, - type DomChartDefinition, -} from '@tanstack/charts' +import { useRef } from 'react' +import { barY, defineChart, stack, type ChartPoint } from '@tanstack/charts' import { RendererChart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' import { motion } from '@tanstack/charts/motion' @@ -15,35 +8,53 @@ import { shadcnActivities, shadcnColors, type ShadcnActivityDatum, -} from '@charts-poc/demo-data/shadcn' +} from '@tanstack/charts-data/shadcn' import './styles.css' const activityNames = ['running', 'swimming'] as const -function createDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, +export function createExampleChart() { + return defineChart( + { + marks: [ + barY(shadcnActivities, { + id: 'activity-bars', + x: 'date', + y: 'value', + z: 'activity', + color: 'activity', + key: (row) => `${row.date}:${row.activity}`, + layout: stack({ order: activityNames }), + radius: 4, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), + axis: { + line: false, + ticks: { size: 0, padding: 10, format: formatWeekday }, + }, }, + y: { scale: scaleLinear().domain([0, 1000]), axis: false }, + color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, + margin: { top: 0, right: 7, bottom: 32, left: 7 }, + theme: shadcnTheme(), }, - y: { scale: scaleLinear().domain([0, 1000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) + { + svgAnimation: false, + focus: 'group-x', + tooltip: { + use: tooltip, + className: 'sc-chart-tooltip', + anchor: (_points, context) => ({ + x: context.surface.width * 0.271, + y: context.surface.height * 0.554, + }), + placement: 'bottom-right', + offset: 0, + sort: 'color-domain', + content: () => ({ rows: [] }), + }, + }, + ) } function formatWeekday(value: string) { return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( @@ -141,72 +152,20 @@ function ShadcnActivityIcon({ activity }: { activity: string }) { ) } -export function createExampleChart() { - return defineChart(createDefinition(), { - svgAnimation: false, - focus: 'group-x', - keyboard: true, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }), - placement: 'bottom-right', - offset: 0, - sort: 'color-domain', - content: () => ({ rows: [] }), - }, - }) -} export const definition = createExampleChart() -type ExampleDefinition = ReturnType -type ExampleDatum = - ExampleDefinition extends DomChartDefinition< - infer TDatum, - infer _TXValue, - infer _TYValue - > - ? TDatum - : never -type ExampleXValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer TXValue extends ChartValue, - infer _TYValue - > - ? TXValue - : never -type ExampleYValue = - ExampleDefinition extends DomChartDefinition< - infer _TDatum, - infer _TXValue, - infer TYValue extends ChartValue - > - ? TYValue - : never +const renderer = motion({ + initial: 'always', + transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, +}) export interface ExampleProps { width?: number height?: number } export default function Example({ width = 640, height = 600 }: ExampleProps) { const seededTooltip = useRef(false) - const chartDefinition = definition - const renderer = useMemo( - () => - motion({ - initial: 'always', - transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 }, - }), - [], - ) const contentWidth = Math.max(1, width - 50) const chartWidth = contentWidth const chartHeight = (contentWidth * 9) / 16 - const headerAction = null - const legend = null - const footer = null return (
@@ -215,9 +174,6 @@ export default function Example({ width = 640, height = 600 }: ExampleProps) {

Tooltip - No Label

Tooltip with no label.

- {headerAction ? ( -
{headerAction}
- ) : null}
- {legend ?
{legend}
: null}
- {footer ?
{footer}
: null} ) diff --git a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/styles.css b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/styles.css index 7d46886a..7fcf7422 100644 --- a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/styles.css +++ b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/styles.css @@ -90,86 +90,9 @@ .sc-chart > * { display: block; } -.sc-chart-clip .ts-chart { - overflow: hidden !important; -} -.sc-card-footer { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0 24px; - font-size: 14px; - line-height: 1; -} -.sc-chart-footer { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - margin-top: 12px; - color: var(--muted-foreground); - font-size: 12px; -} -.sc-legend-item { - display: inline-flex; - align-items: center; - gap: 6px; -} -.sc-legend-dot { - width: 8px; - height: 8px; - border-radius: 2px; -} -.sc-legend-icon { - width: 12px; - height: 12px; - fill: none; - stroke: var(--muted-foreground); - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-pie-legend { - display: flex; - width: 260px; - flex-wrap: wrap; - justify-content: center; - gap: 10px 16px; -} -.sc-pie-legend .sc-legend-item { - flex: 0 0 70px; - justify-content: center; -} -.sc-centered { - justify-content: center; - align-items: center; - text-align: center; -} -.sc-trend { - display: flex; - align-items: center; - gap: 8px; - font-weight: 500; -} -.sc-trend svg { - width: 16px; - height: 16px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} -.sc-footer-note { - color: var(--muted-foreground); -} .sc-example .ts-chart { color: var(--muted-foreground); } -.sc-example .recharts-surface { - overflow: visible; -} .sc-example .ts-chart__grid line, .sc-example .ts-chart__polar-grid path, .sc-example .ts-chart__polar-grid line { @@ -195,43 +118,6 @@ width: 158px; gap: 6px; } -.sc-advanced-row { - display: grid; - grid-template-columns: 10px 1fr auto; - align-items: center; - gap: 6px; -} -.sc-advanced-swatch { - width: 10px; - height: 10px; - border-radius: 2px; -} -.sc-advanced-value { - display: flex; - align-items: baseline; - gap: 2px; - color: var(--foreground); - font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-weight: 500; - font-variant-numeric: tabular-nums; -} -.sc-advanced-unit { - color: var(--muted-foreground); - font-family: inherit; - font-weight: 400; -} -.sc-advanced-total { - display: flex; - align-items: center; - margin-top: 2px; - padding-top: 7px; - border-top: 1px solid var(--border); - color: var(--foreground); - font-weight: 500; -} -.sc-advanced-total .sc-advanced-value { - margin-left: auto; -} .sc-shadcn-tooltip { display: grid; gap: 5px; @@ -292,170 +178,3 @@ color: var(--foreground); font-weight: 500; } -.sc-interactive-area { - gap: 0; - padding-top: 0; -} -.sc-interactive-area .sc-card-header { - display: flex; - align-items: center; - gap: 16px; - padding-top: 20px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} -.sc-interactive-area .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-area .sc-card-content { - padding-top: 24px; -} -.sc-interactive-area .sc-chart-footer { - margin-top: 8px; -} -.sc-interactive-bar { - gap: 0; - padding: 0 0 30px; -} -.sc-interactive-bar .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-bar .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-bar .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-bar .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-line { - gap: 0; - padding: 0; -} -.sc-interactive-line .sc-card-header { - display: flex; - min-height: 99px; - align-items: stretch; - gap: 0; - padding: 0; - border-bottom: 1px solid var(--border); -} -.sc-interactive-line .sc-card-heading { - flex: 1; - align-content: center; - gap: 4px; - padding: 16px 24px; -} -.sc-interactive-line .sc-card-action { - display: flex; - margin: 0; -} -.sc-interactive-line .sc-card-content { - padding: 43px 24px 0; -} -.sc-interactive-pie .sc-card-header { - display: flex; - align-items: flex-start; - gap: 16px; - padding-bottom: 0; -} -.sc-interactive-pie .sc-card-heading { - flex: 1; - gap: 4px; -} -.sc-interactive-pie .sc-card-content { - padding-bottom: 44px; -} -.sc-interactive-pie .sc-chart { - transform: translateY(55px); -} -.sc-interactive-pie .sc-card-action { - transform: translateY(48px); -} -.sc-card-action { - margin-left: auto; -} -.sc-select-display { - position: relative; - display: flex; - min-width: 130px; - height: 36px; - align-items: center; - gap: 8px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--background); - color: var(--foreground); - font-size: 14px; - box-shadow: 0 1px 2px rgb(0 0 0 / 4%); -} -.sc-select-display:focus-within { - outline: 2px solid var(--foreground); - outline-offset: 2px; -} -.sc-select-display select { - min-width: 0; - flex: 1; - appearance: none; - border: 0; - outline: 0; - background: transparent; - color: inherit; - font: inherit; - cursor: pointer; -} -.sc-select-display svg { - width: 14px; - height: 14px; - flex: none; - color: var(--muted-foreground); - pointer-events: none; -} -.sc-select-swatch { - width: 12px; - height: 12px; - flex: none; - border-radius: 3px; -} -.sc-bar-metric { - display: grid; - width: 168px; - align-content: center; - gap: 6px; - padding: 16px 32px; - border: 0; - border-left: 1px solid var(--border); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} -.sc-bar-metric[data-active='true'] { - background: var(--muted); -} -.sc-bar-metric:focus-visible { - outline: 2px solid var(--foreground); - outline-offset: -3px; -} -.sc-bar-metric span { - color: var(--muted-foreground); - font-size: 12px; -} -.sc-bar-metric strong { - font-size: 30px; - line-height: 1; - letter-spacing: -0.03em; -} diff --git a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/tanstack.ts b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/tanstack.ts index a1153bc9..f866b987 100644 --- a/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/tanstack.ts +++ b/benchmarks/conformance/cases/197-shadcn-tooltip-label-none/tanstack.ts @@ -9,7 +9,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition - export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, diff --git a/benchmarks/conformance/cases/20-normalized-stacked-area/example.tsx b/benchmarks/conformance/cases/20-normalized-stacked-area/example.tsx index 08bfd7e4..5677a12b 100644 --- a/benchmarks/conformance/cases/20-normalized-stacked-area/example.tsx +++ b/benchmarks/conformance/cases/20-normalized-stacked-area/example.tsx @@ -4,7 +4,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { areaY, colorLegend, defineChart, ruleY, stack } from '@tanstack/charts' import { format } from 'd3-format' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' const percent = format('.0%') const colors = [ @@ -20,50 +20,41 @@ const colors = [ '#bab0ab', ] -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - areaY(industries, { - x: 'date', - y: 'unemployed', - color: 'industry', - fillOpacity: 0.82, - layout: stack({ offset: 'normalize' }), - }), - ruleY([0]), - ], - x: { scale: scaleUtc, axis: { label: 'Month' } }, - y: { - scale: scaleLinear().domain([0, 1]), - grid: true, - axis: { ticks: { format: percent }, label: 'Share of unemployment' }, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + areaY(industries, { + x: 'date', + y: 'unemployed', + color: 'industry', + fillOpacity: 0.82, + layout: stack({ offset: 'normalize' }), + }), + ruleY([0]), + ], + x: { scale: scaleUtc, axis: { label: 'Month' } }, + y: { + scale: scaleLinear().domain([0, 1]), + grid: true, + axis: { ticks: { format: percent }, label: 'Share of unemployment' }, + }, + color: { + range: colors, + ...(input.preview === true + ? {} + : { legend: colorLegend({ label: 'Industry' }) }), + }, }, - color: { - range: colors, - ...(input.preview === true - ? {} - : { legend: colorLegend({ label: 'Industry' }) }), - }, - }) -export interface ExampleOptions { - width: number - height: number - revision: number + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Industry share of unemployment' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/20-normalized-stacked-area/plot.ts b/benchmarks/conformance/cases/20-normalized-stacked-area/plot.ts index c5a862c4..66abfa4e 100644 --- a/benchmarks/conformance/cases/20-normalized-stacked-area/plot.ts +++ b/benchmarks/conformance/cases/20-normalized-stacked-area/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/21-streamgraph/example.tsx b/benchmarks/conformance/cases/21-streamgraph/example.tsx index 18c27ac6..d6b543c9 100644 --- a/benchmarks/conformance/cases/21-streamgraph/example.tsx +++ b/benchmarks/conformance/cases/21-streamgraph/example.tsx @@ -3,8 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { areaY, colorLegend, defineChart, stack } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' const colors = [ '#4e79a7', @@ -19,51 +18,52 @@ const colors = [ '#bab0ab', ] -function streamgraphChart(rows: readonly IndustriesRow[], showLegend: boolean) { - return defineChart({ - marks: [ - areaY(rows, { - x: 'date', - y: 'unemployed', - z: 'industry', - color: 'industry', - layout: stack({ offset: 'wiggle', order: 'inside-out' }), - fillOpacity: 0.85, - }), - ], - x: { scale: scaleUtc, axis: { label: 'Month' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Unemployed (thousands)' }, +export const createExampleChart = () => { + const rows = industries + const showLegend = true + + return defineChart( + { + marks: [ + areaY(rows, { + x: 'date', + y: 'unemployed', + z: 'industry', + color: 'industry', + layout: stack({ offset: 'wiggle', order: 'inside-out' }), + fillOpacity: 0.85, + }), + ], + x: { scale: scaleUtc, axis: { label: 'Month' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Unemployed (thousands)' }, + }, + color: { + range: colors, + ...(showLegend ? { legend: colorLegend({ label: 'Industry' }) } : {}), + }, }, - color: { - range: colors, - ...(showLegend ? { legend: colorLegend({ label: 'Industry' }) } : {}), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { + month: 'short', + year: 'numeric', + timeZone: 'UTC', + })} · ${datum.unemployed.toLocaleString('en-US')} thousand unemployed`, + }, + }, }, - }) + ) } -export const streamgraphDefinition = () => streamgraphChart(industries, true) - export const exampleAriaLabel = 'Unemployment by industry as a streamgraph' -export const createExampleChart = () => - defineChart(streamgraphDefinition(), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { - month: 'short', - year: 'numeric', - timeZone: 'UTC', - })} · ${datum.unemployed.toLocaleString('en-US')} thousand unemployed`, - }, - }, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/21-streamgraph/plot.ts b/benchmarks/conformance/cases/21-streamgraph/plot.ts index e02f6544..35692416 100644 --- a/benchmarks/conformance/cases/21-streamgraph/plot.ts +++ b/benchmarks/conformance/cases/21-streamgraph/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/21-streamgraph/tanstack.test.ts b/benchmarks/conformance/cases/21-streamgraph/tanstack.test.ts index 64a53cbf..ebae946b 100644 --- a/benchmarks/conformance/cases/21-streamgraph/tanstack.test.ts +++ b/benchmarks/conformance/cases/21-streamgraph/tanstack.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { industries } from '@charts-poc/demo-data/industries' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import { createChartRuntime } from '@tanstack/charts' import type { ChartSpecDatum, @@ -9,14 +9,14 @@ import type { ChartSpecYValue, } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { streamgraphDefinition } from './tanstack' +import { createExampleChart } from './tanstack' -type Definition = ReturnType +type Definition = ReturnType describe('definition-owned streamgraph stack', () => { it('keeps raw rows while deriving inside-out wiggle intervals', () => { const scene = createChartRuntime().render( - streamgraphDefinition(), + createExampleChart(), { width: 640, height: 400 }, ) @@ -60,7 +60,8 @@ describe('definition-owned streamgraph stack', () => { expect(source).toContain("order: 'inside-out'") expect(source).toContain("offset: 'wiggle'") - expect(source).toContain('streamgraphChart(industries, true)') + expect(source).toContain('const rows = industries') + expect(source).toContain('const showLegend = true') expect(source).toContain('areaY(rows') expect(source).not.toContain("from 'd3-array'") expect(source).not.toContain("from 'd3-shape'") diff --git a/benchmarks/conformance/cases/22-bollinger-band/example.tsx b/benchmarks/conformance/cases/22-bollinger-band/example.tsx index 7481a64b..2fd11e54 100644 --- a/benchmarks/conformance/cases/22-bollinger-band/example.tsx +++ b/benchmarks/conformance/cases/22-bollinger-band/example.tsx @@ -9,13 +9,13 @@ import { rollingWindow, } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { selectBollingerData } from './selection' const windowSize = 20 const deviationMultiplier = 2 -function bollingerRows(input: ExampleOptions) { +function bollingerRows(input: ChartOptions) { const rows = rollingWindow(selectBollingerData(aapl, input.revision), { size: windowSize, orderBy: 'Date', @@ -29,59 +29,46 @@ function bollingerRows(input: ExampleOptions) { return rows } -function bollingerChart( - rows: readonly ReturnType[number][], -) { - return defineChart({ - marks: [ - areaY(rows, { - id: 'bollinger-band', - x: 'Date', - y1: (row) => row.meanClose - row.closeDeviation * deviationMultiplier, - y2: (row) => row.meanClose + row.closeDeviation * deviationMultiplier, - fill: '#7c3aed', - fillOpacity: 0.18, - }), - lineY(rows, { - id: 'bollinger-mean', - x: 'Date', - y: 'meanClose', - stroke: '#7c3aed', - strokeWidth: 2.25, - }), - ], - x: { scale: scaleUtc, axis: { label: 'Date' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Apple close (USD)' } }, - }) -} - -export const bollingerDefinition = (input: ExampleOptions) => - bollingerChart(bollingerRows(input)) - -export const catalogBollingerDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = bollingerRows(input) - return bollingerChart(rows) + + return defineChart( + { + marks: [ + areaY(rows, { + id: 'bollinger-band', + x: 'Date', + y1: (row) => row.meanClose - row.closeDeviation * deviationMultiplier, + y2: (row) => row.meanClose + row.closeDeviation * deviationMultiplier, + fill: '#7c3aed', + fillOpacity: 0.18, + }), + lineY(rows, { + id: 'bollinger-mean', + x: 'Date', + y: 'meanClose', + stroke: '#7c3aed', + strokeWidth: 2.25, + }), + ], + x: { scale: scaleUtc, axis: { label: 'Date' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Apple close (USD)' }, + }, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Twenty-day Apple Bollinger band' -export const createExampleChart = (options: ExampleOptions) => - defineChart(catalogBollingerDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/22-bollinger-band/plot.ts b/benchmarks/conformance/cases/22-bollinger-band/plot.ts index 50e9d4e1..e791464b 100644 --- a/benchmarks/conformance/cases/22-bollinger-band/plot.ts +++ b/benchmarks/conformance/cases/22-bollinger-band/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' import { selectBollingerData } from './selection' diff --git a/benchmarks/conformance/cases/22-bollinger-band/selection.ts b/benchmarks/conformance/cases/22-bollinger-band/selection.ts index 0be73657..299ab030 100644 --- a/benchmarks/conformance/cases/22-bollinger-band/selection.ts +++ b/benchmarks/conformance/cases/22-bollinger-band/selection.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export function selectBollingerData(rows: readonly AaplRow[], revision = 0) { const offset = Math.abs(revision) % 2 diff --git a/benchmarks/conformance/cases/22-bollinger-band/tanstack.test.ts b/benchmarks/conformance/cases/22-bollinger-band/tanstack.test.ts index 4b018627..e0208f6c 100644 --- a/benchmarks/conformance/cases/22-bollinger-band/tanstack.test.ts +++ b/benchmarks/conformance/cases/22-bollinger-band/tanstack.test.ts @@ -1,16 +1,16 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { aapl } from '@charts-poc/demo-data/aapl' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import { createChartRuntime } from '@tanstack/charts' import type { ChartSpecDatum } from '@tanstack/charts' import { deviation, mean } from 'd3-array' import { describe, expect, expectTypeOf, it } from 'vitest' import type { ConformanceInput } from '../../types' import { selectBollingerData } from './selection' -import { bollingerDefinition } from './tanstack' +import { createExampleChart } from './tanstack' -type BollingerDatum = ChartSpecDatum> +type BollingerDatum = ChartSpecDatum> describe('definition-owned Bollinger band', () => { it.each([0, 1])( @@ -100,7 +100,7 @@ function render(revision: number) { revision, } satisfies ConformanceInput return createChartRuntime().render( - bollingerDefinition(input), + createExampleChart(input), input, ) } diff --git a/benchmarks/conformance/cases/24-quantitative-binned-heatmap/example.tsx b/benchmarks/conformance/cases/24-quantitative-binned-heatmap/example.tsx index 663f2082..d0b75e56 100644 --- a/benchmarks/conformance/cases/24-quantitative-binned-heatmap/example.tsx +++ b/benchmarks/conformance/cases/24-quantitative-binned-heatmap/example.tsx @@ -1,10 +1,10 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { binXY, colorGradientLegend, defineChart, rect } from '@tanstack/charts' import { scaleLinear, scaleSequential } from 'd3-scale' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' type PenguinBill = PenguinsRow & { readonly culmen_length_mm: number @@ -13,7 +13,7 @@ type PenguinBill = PenguinsRow & { const xBoundaries = [30, 34, 38, 42, 46, 50, 54, 58, 62] const yBoundaries = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = penguins .filter((row): row is PenguinBill => { return row.culmen_length_mm !== null && row.culmen_depth_mm !== null @@ -28,60 +28,54 @@ export const definition = (input: ExampleOptions) => { outputs: { count: { reduce: 'count' } }, }).filter((cell) => cell.count > 0) - return defineChart({ - marks: [ - rect(cells, { - x1: 'x1', - x2: 'x2', - y1: 'y1', - y2: 'y2', - color: 'count', - inset: 0.75, - }), - ], - x: { - scale: scaleLinear().domain([30, 62]), - grid: true, - axis: { label: 'Bill length (mm)' }, - }, - y: { - scale: scaleLinear().domain([12, 23]), - grid: true, - axis: { label: 'Bill depth (mm)' }, + return defineChart( + { + marks: [ + rect(cells, { + x1: 'x1', + x2: 'x2', + y1: 'y1', + y2: 'y2', + color: 'count', + inset: 0.75, + }), + ], + x: { + scale: scaleLinear().domain([30, 62]), + grid: true, + axis: { label: 'Bill length (mm)' }, + }, + y: { + scale: scaleLinear().domain([12, 23]), + grid: true, + axis: { label: 'Bill depth (mm)' }, + }, + color: { + scale: scaleSequential, + range: ['#eff6ff', '#1d4ed8'], + legend: colorGradientLegend({ label: 'Count', steps: 5 }), + }, }, - color: { - scale: scaleSequential, - range: ['#eff6ff', '#1d4ed8'], - legend: colorGradientLegend({ label: 'Count', steps: 5 }), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `Bill length: ${point.datum.x1}–${point.datum.x2} mm · Bill depth: ${point.datum.y1}–${point.datum.y2} mm · Penguins: ${point.datum.count}`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Quantitative two-dimensional binned heatmap' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `Bill length: ${point.datum.x1}–${point.datum.x2} mm · Bill depth: ${point.datum.y1}–${point.datum.y2} mm · Penguins: ${point.datum.count}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/24-quantitative-binned-heatmap/plot.ts b/benchmarks/conformance/cases/24-quantitative-binned-heatmap/plot.ts index 334078e4..a1974d7e 100644 --- a/benchmarks/conformance/cases/24-quantitative-binned-heatmap/plot.ts +++ b/benchmarks/conformance/cases/24-quantitative-binned-heatmap/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/25-calendar-heatmap/example.tsx b/benchmarks/conformance/cases/25-calendar-heatmap/example.tsx index 583c339f..26411490 100644 --- a/benchmarks/conformance/cases/25-calendar-heatmap/example.tsx +++ b/benchmarks/conformance/cases/25-calendar-heatmap/example.tsx @@ -2,67 +2,58 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { cell, colorGradientLegend, defineChart } from '@tanstack/charts' -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { scaleBand, scaleSequential } from 'd3-scale' import { utcSunday } from 'd3-time' import { selectCalendarData } from './selection' const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = selectCalendarData(weather, input.revision) const calendarStart = rows[0]?.date if (calendarStart === undefined) { throw new TypeError('The weather calendar selection is empty') } - return defineChart({ - marks: [ - cell(rows, { - x: (row) => utcSunday.count(calendarStart, row.date), - y: (row) => weekdays[row.date.getUTCDay()], - color: 'precipitation', - inset: 1, - radius: 2, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.06).paddingOuter(0.03), - axis: { ticks: { format: (value) => `W${value + 1}` }, label: 'Week' }, + return defineChart( + { + marks: [ + cell(rows, { + x: (row) => utcSunday.count(calendarStart, row.date), + y: (row) => weekdays[row.date.getUTCDay()], + color: 'precipitation', + inset: 1, + radius: 2, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.06).paddingOuter(0.03), + axis: { ticks: { format: (value) => `W${value + 1}` }, label: 'Week' }, + }, + y: { + scale: scaleBand() + .domain(weekdays) + .paddingInner(0.06) + .paddingOuter(0.03), + }, + color: { + scale: scaleSequential, + range: ['#ecfdf5', '#047857'], + legend: colorGradientLegend({ label: 'Precipitation (mm)', steps: 6 }), + }, }, - y: { - scale: scaleBand() - .domain(weekdays) - .paddingInner(0.06) - .paddingOuter(0.03), - }, - color: { - scale: scaleSequential, - range: ['#ecfdf5', '#047857'], - legend: colorGradientLegend({ label: 'Precipitation (mm)', steps: 6 }), - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Fourteen-week Seattle precipitation heatmap' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/25-calendar-heatmap/plot.ts b/benchmarks/conformance/cases/25-calendar-heatmap/plot.ts index 1e52301d..d1fe26bf 100644 --- a/benchmarks/conformance/cases/25-calendar-heatmap/plot.ts +++ b/benchmarks/conformance/cases/25-calendar-heatmap/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { utcSunday } from 'd3-time' import { selectCalendarData } from './selection' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/25-calendar-heatmap/selection.ts b/benchmarks/conformance/cases/25-calendar-heatmap/selection.ts index 1a31b18b..dbef89fa 100644 --- a/benchmarks/conformance/cases/25-calendar-heatmap/selection.ts +++ b/benchmarks/conformance/cases/25-calendar-heatmap/selection.ts @@ -1,4 +1,4 @@ -import type { WeatherRow } from '@charts-poc/demo-data/weather' +import type { WeatherRow } from '@tanstack/charts-data/weather' const daysPerView = 98 diff --git a/benchmarks/conformance/cases/26-diverging-likert/example.tsx b/benchmarks/conformance/cases/26-diverging-likert/example.tsx index 27c6b6d6..f991af0f 100644 --- a/benchmarks/conformance/cases/26-diverging-likert/example.tsx +++ b/benchmarks/conformance/cases/26-diverging-likert/example.tsx @@ -9,7 +9,7 @@ import { ruleX, stack, } from '@tanstack/charts' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { scaleBand, scaleLinear } from 'd3-scale' import { likertResponses, selectLikertSurvey } from './selection' @@ -21,50 +21,47 @@ export const likertCounts = groupBy(likertSurvey, { outputs: { count: { reduce: 'count' } }, }) -export const likertDefinition = () => - defineChart({ - marks: [ - barX(likertCounts, { - id: 'likert-responses', - x: 'count', - y: 'Question', - z: 'Response', - color: 'Response', - layout: stack({ - order: likertResponses, - anchor: { series: 'Neutral', fraction: 0.5 }, +export const createExampleChart = () => + defineChart( + { + marks: [ + barX(likertCounts, { + id: 'likert-responses', + x: 'count', + y: 'Question', + z: 'Response', + color: 'Response', + layout: stack({ + order: likertResponses, + anchor: { series: 'Neutral', fraction: 0.5 }, + }), + key: (row) => `${row.Question}:${row.Response}`, + inset: 0.75, }), - key: (row) => `${row.Question}:${row.Response}`, - inset: 0.75, - }), - ruleX([0], { stroke: '#64748b' }), - ], - x: { - scale: scaleLinear, - grid: true, - axis: { - ticks: { format: (value) => `${Math.abs(value)}` }, - label: '← more disagree · Number of responses · more agree →', + ruleX([0], { stroke: '#64748b' }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { + ticks: { format: (value) => `${Math.abs(value)}` }, + label: '← more disagree · Number of responses · more agree →', + }, + }, + y: { + scale: () => scaleBand().paddingInner(0.14).paddingOuter(0.08), + }, + color: { + domain: likertResponses, + range: colors, + legend: colorLegend({ label: 'Response' }), }, }, - y: { - scale: () => scaleBand().paddingInner(0.14).paddingOuter(0.08), - }, - color: { - domain: likertResponses, - range: colors, - legend: colorLegend({ label: 'Response' }), - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) export const exampleAriaLabel = 'Diverging Likert survey responses' -export const createExampleChart = () => - defineChart(likertDefinition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/26-diverging-likert/plot.ts b/benchmarks/conformance/cases/26-diverging-likert/plot.ts index 5309bb39..a8f61d82 100644 --- a/benchmarks/conformance/cases/26-diverging-likert/plot.ts +++ b/benchmarks/conformance/cases/26-diverging-likert/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { likertResponses, selectLikertSurvey } from './selection' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/26-diverging-likert/selection.ts b/benchmarks/conformance/cases/26-diverging-likert/selection.ts index 44336613..8988d221 100644 --- a/benchmarks/conformance/cases/26-diverging-likert/selection.ts +++ b/benchmarks/conformance/cases/26-diverging-likert/selection.ts @@ -1,4 +1,4 @@ -import type { SurveyRow } from '@charts-poc/demo-data/survey' +import type { SurveyRow } from '@tanstack/charts-data/survey' export type LikertResponse = 'Strongly Disagree' | 'Disagree' | 'Neutral' | 'Agree' | 'Strongly Agree' diff --git a/benchmarks/conformance/cases/26-diverging-likert/tanstack.test.ts b/benchmarks/conformance/cases/26-diverging-likert/tanstack.test.ts index fb0d60a9..28c10eff 100644 --- a/benchmarks/conformance/cases/26-diverging-likert/tanstack.test.ts +++ b/benchmarks/conformance/cases/26-diverging-likert/tanstack.test.ts @@ -1,6 +1,6 @@ import { existsSync, readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { @@ -9,7 +9,7 @@ import { selectLikertSurvey, } from './selection' import type { LikertSurveyRow } from './selection' -import { likertCounts, likertDefinition } from './tanstack' +import { likertCounts, createExampleChart } from './tanstack' type LikertCount = (typeof likertCounts)[number] @@ -96,7 +96,7 @@ describe('definition-owned anchored Likert stack', () => { function render() { return createChartRuntime().render( - likertDefinition(), + createExampleChart(), { width: 640, height: 400 }, ) } diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/example.tsx b/benchmarks/conformance/cases/27-parallel-coordinates/example.tsx index edf3ec18..169f2921 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/example.tsx +++ b/benchmarks/conformance/cases/27-parallel-coordinates/example.tsx @@ -10,7 +10,7 @@ import { select, } from '@tanstack/charts' import { fold } from '@tanstack/charts/transform/fold' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { scaleBand, scaleLinear } from 'd3-scale' import { decathlonEvents, timedEvents } from './selection' @@ -40,48 +40,45 @@ export const representativeProfiles = select(normalizedDecathlon, { select: 'last', }) -export const parallelCoordinatesDefinition = () => - defineChart({ - marks: [ - lineY(representativeProfiles, { - id: 'country-lines', - x: 'event', - y: ({ relativePerformance }) => relativePerformance * 100, - color: 'Country', - key: ({ Country, event }) => `${Country}:${event}`, - strokeWidth: 1.75, - }), - dot(representativeProfiles, { - id: 'country-points', - x: 'event', - y: ({ relativePerformance }) => relativePerformance * 100, - color: 'Country', - key: ({ Country, event }) => `${Country}:${event}`, - r: 2.75, - }), - ], - x: { - scale: scaleBand().domain(decathlonEvents).padding(0.1), - }, - y: { - scale: scaleLinear().domain([0, 100]), - grid: true, - axis: { label: 'Relative performance within sample' }, - }, - color: { - range: colors, - legend: colorLegend({ label: 'Country' }), +export const createExampleChart = () => + defineChart( + { + marks: [ + lineY(representativeProfiles, { + id: 'country-lines', + x: 'event', + y: ({ relativePerformance }) => relativePerformance * 100, + color: 'Country', + key: ({ Country, event }) => `${Country}:${event}`, + strokeWidth: 1.75, + }), + dot(representativeProfiles, { + id: 'country-points', + x: 'event', + y: ({ relativePerformance }) => relativePerformance * 100, + color: 'Country', + key: ({ Country, event }) => `${Country}:${event}`, + r: 2.75, + }), + ], + x: { + scale: scaleBand().domain(decathlonEvents).padding(0.1), + }, + y: { + scale: scaleLinear().domain([0, 100]), + grid: true, + axis: { label: 'Relative performance within sample' }, + }, + color: { + range: colors, + legend: colorLegend({ label: 'Country' }), + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) export const exampleAriaLabel = 'Parallel coordinates model comparison' -export const createExampleChart = () => - defineChart(parallelCoordinatesDefinition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/plot.ts b/benchmarks/conformance/cases/27-parallel-coordinates/plot.ts index 152a5995..b3368759 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/plot.ts +++ b/benchmarks/conformance/cases/27-parallel-coordinates/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { decathlonEvents, selectRepresentativeDecathletes } from './selection' import { normalizeDecathlonResults } from './transform' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/selection.ts b/benchmarks/conformance/cases/27-parallel-coordinates/selection.ts index a6eb1af7..0141be4b 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/selection.ts +++ b/benchmarks/conformance/cases/27-parallel-coordinates/selection.ts @@ -1,4 +1,4 @@ -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' export const decathlonEvents = [ '100 Meters', diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/tanstack.test.ts b/benchmarks/conformance/cases/27-parallel-coordinates/tanstack.test.ts index 577d2812..24bed258 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/tanstack.test.ts +++ b/benchmarks/conformance/cases/27-parallel-coordinates/tanstack.test.ts @@ -1,13 +1,13 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { describe, expect, it } from 'vitest' import { decathlonEvents, timedEvents } from './selection' import { foldedDecathlon, normalizedDecathlon, - parallelCoordinatesDefinition, + createExampleChart, representativeProfiles, } from './tanstack' @@ -94,7 +94,7 @@ describe('folded parallel coordinates', () => { }) function render() { - return createChartRuntime().render(parallelCoordinatesDefinition(), { + return createChartRuntime().render(createExampleChart(), { width: 640, height: 400, }) diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/transform.test.ts b/benchmarks/conformance/cases/27-parallel-coordinates/transform.test.ts index b5c1e070..0e5aed9a 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/transform.test.ts +++ b/benchmarks/conformance/cases/27-parallel-coordinates/transform.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { selectRepresentativeDecathletes } from './selection' import { normalizeDecathlonResults } from './transform' diff --git a/benchmarks/conformance/cases/27-parallel-coordinates/transform.ts b/benchmarks/conformance/cases/27-parallel-coordinates/transform.ts index 9aa8c75b..6c7dd09b 100644 --- a/benchmarks/conformance/cases/27-parallel-coordinates/transform.ts +++ b/benchmarks/conformance/cases/27-parallel-coordinates/transform.ts @@ -1,6 +1,6 @@ import { extent } from 'd3-array' import { decathlonEvents, timedEvents } from './selection' -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' import type { DecathlonEvent } from './selection' export interface NormalizedDecathlonResult { diff --git a/benchmarks/conformance/cases/28-candlestick/example.tsx b/benchmarks/conformance/cases/28-candlestick/example.tsx index bd5ca819..229604c1 100644 --- a/benchmarks/conformance/cases/28-candlestick/example.tsx +++ b/benchmarks/conformance/cases/28-candlestick/example.tsx @@ -2,7 +2,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, link } from '@tanstack/charts' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { scaleLinear, scaleUtc } from 'd3-scale' import { selectCandleData } from './selection' @@ -17,67 +17,61 @@ const price = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2, }) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = selectCandleData(aapl, input.revision) const gains = rows.filter((row) => row.Close >= row.Open) const losses = rows.filter((row) => row.Close < row.Open) - return defineChart({ - marks: [ - link(rows, { - x1: 'Date', - y1: 'Low', - x2: 'Date', - y2: 'High', - stroke: '#64748b', - strokeWidth: 1, - }), - link(gains, { - x1: 'Date', - y1: 'Open', - x2: 'Date', - y2: 'Close', - stroke: '#10b981', - strokeWidth: 5, - }), - link(losses, { - x1: 'Date', - y1: 'Open', - x2: 'Date', - y2: 'Close', - stroke: '#ef4444', - strokeWidth: 5, - }), - ], - x: { scale: scaleUtc }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Price' } }, - }) + return defineChart( + { + marks: [ + link(rows, { + x1: 'Date', + y1: 'Low', + x2: 'Date', + y2: 'High', + stroke: '#64748b', + strokeWidth: 1, + }), + link(gains, { + x1: 'Date', + y1: 'Open', + x2: 'Date', + y2: 'Close', + stroke: '#10b981', + strokeWidth: 5, + }), + link(losses, { + x1: 'Date', + y1: 'Open', + x2: 'Date', + y2: 'Close', + stroke: '#ef4444', + strokeWidth: 5, + }), + ], + x: { scale: scaleUtc }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Price' } }, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `${candleDate.format(point.datum.Date)} · Open: ${price.format(point.datum.Open)} · High: ${price.format(point.datum.High)} · Low: ${price.format(point.datum.Low)} · Close: ${price.format(point.datum.Close)}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Apple daily candlestick chart' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `${candleDate.format(point.datum.Date)} · Open: ${price.format(point.datum.Open)} · High: ${price.format(point.datum.High)} · Low: ${price.format(point.datum.Low)} · Close: ${price.format(point.datum.Close)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/28-candlestick/plot.ts b/benchmarks/conformance/cases/28-candlestick/plot.ts index e709349c..33a85d3a 100644 --- a/benchmarks/conformance/cases/28-candlestick/plot.ts +++ b/benchmarks/conformance/cases/28-candlestick/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { selectCandleData } from './selection' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/28-candlestick/selection.ts b/benchmarks/conformance/cases/28-candlestick/selection.ts index d61d84ee..c2928a9d 100644 --- a/benchmarks/conformance/cases/28-candlestick/selection.ts +++ b/benchmarks/conformance/cases/28-candlestick/selection.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' const sessionsPerView = 30 diff --git a/benchmarks/conformance/cases/29-waterfall/example.tsx b/benchmarks/conformance/cases/29-waterfall/example.tsx index aa299583..06bdf72a 100644 --- a/benchmarks/conformance/cases/29-waterfall/example.tsx +++ b/benchmarks/conformance/cases/29-waterfall/example.tsx @@ -8,11 +8,13 @@ import { delta, ruleY, rollingWindow, + type ChartPoint, } from '@tanstack/charts' import { waterfall } from '@tanstack/charts/transform/waterfall' +import { decorative } from '@tanstack/charts/mark/decorative' import type { WaterfallKind } from '@tanstack/charts/transform/waterfall' import { scaleBand, scaleLinear } from 'd3-scale' -import { driving } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' const kinds = [ 'increase', @@ -50,48 +52,45 @@ export const waterfallRows = waterfall(yearlyChanges, { total: true, }) -export const waterfallDefinition = () => - defineChart(({ width }) => { - return { - marks: [ - barY(waterfallRows, { - id: 'waterfall-bars', - x: (datum) => (datum.kind === 'total' ? totalLabel : `${datum.year}`), - y1: 'start', - y2: 'end', - color: 'kind', - key: (datum) => - datum.kind === 'total' ? 'net-total' : `${datum.year}`, - inset: 1, - }), - ruleY([0], { stroke: '#64748b', strokeOpacity: 0.6 }), - ], - x: { - scale: () => scaleBand().padding(0.14), - axis: { tickLabels: { rotate: width < 560 ? -32 : 0 } }, - }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Change in gasoline price (USD per gallon)' }, - }, - color: { - domain: kinds, - range: colors, - legend: colorLegend({ label: 'Change' }), - }, - } - }) - -export const exampleAriaLabel = 'Annual changes in U.S. gasoline prices' - export const createExampleChart = () => - defineChart(waterfallDefinition(), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => + defineChart( + ({ width }) => { + return { + marks: [ + barY(waterfallRows, { + id: 'waterfall-bars', + x: (datum) => + datum.kind === 'total' ? totalLabel : `${datum.year}`, + y1: 'start', + y2: 'end', + color: 'kind', + key: (datum) => + datum.kind === 'total' ? 'net-total' : `${datum.year}`, + inset: 1, + }), + decorative(ruleY([0], { stroke: '#64748b', strokeOpacity: 0.6 })), + ] as const, + x: { + scale: () => scaleBand().padding(0.14), + axis: { tickLabels: { rotate: width < 560 ? -32 : 0 } }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Change in gasoline price (USD per gallon)' }, + }, + color: { + domain: kinds, + range: colors, + legend: colorLegend({ label: 'Change' }), + }, + } + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + format: ({ datum }: ChartPoint<(typeof waterfallRows)[number]>) => datum.kind === 'total' ? `${totalLabel} · ${signedAmount.format(datum.end)} net change` : `${datum.year} · ${signedAmount.format( @@ -99,7 +98,9 @@ export const createExampleChart = () => )} · ${signedAmount.format(datum.end)} running change`, }, }, - }) + ) + +export const exampleAriaLabel = 'Annual changes in U.S. gasoline prices' export const chart = createExampleChart() diff --git a/benchmarks/conformance/cases/29-waterfall/plot.ts b/benchmarks/conformance/cases/29-waterfall/plot.ts index c2930f94..3e2086aa 100644 --- a/benchmarks/conformance/cases/29-waterfall/plot.ts +++ b/benchmarks/conformance/cases/29-waterfall/plot.ts @@ -1,7 +1,7 @@ import * as Plot from '@observablehq/plot' import { pairs } from 'd3-array' -import { driving } from '@charts-poc/demo-data/driving' -import type { DrivingRow } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' +import type { DrivingRow } from '@tanstack/charts-data/driving' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/29-waterfall/tanstack.test.ts b/benchmarks/conformance/cases/29-waterfall/tanstack.test.ts index 68585dad..08b29d38 100644 --- a/benchmarks/conformance/cases/29-waterfall/tanstack.test.ts +++ b/benchmarks/conformance/cases/29-waterfall/tanstack.test.ts @@ -1,9 +1,9 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { driving } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { waterfallDefinition, waterfallRows, yearlyChanges } from './tanstack' +import { createExampleChart, waterfallRows, yearlyChanges } from './tanstack' type WaterfallRow = (typeof waterfallRows)[number] @@ -60,7 +60,7 @@ describe('definition-owned waterfall layout', () => { WaterfallRow | number, string, number - >().render(waterfallDefinition(), { width: 640, height: 400 }) + >().render(createExampleChart(), { width: 640, height: 400 }) const bars = scene.points.filter( ({ markId }) => markId === 'waterfall-bars', ) diff --git a/benchmarks/conformance/cases/30-slopegraph/example.tsx b/benchmarks/conformance/cases/30-slopegraph/example.tsx index 55a0ab73..9ca8965a 100644 --- a/benchmarks/conformance/cases/30-slopegraph/example.tsx +++ b/benchmarks/conformance/cases/30-slopegraph/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import { defineChart, dot, lineY, select, text } from '@tanstack/charts' import { fold } from '@tanstack/charts/transform/fold' import { scaleBand, scaleLinear } from 'd3-scale' @@ -28,7 +28,7 @@ const previewLabelOffsets = new Map([ ['Miami', 24], ]) -export const slopegraphDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const source = citywages.slice(input.revision * 4, input.revision * 4 + 8) const rows = fold(source, { fields: wageFields, @@ -39,75 +39,68 @@ export const slopegraphDefinition = (input: ExampleOptions) => { select: 'last', }) - return defineChart({ - marks: [ - lineY(rows, { - id: 'metro-lines', - x: ({ wageField }) => wageYear(wageField), - y: 'inequality', - color: 'nyt_display', - key: ({ Metro, wageField }) => `${Metro}:${wageField}`, - }), - dot(rows, { - id: 'metro-points', - x: ({ wageField }) => wageYear(wageField), - y: 'inequality', - color: 'nyt_display', - key: ({ Metro, wageField }) => `${Metro}:${wageField}`, - r: 3, - }), - text(labels, { - id: 'endpoint-labels', - x: ({ wageField }) => wageYear(wageField), - y: 'inequality', - text: 'nyt_display', - color: 'nyt_display', - key: ({ Metro, wageField }) => `${Metro}:${wageField}`, - dx: ({ wageField }) => - input.preview === true && wageField === wageFields[1] ? -6 : 6, - anchor: ({ wageField }) => - input.preview === true && wageField === wageFields[1] - ? 'end' - : 'start', - dy: ({ nyt_display }) => - input.preview === true - ? (previewLabelOffsets.get(nyt_display) ?? 0) - : 0, - fontSize: input.preview === true ? 9 : 12, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.08), + return defineChart( + { + marks: [ + lineY(rows, { + id: 'metro-lines', + x: ({ wageField }) => wageYear(wageField), + y: 'inequality', + color: 'nyt_display', + key: ({ Metro, wageField }) => `${Metro}:${wageField}`, + }), + dot(rows, { + id: 'metro-points', + x: ({ wageField }) => wageYear(wageField), + y: 'inequality', + color: 'nyt_display', + key: ({ Metro, wageField }) => `${Metro}:${wageField}`, + r: 3, + }), + text(labels, { + id: 'endpoint-labels', + x: ({ wageField }) => wageYear(wageField), + y: 'inequality', + text: 'nyt_display', + color: 'nyt_display', + key: ({ Metro, wageField }) => `${Metro}:${wageField}`, + dx: ({ wageField }) => + input.preview === true && wageField === wageFields[1] ? -6 : 6, + anchor: ({ wageField }) => + input.preview === true && wageField === wageFields[1] + ? 'end' + : 'start', + dy: ({ nyt_display }) => + input.preview === true + ? (previewLabelOffsets.get(nyt_display) ?? 0) + : 0, + fontSize: input.preview === true ? 9 : 12, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.08), + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: '90th/10th percentile wage ratio' }, + }, + color: { + range: colors, + }, + margin: { right: 76 }, }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: '90th/10th percentile wage ratio' }, - }, - color: { - range: colors, - }, - margin: { right: 76 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Metropolitan wage inequality, 1980 to 2015' -export const createExampleChart = (options: ExampleOptions) => - defineChart(slopegraphDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/30-slopegraph/plot.ts b/benchmarks/conformance/cases/30-slopegraph/plot.ts index e352da94..9b38a488 100644 --- a/benchmarks/conformance/cases/30-slopegraph/plot.ts +++ b/benchmarks/conformance/cases/30-slopegraph/plot.ts @@ -1,4 +1,4 @@ -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import * as Plot from '@observablehq/plot' import { toSlopePoints } from './transform' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/30-slopegraph/tanstack.test.ts b/benchmarks/conformance/cases/30-slopegraph/tanstack.test.ts index ce7f5264..9e1c819e 100644 --- a/benchmarks/conformance/cases/30-slopegraph/tanstack.test.ts +++ b/benchmarks/conformance/cases/30-slopegraph/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import { describe, expect, it } from 'vitest' import { wageFields } from './selection' -import { slopegraphDefinition } from './tanstack' -import type { CitywagesRow } from '@charts-poc/demo-data/citywages' +import { createExampleChart } from './tanstack' +import type { CitywagesRow } from '@tanstack/charts-data/citywages' import type { ChartPoint, ChartScene } from '@tanstack/charts' import type { ConformanceInput } from '../../types' import type { WageField } from './selection' @@ -83,7 +83,7 @@ describe('folded slopegraph', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(slopegraphDefinition(nextInput), { + return createChartRuntime().render(createExampleChart(nextInput), { width: nextInput.width, height: nextInput.height, }) diff --git a/benchmarks/conformance/cases/30-slopegraph/transform.ts b/benchmarks/conformance/cases/30-slopegraph/transform.ts index ee3f8cc2..bd2657b1 100644 --- a/benchmarks/conformance/cases/30-slopegraph/transform.ts +++ b/benchmarks/conformance/cases/30-slopegraph/transform.ts @@ -1,4 +1,4 @@ -import type { CitywagesRow } from '@charts-poc/demo-data/citywages' +import type { CitywagesRow } from '@tanstack/charts-data/citywages' import { wageFields, wageYear } from './selection' export interface SlopePoint { diff --git a/benchmarks/conformance/cases/31-linear-regression/example.tsx b/benchmarks/conformance/cases/31-linear-regression/example.tsx index a307155d..5e443499 100644 --- a/benchmarks/conformance/cases/31-linear-regression/example.tsx +++ b/benchmarks/conformance/cases/31-linear-regression/example.tsx @@ -1,10 +1,10 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart, dot, linearRegressionY } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' type CompleteCar = CarsRow & { 'power (hp)': number @@ -16,80 +16,66 @@ export const completeCars = cars.filter( row['power (hp)'] !== null && row['economy (mpg)'] !== null, ) -function regressionRows(input: ExampleOptions) { - return completeCars.slice(input.revision * 8, input.revision * 8 + 320) -} +export const createExampleChart = (input: ChartOptions) => { + const rows = completeCars.slice(input.revision * 8, input.revision * 8 + 320) + const scatterRows = rows -function regressionChart( - rows: readonly CompleteCar[], - scatterRows: readonly CompleteCar[], -) { - return defineChart({ - marks: [ - dot(scatterRows, { - x: 'power (hp)', - y: 'economy (mpg)', - key: (row) => JSON.stringify([row.name, row.year, row['weight (lb)']]), - fill: '#93c5fd', - stroke: '#2563eb', - r: 3, - }), - linearRegressionY(rows, { - id: 'regression', - x: 'power (hp)', - y: 'economy (mpg)', - ci: 0, - stroke: '#dc2626', - strokeWidth: 2, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Power (hp)' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Fuel economy (mpg)' }, + return defineChart( + { + marks: [ + dot(scatterRows, { + x: 'power (hp)', + y: 'economy (mpg)', + key: (row) => + JSON.stringify([row.name, row.year, row['weight (lb)']]), + fill: '#93c5fd', + stroke: '#2563eb', + r: 3, + }), + linearRegressionY(rows, { + id: 'regression', + x: 'power (hp)', + y: 'economy (mpg)', + ci: 0, + stroke: '#dc2626', + strokeWidth: 2, + }), + ], + x: { scale: scaleLinear, grid: true, axis: { label: 'Power (hp)' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Fuel economy (mpg)' }, + }, }, - }) -} - -export const regressionDefinition = (input: ExampleOptions) => { - const rows = regressionRows(input) - return regressionChart(rows, rows) + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'name' in datum + ? `${datum.name} · ${datum['power (hp)'].toLocaleString( + 'en-US', + )} hp · ${datum['economy (mpg)'].toLocaleString('en-US')} mpg` + : `Regression · ${datum.x.toLocaleString( + 'en-US', + )} hp · predicted ${datum.y.toLocaleString('en-US', { + maximumFractionDigits: 1, + })} mpg`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Scatterplot with linear regression' -export const createExampleChart = (options: ExampleOptions) => - defineChart(regressionDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'name' in datum - ? `${datum.name} · ${datum['power (hp)'].toLocaleString( - 'en-US', - )} hp · ${datum['economy (mpg)'].toLocaleString('en-US')} mpg` - : `Regression · ${datum.x.toLocaleString( - 'en-US', - )} hp · predicted ${datum.y.toLocaleString('en-US', { - maximumFractionDigits: 1, - })} mpg`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/31-linear-regression/plot.ts b/benchmarks/conformance/cases/31-linear-regression/plot.ts index 3b9a07b2..520e7fea 100644 --- a/benchmarks/conformance/cases/31-linear-regression/plot.ts +++ b/benchmarks/conformance/cases/31-linear-regression/plot.ts @@ -1,7 +1,7 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' import type { ConformanceMount } from '../../types' type CompleteCar = CarsRow & { diff --git a/benchmarks/conformance/cases/31-linear-regression/tanstack.test.ts b/benchmarks/conformance/cases/31-linear-regression/tanstack.test.ts index adcb5c1d..c1bf1920 100644 --- a/benchmarks/conformance/cases/31-linear-regression/tanstack.test.ts +++ b/benchmarks/conformance/cases/31-linear-regression/tanstack.test.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { completeCars, regressionDefinition } from './tanstack' +import { completeCars, createExampleChart } from './tanstack' import type { ConformanceInput } from '../../types' type CompleteCar = (typeof completeCars)[number] @@ -90,7 +90,7 @@ describe('definition-owned linear regression', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(regressionDefinition(nextInput), { + return createChartRuntime().render(createExampleChart(nextInput), { width: nextInput.width, height: nextInput.height, }) diff --git a/benchmarks/conformance/cases/32-change-arrows/example.tsx b/benchmarks/conformance/cases/32-change-arrows/example.tsx index 135e592f..f467559d 100644 --- a/benchmarks/conformance/cases/32-change-arrows/example.tsx +++ b/benchmarks/conformance/cases/32-change-arrows/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { arrow, defineChart } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' const metroChanges = citywages.filter( (row) => @@ -12,50 +12,51 @@ const metroChanges = citywages.filter( row.nyt_display === 'Los Angeles', ) -export const definition = () => { +export const createExampleChart = () => { const increases = metroChanges.filter( (row) => row.R90_10_2015 >= row.R90_10_1980, ) const decreases = metroChanges.filter( (row) => row.R90_10_2015 < row.R90_10_1980, ) - return defineChart({ - marks: [ - arrow(increases, { - x1: 'LPOP_1980', - y1: 'R90_10_1980', - x2: 'LPOP_2015', - y2: 'R90_10_2015', - stroke: '#ef4444', - headLength: 8, - }), - arrow(decreases, { - x1: 'LPOP_1980', - y1: 'R90_10_1980', - x2: 'LPOP_2015', - y2: 'R90_10_2015', - stroke: '#10b981', - headLength: 8, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Log₁₀ population' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: '90th-to-10th-percentile wage ratio' }, + return defineChart( + { + marks: [ + arrow(increases, { + x1: 'LPOP_1980', + y1: 'R90_10_1980', + x2: 'LPOP_2015', + y2: 'R90_10_2015', + stroke: '#ef4444', + headLength: 8, + }), + arrow(decreases, { + x1: 'LPOP_1980', + y1: 'R90_10_1980', + x2: 'LPOP_2015', + y2: 'R90_10_2015', + stroke: '#10b981', + headLength: 8, + }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: 'Log₁₀ population' }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: '90th-to-10th-percentile wage ratio' }, + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } export const exampleAriaLabel = 'Metro population and wage inequality, 1980–2015' -export const createExampleChart = () => - defineChart(definition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/32-change-arrows/plot.ts b/benchmarks/conformance/cases/32-change-arrows/plot.ts index ddbd8029..34770df8 100644 --- a/benchmarks/conformance/cases/32-change-arrows/plot.ts +++ b/benchmarks/conformance/cases/32-change-arrows/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/33-difference-chart/example.tsx b/benchmarks/conformance/cases/33-difference-chart/example.tsx index b5541d29..a5bcc9c8 100644 --- a/benchmarks/conformance/cases/33-difference-chart/example.tsx +++ b/benchmarks/conformance/cases/33-difference-chart/example.tsx @@ -1,12 +1,12 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { defineChart, differenceY, rollingWindow } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' import { formatDifferenceMonth } from './model' -export const differenceRows = (input: ExampleOptions) => +export const differenceRows = (input: ChartOptions) => rollingWindow(aapl.slice(input.revision * 10, input.revision * 10 + 120), { size: 20, orderBy: 'Date', @@ -17,54 +17,45 @@ export const differenceRows = (input: ExampleOptions) => }, }) -export const differenceDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = differenceRows(input) - return defineChart({ - marks: [ - differenceY(rows, { - id: 'difference', - x: 'Date', - y1: 'average', - y2: 'Close', - positiveFill: '#16a34a', - negativeFill: '#dc2626', - fillOpacity: 0.35, - stroke: '#166534', - strokeWidth: 2, - comparisonStroke: '#475569', - comparisonStrokeWidth: 2, - }), - ], - x: { - scale: scaleUtc, - axis: { ticks: { count: 9, format: formatDifferenceMonth } }, + return defineChart( + { + marks: [ + differenceY(rows, { + id: 'difference', + x: 'Date', + y1: 'average', + y2: 'Close', + positiveFill: '#16a34a', + negativeFill: '#dc2626', + fillOpacity: 0.35, + stroke: '#166534', + strokeWidth: 2, + comparisonStroke: '#475569', + comparisonStrokeWidth: 2, + }), + ], + x: { + scale: scaleUtc, + axis: { ticks: { count: 9, format: formatDifferenceMonth } }, + }, + y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, + margin: { top: 20, right: 20, bottom: 30, left: 80 }, }, - y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, - margin: { top: 20, right: 20, bottom: 30, left: 80 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Apple closing price versus its twenty-day average' -export const createExampleChart = (options: ExampleOptions) => - defineChart(differenceDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/33-difference-chart/plot.ts b/benchmarks/conformance/cases/33-difference-chart/plot.ts index bec92b74..6ef83068 100644 --- a/benchmarks/conformance/cases/33-difference-chart/plot.ts +++ b/benchmarks/conformance/cases/33-difference-chart/plot.ts @@ -1,4 +1,4 @@ -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import * as Plot from '@observablehq/plot' import { formatDifferenceMonth } from './model' import { rollingCloseAverage } from './transform' diff --git a/benchmarks/conformance/cases/33-difference-chart/tanstack.test.ts b/benchmarks/conformance/cases/33-difference-chart/tanstack.test.ts index 65f16ac9..5b8309ff 100644 --- a/benchmarks/conformance/cases/33-difference-chart/tanstack.test.ts +++ b/benchmarks/conformance/cases/33-difference-chart/tanstack.test.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { differenceDefinition, differenceRows } from './tanstack' +import { createExampleChart, differenceRows } from './tanstack' import type { SceneArea, SceneNode, ScenePolyline } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -102,7 +102,7 @@ describe('definition-owned difference chart', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(differenceDefinition(nextInput), { + return createChartRuntime().render(createExampleChart(nextInput), { width: nextInput.width, height: nextInput.height, }) diff --git a/benchmarks/conformance/cases/33-difference-chart/transform.ts b/benchmarks/conformance/cases/33-difference-chart/transform.ts index 864a33de..a48e919a 100644 --- a/benchmarks/conformance/cases/33-difference-chart/transform.ts +++ b/benchmarks/conformance/cases/33-difference-chart/transform.ts @@ -1,5 +1,5 @@ import { mean } from 'd3-array' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export interface DifferencePoint extends AaplRow { average: number diff --git a/benchmarks/conformance/cases/34-pointer-tooltip/example.tsx b/benchmarks/conformance/cases/34-pointer-tooltip/example.tsx index a9293c51..3f965e5e 100644 --- a/benchmarks/conformance/cases/34-pointer-tooltip/example.tsx +++ b/benchmarks/conformance/cases/34-pointer-tooltip/example.tsx @@ -1,5 +1,5 @@ -import { aapl } from '@charts-poc/demo-data/aapl' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import { defineChart, dot, lineY } from '@tanstack/charts' import { decorative } from '@tanstack/charts/mark/decorative' import { Chart } from '@tanstack/charts/react/tooltip' @@ -8,7 +8,7 @@ import { scaleLinear, scaleUtc } from 'd3-scale' import type { ChartTooltipOptions } from '@tanstack/charts' import { selectPointerTooltipData } from './selection' -export interface ExampleOptions { +export interface ChartOptions { revision?: number } @@ -28,7 +28,7 @@ const interactiveTooltip: ChartTooltipOptions = { ], } -export function createExampleChart({ revision = 0 }: ExampleOptions = {}) { +export function createExampleChart({ revision = 0 }: ChartOptions = {}) { const rows = selectPointerTooltipData(aapl, revision) return defineChart( { diff --git a/benchmarks/conformance/cases/34-pointer-tooltip/plot.ts b/benchmarks/conformance/cases/34-pointer-tooltip/plot.ts index 8bdd2f86..df43f7f0 100644 --- a/benchmarks/conformance/cases/34-pointer-tooltip/plot.ts +++ b/benchmarks/conformance/cases/34-pointer-tooltip/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount, ConformanceTestDriver } from '../../types' import { selectPointerTooltipData } from './selection' diff --git a/benchmarks/conformance/cases/34-pointer-tooltip/selection.ts b/benchmarks/conformance/cases/34-pointer-tooltip/selection.ts index b0e8e7e5..9a686cbf 100644 --- a/benchmarks/conformance/cases/34-pointer-tooltip/selection.ts +++ b/benchmarks/conformance/cases/34-pointer-tooltip/selection.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export function selectPointerTooltipData( rows: readonly AaplRow[], diff --git a/benchmarks/conformance/cases/34-pointer-tooltip/tanstack.ts b/benchmarks/conformance/cases/34-pointer-tooltip/tanstack.ts index 299fcb42..d55096ad 100644 --- a/benchmarks/conformance/cases/34-pointer-tooltip/tanstack.ts +++ b/benchmarks/conformance/cases/34-pointer-tooltip/tanstack.ts @@ -1,6 +1,6 @@ import { mountChart } from '@tanstack/charts' import type { ChartHostOptions } from '@tanstack/charts' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ConformanceHandle, ConformanceInput, diff --git a/benchmarks/conformance/cases/35-grouped-tooltip/example.tsx b/benchmarks/conformance/cases/35-grouped-tooltip/example.tsx index 7d052181..963e2ecb 100644 --- a/benchmarks/conformance/cases/35-grouped-tooltip/example.tsx +++ b/benchmarks/conformance/cases/35-grouped-tooltip/example.tsx @@ -1,4 +1,4 @@ -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { bandX, defineChart, dot, lineY, whenFocused } from '@tanstack/charts' import { decorative } from '@tanstack/charts/mark/decorative' import { Chart } from '@tanstack/charts/react/tooltip' @@ -9,7 +9,7 @@ import type { ChartTooltipOptions } from '@tanstack/charts' import { industryNames, selectGroupedTooltipData } from './selection' import type { GroupedTooltipDatum } from './selection' -export interface ExampleOptions { +export interface ChartOptions { revision?: number } @@ -21,7 +21,7 @@ const interactiveTooltip: ChartTooltipOptions = { sort: 'color-domain', } -export function createExampleChart({ revision = 0 }: ExampleOptions = {}) { +export function createExampleChart({ revision = 0 }: ChartOptions = {}) { const rows = selectGroupedTooltipData(industries, revision) const dates = rows.filter((row) => row.industry === industryNames[0]) return defineChart( diff --git a/benchmarks/conformance/cases/35-grouped-tooltip/plot.ts b/benchmarks/conformance/cases/35-grouped-tooltip/plot.ts index 7600a0f5..b955645a 100644 --- a/benchmarks/conformance/cases/35-grouped-tooltip/plot.ts +++ b/benchmarks/conformance/cases/35-grouped-tooltip/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount, ConformanceTestDriver } from '../../types' import { industryNames, selectGroupedTooltipData } from './selection' diff --git a/benchmarks/conformance/cases/35-grouped-tooltip/selection.ts b/benchmarks/conformance/cases/35-grouped-tooltip/selection.ts index c20f9eb4..d46045cb 100644 --- a/benchmarks/conformance/cases/35-grouped-tooltip/selection.ts +++ b/benchmarks/conformance/cases/35-grouped-tooltip/selection.ts @@ -1,4 +1,4 @@ -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' export const industryNames = ['Manufacturing', 'Construction', 'Finance'] export type IndustryName = (typeof industryNames)[number] diff --git a/benchmarks/conformance/cases/36-hierarchy-tree/example.tsx b/benchmarks/conformance/cases/36-hierarchy-tree/example.tsx index e652906b..1d48c1eb 100644 --- a/benchmarks/conformance/cases/36-hierarchy-tree/example.tsx +++ b/benchmarks/conformance/cases/36-hierarchy-tree/example.tsx @@ -3,97 +3,93 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, dot, link, text } from '@tanstack/charts' import { treeLayout } from '@tanstack/charts/hierarchy/tree' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { scaleLinear } from 'd3-scale' import { selectHierarchyData } from './selection' -export const treeDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const layout = treeLayout(selectHierarchyData(flare, input.revision), { path: 'name', delimiter: '.', }) - return defineChart({ - marks: [ - link(layout.links, { - id: 'hierarchy-links', - x1: 'x1', - y1: 'y1', - x2: 'x2', - y2: 'y2', - key: 'id', - stroke: '#94a3b8', - strokeOpacity: 0.55, - strokeWidth: 1.5, - }), - dot(layout.nodes, { - id: 'hierarchy-nodes', - x: 'x', - y: 'y', - key: 'id', - fill: '#2563eb', - r: 3.5, - }), - text(layout.nodes, { - id: 'hierarchy-labels', - x: 'x', - y: 'y', - text: 'name', - key: 'id', - fill: '#2563eb', - fontSize: input.preview === true ? 8 : 10, - anchor: (node) => - input.preview === true - ? node.internal - ? 'start' - : 'end' - : node.internal - ? 'end' - : 'start', - dx: (node) => - input.preview === true - ? node.internal - ? 4 - : -4 - : node.internal - ? -6 - : 6, - dy: (node) => - input.preview !== true ? 0 : node.y >= 1 ? 5 : node.y <= 0 ? -5 : 0, - }), - ], - x: { scale: scaleLinear }, - y: { scale: scaleLinear }, - guides: false, - margin: { top: 22, right: 140, bottom: 22, left: 50 }, - }) + return defineChart( + { + marks: [ + link(layout.links, { + id: 'hierarchy-links', + x1: 'x1', + y1: 'y1', + x2: 'x2', + y2: 'y2', + key: 'id', + stroke: '#94a3b8', + strokeOpacity: 0.55, + strokeWidth: 1.5, + }), + dot(layout.nodes, { + id: 'hierarchy-nodes', + x: 'x', + y: 'y', + key: 'id', + fill: '#2563eb', + r: 3.5, + }), + text(layout.nodes, { + id: 'hierarchy-labels', + x: 'x', + y: 'y', + text: 'name', + key: 'id', + fill: '#2563eb', + fontSize: input.preview === true ? 8 : 10, + anchor: (node) => + input.preview === true + ? node.internal + ? 'start' + : 'end' + : node.internal + ? 'end' + : 'start', + dx: (node) => + input.preview === true + ? node.internal + ? 4 + : -4 + : node.internal + ? -6 + : 6, + dy: (node) => + input.preview !== true ? 0 : node.y >= 1 ? 5 : node.y <= 0 ? -5 : 0, + }), + ], + x: { scale: scaleLinear }, + y: { scale: scaleLinear }, + guides: false, + margin: { top: 22, right: 140, bottom: 22, left: 50 }, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'internal' in datum + ? `${datum.data?.name ?? datum.name} · ${datum.internal ? 'Group' : 'Leaf'}` + : `${datum.sourceNode.data?.name ?? datum.source} → ${datum.targetNode.data?.name ?? datum.target}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Tidy Flare analytics hierarchy' -export const createExampleChart = (options: ExampleOptions) => - defineChart(treeDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'internal' in datum - ? `${datum.data?.name ?? datum.name} · ${datum.internal ? 'Group' : 'Leaf'}` - : `${datum.sourceNode.data?.name ?? datum.source} → ${datum.targetNode.data?.name ?? datum.target}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/36-hierarchy-tree/plot.ts b/benchmarks/conformance/cases/36-hierarchy-tree/plot.ts index 05cd8191..97b6a082 100644 --- a/benchmarks/conformance/cases/36-hierarchy-tree/plot.ts +++ b/benchmarks/conformance/cases/36-hierarchy-tree/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { selectHierarchyData } from './selection' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/36-hierarchy-tree/selection.ts b/benchmarks/conformance/cases/36-hierarchy-tree/selection.ts index dad39019..6eff6510 100644 --- a/benchmarks/conformance/cases/36-hierarchy-tree/selection.ts +++ b/benchmarks/conformance/cases/36-hierarchy-tree/selection.ts @@ -1,4 +1,4 @@ -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' export function selectHierarchyData(rows: readonly FlareRow[], revision = 0) { return revision % 2 === 0 diff --git a/benchmarks/conformance/cases/36-hierarchy-tree/tanstack.test.ts b/benchmarks/conformance/cases/36-hierarchy-tree/tanstack.test.ts index 5f083224..99c92782 100644 --- a/benchmarks/conformance/cases/36-hierarchy-tree/tanstack.test.ts +++ b/benchmarks/conformance/cases/36-hierarchy-tree/tanstack.test.ts @@ -1,15 +1,15 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { describe, expect, it } from 'vitest' import { selectHierarchyData } from './selection' -import { treeDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { TreeLayoutLink, TreeLayoutNode, } from '@tanstack/charts/hierarchy/tree' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { ConformanceInput } from '../../types' import type { ChartPoint, ChartScene, SceneNode } from '@tanstack/charts' @@ -156,7 +156,7 @@ describe('native hierarchy tree', () => { function render(revision: number) { return createChartRuntime().render( - treeDefinition({ + createExampleChart({ ...size, revision, } satisfies ConformanceInput), diff --git a/benchmarks/conformance/cases/37-delaunay-network/example.tsx b/benchmarks/conformance/cases/37-delaunay-network/example.tsx index 3a8e1ff6..13cf028d 100644 --- a/benchmarks/conformance/cases/37-delaunay-network/example.tsx +++ b/benchmarks/conformance/cases/37-delaunay-network/example.tsx @@ -1,68 +1,59 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart, dot } from '@tanstack/charts' import { delaunayLink } from '@tanstack/charts/spatial/delaunay' import { scaleLinear } from 'd3-scale' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' const carKey = (row: CarsRow) => `${row.name}:${row.year}:${row['weight (lb)']}` -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const points = cars .filter((row) => { return row['economy (mpg)'] !== null && row['power (hp)'] !== null }) .slice(input.revision * 3, input.revision * 3 + 24) - return defineChart({ - marks: [ - delaunayLink(points, { - x: 'weight (lb)', - y: 'economy (mpg)', - key: carKey, - stroke: '#94a3b8', - strokeOpacity: 0.75, - strokeWidth: 1, - }), - dot(points, { - x: 'weight (lb)', - y: 'economy (mpg)', - key: carKey, - fill: '#2563eb', - stroke: '#ffffff', - strokeWidth: 1, - r: 4, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Weight (lb)' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Fuel economy (mpg)' }, + return defineChart( + { + marks: [ + delaunayLink(points, { + x: 'weight (lb)', + y: 'economy (mpg)', + key: carKey, + stroke: '#94a3b8', + strokeOpacity: 0.75, + strokeWidth: 1, + }), + dot(points, { + x: 'weight (lb)', + y: 'economy (mpg)', + key: carKey, + fill: '#2563eb', + stroke: '#ffffff', + strokeWidth: 1, + r: 4, + }), + ], + x: { scale: scaleLinear, grid: true, axis: { label: 'Weight (lb)' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Fuel economy (mpg)' }, + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Delaunay spatial network' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/37-delaunay-network/plot.ts b/benchmarks/conformance/cases/37-delaunay-network/plot.ts index 23ffb911..3c9ba711 100644 --- a/benchmarks/conformance/cases/37-delaunay-network/plot.ts +++ b/benchmarks/conformance/cases/37-delaunay-network/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/38-contour-topography/example.tsx b/benchmarks/conformance/cases/38-contour-topography/example.tsx index f28c7af1..2f9ebdf5 100644 --- a/benchmarks/conformance/cases/38-contour-topography/example.tsx +++ b/benchmarks/conformance/cases/38-contour-topography/example.tsx @@ -8,48 +8,39 @@ import { contourThresholds, windObservationGrid } from './transform' const colors = ['#dbeafe', '#bfdbfe', '#93c5fd', '#60a5fa', '#2563eb'] -export const contourDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const grid = windObservationGrid(input.revision) - return defineChart({ - marks: [ - contour(grid.data, { - width: grid.width, - height: grid.height, - value: (row) => Math.hypot(row.u, row.v), - thresholds: contourThresholds, - stroke: '#ffffff', - strokeWidth: 0.75, - }), - ], - color: { - scale: scaleThreshold, - domain: contourThresholds.slice(1), - range: colors, + return defineChart( + { + marks: [ + contour(grid.data, { + width: grid.width, + height: grid.height, + value: (row) => Math.hypot(row.u, row.v), + thresholds: contourThresholds, + stroke: '#ffffff', + strokeWidth: 0.75, + }), + ], + color: { + scale: scaleThreshold, + domain: contourThresholds.slice(1), + range: colors, + }, + margin: 12, }, - margin: 12, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Filled wind-speed contours' -export const createExampleChart = (options: ExampleOptions) => - defineChart(contourDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/38-contour-topography/tanstack.test.ts b/benchmarks/conformance/cases/38-contour-topography/tanstack.test.ts index 24a16f74..50962d7c 100644 --- a/benchmarks/conformance/cases/38-contour-topography/tanstack.test.ts +++ b/benchmarks/conformance/cases/38-contour-topography/tanstack.test.ts @@ -1,18 +1,15 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { contourDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import { contourThresholds } from './transform' -import type { ConformanceInput } from '../../types' import type { SceneArea, SceneNode } from '@tanstack/charts' describe('native scalar-grid contours', () => { it('emits five structured levels without synthetic focus points', () => { const scene = createChartRuntime().render( - contourDefinition({ - width: 640, - height: 400, + createExampleChart({ revision: 0, - } satisfies ConformanceInput), + }), { width: 640, height: 400 }, ) const areas = sceneAreas(scene.nodes) diff --git a/benchmarks/conformance/cases/38-contour-topography/transform.ts b/benchmarks/conformance/cases/38-contour-topography/transform.ts index 34f630b8..ef019b9e 100644 --- a/benchmarks/conformance/cases/38-contour-topography/transform.ts +++ b/benchmarks/conformance/cases/38-contour-topography/transform.ts @@ -1,4 +1,4 @@ -import { wind } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' export interface ContourGrid { width: number diff --git a/benchmarks/conformance/cases/39-density-contours/example.tsx b/benchmarks/conformance/cases/39-density-contours/example.tsx index 541241e2..40a32fb4 100644 --- a/benchmarks/conformance/cases/39-density-contours/example.tsx +++ b/benchmarks/conformance/cases/39-density-contours/example.tsx @@ -1,11 +1,11 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { defineChart } from '@tanstack/charts' import { densityContour } from '@tanstack/charts/spatial/density' import { scaleLinear } from 'd3-scale' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' type PenguinBill = PenguinsRow & { readonly culmen_length_mm: number @@ -17,56 +17,47 @@ export const densityThresholds = [0.0004, 0.0008, 0.0012, 0.0016, 0.002, 0.0024] export const densityXDomain: [number, number] = [30, 62] export const densityYDomain: [number, number] = [12, 23] -export const densityDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const points = penguins .filter((row): row is PenguinBill => { return row.culmen_length_mm !== null && row.culmen_depth_mm !== null }) .slice(input.revision * 8, input.revision * 8 + 320) - return defineChart({ - marks: [ - densityContour(points, { - x: 'culmen_length_mm', - y: 'culmen_depth_mm', - bandwidth: densityBandwidth, - thresholds: densityThresholds, - fill: '#2563eb', - fillOpacity: 0.16, - stroke: '#1e3a8a', - strokeWidth: 1, - }), - ], - x: { - scale: scaleLinear().domain(densityXDomain), + return defineChart( + { + marks: [ + densityContour(points, { + x: 'culmen_length_mm', + y: 'culmen_depth_mm', + bandwidth: densityBandwidth, + thresholds: densityThresholds, + fill: '#2563eb', + fillOpacity: 0.16, + stroke: '#1e3a8a', + strokeWidth: 1, + }), + ], + x: { + scale: scaleLinear().domain(densityXDomain), + }, + y: { + scale: scaleLinear().domain(densityYDomain), + }, + guides: false, + margin: densityBandwidth * 1.5, }, - y: { - scale: scaleLinear().domain(densityYDomain), - }, - guides: false, - margin: densityBandwidth * 1.5, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Point density contours' -export const createExampleChart = (options: ExampleOptions) => - defineChart(densityDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/39-density-contours/plot.ts b/benchmarks/conformance/cases/39-density-contours/plot.ts index 9fc1b176..ca3a06f8 100644 --- a/benchmarks/conformance/cases/39-density-contours/plot.ts +++ b/benchmarks/conformance/cases/39-density-contours/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/39-density-contours/tanstack.test.ts b/benchmarks/conformance/cases/39-density-contours/tanstack.test.ts index c0cecc5e..8b12cca1 100644 --- a/benchmarks/conformance/cases/39-density-contours/tanstack.test.ts +++ b/benchmarks/conformance/cases/39-density-contours/tanstack.test.ts @@ -1,18 +1,15 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { densityDefinition, densityThresholds } from './tanstack' -import type { ConformanceInput } from '../../types' +import { createExampleChart, densityThresholds } from './tanstack' import type { SceneArea, SceneNode } from '@tanstack/charts' describe('native density contours', () => { it('emits six structured contour levels without synthetic focus points', () => { const runtime = createChartRuntime() const scene = runtime.render( - densityDefinition({ - width: 640, - height: 400, + createExampleChart({ revision: 0, - } satisfies ConformanceInput), + }), { width: 640, height: 400 }, ) const areas = sceneAreas(scene.nodes) diff --git a/benchmarks/conformance/cases/40-force-directed-network/example.tsx b/benchmarks/conformance/cases/40-force-directed-network/example.tsx index c46cc7e7..f01f8668 100644 --- a/benchmarks/conformance/cases/40-force-directed-network/example.tsx +++ b/benchmarks/conformance/cases/40-force-directed-network/example.tsx @@ -3,14 +3,14 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, dot, link, text } from '@tanstack/charts' import { forceLayout } from '@tanstack/charts/network/force' -import { miserables } from '@charts-poc/demo-data/miserables' +import { miserables } from '@tanstack/charts-data/miserables' import { scaleLinear } from 'd3-scale' import { forceNetworkData } from './transform' const colors = ['#2563eb', '#f97316', '#10b981'] const network = forceNetworkData(miserables) -export const forceDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const distanceDelta = Math.abs(input.revision % 2) * 3 const graph = forceLayout(network.nodes, network.links, { nodeKey: 'id', @@ -33,59 +33,71 @@ export const forceDefinition = (input: ExampleOptions) => { ], }) - return defineChart({ - marks: [ - link(graph.links, { - id: 'network-links', - x1: 'x1', - y1: 'y1', - x2: 'x2', - y2: 'y2', - key: ({ source, target }) => `${source}->${target}`, - stroke: '#94a3b8', - strokeOpacity: 0.6, - strokeWidth: 2, - }), - dot(graph.nodes, { - id: 'network-nodes', - x: 'x', - y: 'y', - color: 'group', - key: 'id', - r: 7, - stroke: '#ffffff', - strokeWidth: 1.5, - }), - ...(input.preview === true - ? [] - : [ - text(graph.nodes, { - id: 'network-labels', - x: 'x', - y: 'y', - text: 'id', - key: 'id', - dy: -12, - fontSize: 10, - fontWeight: 600, - }), - ]), - ], - x: { - scale: scaleLinear().domain(graph.xDomain), - }, - y: { - scale: scaleLinear().domain(graph.yDomain), + return defineChart( + { + marks: [ + link(graph.links, { + id: 'network-links', + x1: 'x1', + y1: 'y1', + x2: 'x2', + y2: 'y2', + key: ({ source, target }) => `${source}->${target}`, + stroke: '#94a3b8', + strokeOpacity: 0.6, + strokeWidth: 2, + }), + dot(graph.nodes, { + id: 'network-nodes', + x: 'x', + y: 'y', + color: 'group', + key: 'id', + r: 7, + stroke: '#ffffff', + strokeWidth: 1.5, + }), + ...(input.preview === true + ? [] + : [ + text(graph.nodes, { + id: 'network-labels', + x: 'x', + y: 'y', + text: 'id', + key: 'id', + dy: -12, + fontSize: 10, + fontWeight: 600, + }), + ]), + ], + x: { + scale: scaleLinear().domain(graph.xDomain), + }, + y: { + scale: scaleLinear().domain(graph.yDomain), + }, + guides: false, + color: { + range: colors, + }, }, - guides: false, - color: { - range: colors, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'group' in datum + ? `${datum.id} · Group ${datum.group}` + : `${datum.source} → ${datum.target} · Value ${datum.value}`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } @@ -93,23 +105,7 @@ export interface ExampleOptions { export const exampleAriaLabel = 'Force-directed Les Misérables character network' -export const createExampleChart = (options: ExampleOptions) => - defineChart(forceDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'group' in datum - ? `${datum.id} · Group ${datum.group}` - : `${datum.source} → ${datum.target} · Value ${datum.value}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/40-force-directed-network/layout.ts b/benchmarks/conformance/cases/40-force-directed-network/layout.ts index 819a2e01..9260efb9 100644 --- a/benchmarks/conformance/cases/40-force-directed-network/layout.ts +++ b/benchmarks/conformance/cases/40-force-directed-network/layout.ts @@ -12,7 +12,7 @@ import type { MiserablesGraph, MiserablesLink, MiserablesNode, -} from '@charts-poc/demo-data/miserables' +} from '@tanstack/charts-data/miserables' import type { SimulationLinkDatum, SimulationNodeDatum } from 'd3-force' export interface PositionedNetworkNode extends MiserablesNode { diff --git a/benchmarks/conformance/cases/40-force-directed-network/plot.ts b/benchmarks/conformance/cases/40-force-directed-network/plot.ts index e309183a..05f9fe15 100644 --- a/benchmarks/conformance/cases/40-force-directed-network/plot.ts +++ b/benchmarks/conformance/cases/40-force-directed-network/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { miserables } from '@charts-poc/demo-data/miserables' +import { miserables } from '@tanstack/charts-data/miserables' import { networkLayout } from './layout' import { forceNetworkData } from './transform' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/40-force-directed-network/tanstack.test.ts b/benchmarks/conformance/cases/40-force-directed-network/tanstack.test.ts index c7d8b246..6ded667b 100644 --- a/benchmarks/conformance/cases/40-force-directed-network/tanstack.test.ts +++ b/benchmarks/conformance/cases/40-force-directed-network/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { miserables } from '@charts-poc/demo-data/miserables' +import { miserables } from '@tanstack/charts-data/miserables' import { describe, expect, it } from 'vitest' import { networkLayout } from './layout' -import { forceDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import { forceNetworkData } from './transform' import type { ConformanceInput } from '../../types' import type { ChartPoint, ChartScene, SceneNode } from '@tanstack/charts' @@ -178,7 +178,7 @@ describe('native force-directed network', () => { function render(revision: number) { return createChartRuntime().render( - forceDefinition({ + createExampleChart({ ...size, revision, } satisfies ConformanceInput), diff --git a/benchmarks/conformance/cases/40-force-directed-network/transform.ts b/benchmarks/conformance/cases/40-force-directed-network/transform.ts index 41f7592c..735eadc9 100644 --- a/benchmarks/conformance/cases/40-force-directed-network/transform.ts +++ b/benchmarks/conformance/cases/40-force-directed-network/transform.ts @@ -1,4 +1,4 @@ -import type { MiserablesGraph } from '@charts-poc/demo-data/miserables' +import type { MiserablesGraph } from '@tanstack/charts-data/miserables' export function forceNetworkData(source: MiserablesGraph): MiserablesGraph { const nodes = source.nodes.slice(0, 13) diff --git a/benchmarks/conformance/cases/40-geojson-map/example.tsx b/benchmarks/conformance/cases/40-geojson-map/example.tsx index aef58817..5331bced 100644 --- a/benchmarks/conformance/cases/40-geojson-map/example.tsx +++ b/benchmarks/conformance/cases/40-geojson-map/example.tsx @@ -1,57 +1,51 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { westportHouse } from '@charts-poc/demo-data/westport-house' +import { westportHouse } from '@tanstack/charts-data/westport-house' import { defineChart } from '@tanstack/charts' import { geoShape } from '@tanstack/charts/geo' import { geoIdentity } from 'd3-geo' const strokes = ['#1e293b', '#2563eb'] -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - geoShape(westportHouse.features, { - key: (feature) => feature.properties.id, - projection: { - type: geoIdentity, - fit: westportHouse, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + geoShape(westportHouse.features, { + key: (feature) => feature.properties.id, + projection: { + type: geoIdentity, + fit: westportHouse, + }, + fill: 'none', + stroke: strokes[input.revision % 2] ?? strokes[0], + strokeWidth: 1, + }), + ], + margin: 10, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + datum.properties.name ?? + datum.properties.roomnumber ?? + datum.properties.type.replaceAll('_', ' '), }, - fill: 'none', - stroke: strokes[input.revision % 2] ?? strokes[0], - strokeWidth: 1, - }), - ], - margin: 10, - }) -export interface ExampleOptions { - width: number - height: number + }, + }, + ) +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Westport House floor plan' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - datum.properties.name ?? - datum.properties.roomnumber ?? - datum.properties.type.replaceAll('_', ' '), - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/40-geojson-map/plot.ts b/benchmarks/conformance/cases/40-geojson-map/plot.ts index 4fc916c4..093607a3 100644 --- a/benchmarks/conformance/cases/40-geojson-map/plot.ts +++ b/benchmarks/conformance/cases/40-geojson-map/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { westportHouse } from '@charts-poc/demo-data/westport-house' +import { westportHouse } from '@tanstack/charts-data/westport-house' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/41-waffle-unit-chart/example.tsx b/benchmarks/conformance/cases/41-waffle-unit-chart/example.tsx index aefa616b..f9a11ab1 100644 --- a/benchmarks/conformance/cases/41-waffle-unit-chart/example.tsx +++ b/benchmarks/conformance/cases/41-waffle-unit-chart/example.tsx @@ -2,7 +2,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { colorLegend, defineChart, waffleY } from '@tanstack/charts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' const colors = [ '#8b5cf6', @@ -14,37 +14,32 @@ const colors = [ ] const letters = alphabet.map((row) => row.letter) -const waffleDefinition = (showLegend: boolean) => - defineChart({ - marks: [ - waffleY(alphabet, { - y: 'frequency', - color: 'letter', - key: 'letter', - unit: 0.01, - gap: 2, - round: true, - radius: 2, - }), - ], - guides: false, - color: { - domain: letters, - range: colors, - ...(showLegend ? { legend: colorLegend({ label: 'Letter' }) } : {}), +export const createExampleChart = () => + defineChart( + { + marks: [ + waffleY(alphabet, { + y: 'frequency', + color: 'letter', + key: 'letter', + unit: 0.01, + gap: 2, + round: true, + radius: 2, + }), + ], + guides: false, + color: { + domain: letters, + range: colors, + legend: colorLegend({ label: 'Letter' }), + }, }, - }) - -export const definition = () => waffleDefinition(true) + { keyboard: true, tooltip: exampleTooltip }, + ) export const exampleAriaLabel = 'English letter frequency waffle chart' -export const createExampleChart = () => - defineChart(definition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/41-waffle-unit-chart/plot.ts b/benchmarks/conformance/cases/41-waffle-unit-chart/plot.ts index f96aff76..f92db9c7 100644 --- a/benchmarks/conformance/cases/41-waffle-unit-chart/plot.ts +++ b/benchmarks/conformance/cases/41-waffle-unit-chart/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/42-vector-field/example.tsx b/benchmarks/conformance/cases/42-vector-field/example.tsx index 6b77d7d4..2ba11c10 100644 --- a/benchmarks/conformance/cases/42-vector-field/example.tsx +++ b/benchmarks/conformance/cases/42-vector-field/example.tsx @@ -2,37 +2,34 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, vector } from '@tanstack/charts' -import { wind } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' import { scaleLinear, scaleSqrt } from 'd3-scale' import { sampleWind } from './selection' const speed = scaleSqrt().domain([0, 14]).range([0, 22]) const sampledWind = sampleWind(wind) -export const vectorFieldDefinition = () => - defineChart({ - marks: [ - vector(sampledWind, { - id: 'wind-vectors', - x: 'longitude', - y: 'latitude', - length: (row) => speed(Math.hypot(row.u, row.v)), - rotate: (row) => (Math.atan2(row.u, row.v) * 180) / Math.PI, - stroke: '#2563eb', - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Longitude' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Latitude' } }, - }) +export const createExampleChart = () => + defineChart( + { + marks: [ + vector(sampledWind, { + id: 'wind-vectors', + x: 'longitude', + y: 'latitude', + length: (row) => speed(Math.hypot(row.u, row.v)), + rotate: (row) => (Math.atan2(row.u, row.v) * 180) / Math.PI, + stroke: '#2563eb', + }), + ], + x: { scale: scaleLinear, grid: true, axis: { label: 'Longitude' } }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Latitude' } }, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) export const exampleAriaLabel = 'Two-dimensional vector field' -export const createExampleChart = () => - defineChart(vectorFieldDefinition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/42-vector-field/plot.ts b/benchmarks/conformance/cases/42-vector-field/plot.ts index 62149a47..a5d77b04 100644 --- a/benchmarks/conformance/cases/42-vector-field/plot.ts +++ b/benchmarks/conformance/cases/42-vector-field/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { wind } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' import { sampleWind } from './selection' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/42-vector-field/selection.ts b/benchmarks/conformance/cases/42-vector-field/selection.ts index 75b594a0..7bfe0728 100644 --- a/benchmarks/conformance/cases/42-vector-field/selection.ts +++ b/benchmarks/conformance/cases/42-vector-field/selection.ts @@ -1,4 +1,4 @@ -import type { WindRow } from '@charts-poc/demo-data/wind' +import type { WindRow } from '@tanstack/charts-data/wind' export function sampleWind(rows: readonly WindRow[]) { const longitudes = [...new Set(rows.map((row) => row.longitude))] diff --git a/benchmarks/conformance/cases/42-vector-field/tanstack.test.ts b/benchmarks/conformance/cases/42-vector-field/tanstack.test.ts index 35a3b486..b48c0cd3 100644 --- a/benchmarks/conformance/cases/42-vector-field/tanstack.test.ts +++ b/benchmarks/conformance/cases/42-vector-field/tanstack.test.ts @@ -1,9 +1,9 @@ -import { wind } from '@charts-poc/demo-data/wind' +import { wind } from '@tanstack/charts-data/wind' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { sampleWind } from './selection' -import { vectorFieldDefinition } from './tanstack' -import type { WindRow } from '@charts-poc/demo-data/wind' +import { createExampleChart } from './tanstack' +import type { WindRow } from '@tanstack/charts-data/wind' describe('native sampled vector field', () => { it('selects the authored six-by-five source grid without fabricating rows', () => { @@ -17,10 +17,10 @@ describe('native sampled vector field', () => { it('keeps one semantic interaction point per sampled observation', () => { const sampled = sampleWind(wind) - const scene = createChartRuntime().render( - vectorFieldDefinition(), - { width: 640, height: 400 }, - ) + const scene = createChartRuntime().render(createExampleChart(), { + width: 640, + height: 400, + }) const points = scene.points.filter( ({ markId }) => markId === 'wind-vectors', ) diff --git a/benchmarks/conformance/cases/43-hexbin-density/example.tsx b/benchmarks/conformance/cases/43-hexbin-density/example.tsx index 29373658..31e2d412 100644 --- a/benchmarks/conformance/cases/43-hexbin-density/example.tsx +++ b/benchmarks/conformance/cases/43-hexbin-density/example.tsx @@ -1,11 +1,11 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart } from '@tanstack/charts' import { hexbin } from '@tanstack/charts/spatial/hexbin' import { scaleLinear, scaleThreshold } from 'd3-scale' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' type CompleteCar = CarsRow & { readonly 'economy (mpg)': number @@ -17,67 +17,61 @@ const coordinate = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1, }) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = cars .filter((row): row is CompleteCar => row['economy (mpg)'] !== null) .slice(input.revision * 8, input.revision * 8 + 360) - return defineChart({ - marks: [ - hexbin(rows, { - x: 'weight (lb)', - y: 'economy (mpg)', - binWidth: 24, - color: 'count', - r: 11, - stroke: '#ffffff', - strokeWidth: 0.75, - }), - ], - x: { - scale: scaleLinear().domain([1500, 5500]), - grid: true, - axis: { label: 'Weight (lb)' }, - }, - y: { - scale: scaleLinear().domain([5, 50]), - grid: true, - axis: { label: 'Fuel economy (mpg)' }, + return defineChart( + { + marks: [ + hexbin(rows, { + x: 'weight (lb)', + y: 'economy (mpg)', + binWidth: 24, + color: 'count', + r: 11, + stroke: '#ffffff', + strokeWidth: 0.75, + }), + ], + x: { + scale: scaleLinear().domain([1500, 5500]), + grid: true, + axis: { label: 'Weight (lb)' }, + }, + y: { + scale: scaleLinear().domain([5, 50]), + grid: true, + axis: { label: 'Fuel economy (mpg)' }, + }, + color: { + scale: scaleThreshold, + domain: [5, 12, 24], + range: colors, + }, + margin, }, - color: { - scale: scaleThreshold, - domain: [5, 12, 24], - range: colors, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `Bin center: ${coordinate.format(point.datum.x)} lb, ${coordinate.format(point.datum.y)} mpg · Cars: ${point.datum.count}`, + }, + }, }, - margin, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Hexagonally binned point density' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `Bin center: ${coordinate.format(point.datum.x)} lb, ${coordinate.format(point.datum.y)} mpg · Cars: ${point.datum.count}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/43-hexbin-density/plot.ts b/benchmarks/conformance/cases/43-hexbin-density/plot.ts index 09c3b148..2eda8e9e 100644 --- a/benchmarks/conformance/cases/43-hexbin-density/plot.ts +++ b/benchmarks/conformance/cases/43-hexbin-density/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/44-framed-scatter/example.tsx b/benchmarks/conformance/cases/44-framed-scatter/example.tsx index bf4e6830..c8fe4768 100644 --- a/benchmarks/conformance/cases/44-framed-scatter/example.tsx +++ b/benchmarks/conformance/cases/44-framed-scatter/example.tsx @@ -1,62 +1,53 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart, dot, frame } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = cars .filter((row) => row['economy (mpg)'] !== null) .slice(input.revision * 8, input.revision * 8 + 320) const scatterRows = rows - return defineChart({ - marks: [ - frame({ - inset: 4, - radius: 6, - fill: '#eff6ff', - stroke: '#2563eb', - strokeOpacity: 0.7, - }), - dot(scatterRows, { - key: (row) => - `${row.name}:${row.year}:${row['weight (lb)']}:${row['economy (mpg)']}`, - x: 'weight (lb)', - y: 'economy (mpg)', - fill: '#2563eb', - fillOpacity: 0.65, - r: 3, - }), - ], - x: { scale: scaleLinear }, - y: { scale: scaleLinear }, - guides: false, - margin: 20, - }) + return defineChart( + { + marks: [ + frame({ + inset: 4, + radius: 6, + fill: '#eff6ff', + stroke: '#2563eb', + strokeOpacity: 0.7, + }), + dot(scatterRows, { + key: (row) => + `${row.name}:${row.year}:${row['weight (lb)']}:${row['economy (mpg)']}`, + x: 'weight (lb)', + y: 'economy (mpg)', + fill: '#2563eb', + fillOpacity: 0.65, + r: 3, + }), + ], + x: { scale: scaleLinear }, + y: { scale: scaleLinear }, + guides: false, + margin: 20, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Guide-free scatterplot with a framed plotting region' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/44-framed-scatter/plot.ts b/benchmarks/conformance/cases/44-framed-scatter/plot.ts index f9310042..2aefe350 100644 --- a/benchmarks/conformance/cases/44-framed-scatter/plot.ts +++ b/benchmarks/conformance/cases/44-framed-scatter/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceInput, ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/50-empirical-cdf/example.tsx b/benchmarks/conformance/cases/50-empirical-cdf/example.tsx index 51412704..3bea9c8a 100644 --- a/benchmarks/conformance/cases/50-empirical-cdf/example.tsx +++ b/benchmarks/conformance/cases/50-empirical-cdf/example.tsx @@ -1,11 +1,11 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { d3Curve, defineChart, lineY, rank } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' import { curveStepAfter } from 'd3-shape' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' type CarWithEconomy = CarsRow & { 'economy (mpg)': number } @@ -18,7 +18,7 @@ const percent = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0, }) -export const empiricalCdfDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const source = completeCars .slice(input.revision * 8) .sort((left, right) => left['economy (mpg)'] - right['economy (mpg)']) @@ -29,53 +29,44 @@ export const empiricalCdfDefinition = (input: ExampleOptions) => { })) const rows = fullRows - return defineChart({ - marks: [ - lineY(rows, { - id: 'empirical-cdf', - key: (row) => `${row.name}:${row.year}`, - x: 'economy (mpg)', - y: 'probability', - curve: d3Curve(curveStepAfter), - stroke: '#2563eb', - strokeWidth: 2, - }), - ], - x: { - scale: scaleLinear, - grid: true, - axis: { label: 'Fuel economy (mpg)' }, - }, - y: { - scale: scaleLinear().domain([0, 1]), - grid: true, - axis: { - ticks: { format: (value) => percent.format(value) }, - label: 'Cumulative proportion', + return defineChart( + { + marks: [ + lineY(rows, { + id: 'empirical-cdf', + key: (row) => `${row.name}:${row.year}`, + x: 'economy (mpg)', + y: 'probability', + curve: d3Curve(curveStepAfter), + stroke: '#2563eb', + strokeWidth: 2, + }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: 'Fuel economy (mpg)' }, + }, + y: { + scale: scaleLinear().domain([0, 1]), + grid: true, + axis: { + ticks: { format: (value) => percent.format(value) }, + label: 'Cumulative proportion', + }, }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Empirical cumulative distribution' -export const createExampleChart = (options: ExampleOptions) => - defineChart(empiricalCdfDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/50-empirical-cdf/plot.ts b/benchmarks/conformance/cases/50-empirical-cdf/plot.ts index 7e8d1a98..71d71c56 100644 --- a/benchmarks/conformance/cases/50-empirical-cdf/plot.ts +++ b/benchmarks/conformance/cases/50-empirical-cdf/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { rank } from 'd3-array' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/50-empirical-cdf/tanstack.test.ts b/benchmarks/conformance/cases/50-empirical-cdf/tanstack.test.ts index 36744368..294c34dc 100644 --- a/benchmarks/conformance/cases/50-empirical-cdf/tanstack.test.ts +++ b/benchmarks/conformance/cases/50-empirical-cdf/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { empiricalCdfDefinition } from './tanstack' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import { createExampleChart } from './tanstack' +import type { CarsRow } from '@tanstack/charts-data/cars' import type { ChartPoint } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -79,7 +79,7 @@ describe('native empirical CDF preparation', () => { function render(nextInput: ConformanceInput) { return createChartRuntime().render( - empiricalCdfDefinition(nextInput), + createExampleChart(nextInput), nextInput, ) } diff --git a/benchmarks/conformance/cases/51-faceted-distributions/example.tsx b/benchmarks/conformance/cases/51-faceted-distributions/example.tsx index 2d10e106..4510a3b4 100644 --- a/benchmarks/conformance/cases/51-faceted-distributions/example.tsx +++ b/benchmarks/conformance/cases/51-faceted-distributions/example.tsx @@ -1,10 +1,10 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { binX, defineChart, facet, normalize, rect } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export const species = ['Adelie', 'Chinstrap', 'Gentoo'] as const export type PenguinSpecies = (typeof species)[number] @@ -19,7 +19,7 @@ const percent = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0, }) -export const facetedDistributionDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = penguins .filter((row): row is PenguinMass => { return ( @@ -48,68 +48,64 @@ export const facetedDistributionDefinition = (input: ExampleOptions) => { species.indexOf(left.species) - species.indexOf(right.species), ) - return defineChart({ - marks: [ - facet(bins, { - by: 'species', - columns: 1, - gap: 8, - label: input.preview === true ? false : (group) => String(group), - chart: (facetBins) => ({ - marks: [ - rect(facetBins, { - x1: 'x1', - x2: 'x2', - y1: () => 0, - y2: 'proportion', - fill: '#8b5cf6', - inset: 0.75, - }), - ], - ...(input.preview ? { guides: false, margin: 0 } : {}), - x: { - scale: scaleLinear().domain([2500, 6500]), - grid: true, - axis: { label: 'Body mass (g)' }, - }, - y: { - scale: scaleLinear().domain([0, 0.4]), - grid: true, - axis: { - ticks: { count: 3, format: (value) => percent.format(value) }, - label: 'Proportion', + return defineChart( + { + marks: [ + facet(bins, { + by: 'species', + columns: 1, + gap: 8, + label: input.preview === true ? false : (group) => String(group), + chart: (facetBins) => ({ + marks: [ + rect(facetBins, { + x1: 'x1', + x2: 'x2', + y1: () => 0, + y2: 'proportion', + fill: '#8b5cf6', + inset: 0.75, + }), + ], + ...(input.preview ? { guides: false, margin: 0 } : {}), + x: { + scale: scaleLinear().domain([2500, 6500]), + grid: true, + axis: { label: 'Body mass (g)' }, + }, + y: { + scale: scaleLinear().domain([0, 0.4]), + grid: true, + axis: { + ticks: { count: 3, format: (value) => percent.format(value) }, + label: 'Proportion', + }, }, - }, + }), }), - }), - ], - margin: 0, - }) + ], + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point) => + `${point.datum.species} · Body mass: ${point.datum.x1}–${point.datum.x2} g · Proportion: ${percent.format(point.datum.proportion)}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Faceted distribution comparison' -export const createExampleChart = (options: ExampleOptions) => - defineChart(facetedDistributionDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => - `${point.datum.species} · Body mass: ${point.datum.x1}–${point.datum.x2} g · Proportion: ${percent.format(point.datum.proportion)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/51-faceted-distributions/plot.ts b/benchmarks/conformance/cases/51-faceted-distributions/plot.ts index be7efd81..0d07eceb 100644 --- a/benchmarks/conformance/cases/51-faceted-distributions/plot.ts +++ b/benchmarks/conformance/cases/51-faceted-distributions/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/51-faceted-distributions/tanstack.test.ts b/benchmarks/conformance/cases/51-faceted-distributions/tanstack.test.ts index 27913d6d..27a21a94 100644 --- a/benchmarks/conformance/cases/51-faceted-distributions/tanstack.test.ts +++ b/benchmarks/conformance/cases/51-faceted-distributions/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { - facetedDistributionDefinition, + createExampleChart, species, type PenguinMass, type PenguinSpecies, @@ -17,9 +17,7 @@ import type { } from '@tanstack/charts' import type { ConformanceInput } from '../../types' -type DistributionDatum = ChartSpecDatum< - ReturnType -> +type DistributionDatum = ChartSpecDatum> type AggregateBin = DistributionDatum['source'][number] const completeRows = penguins.filter((row): row is PenguinMass => { @@ -118,7 +116,7 @@ function render(revision: number) { revision, } satisfies ConformanceInput return createChartRuntime().render( - facetedDistributionDefinition(input), + createExampleChart(input), input, ) } diff --git a/benchmarks/conformance/cases/52-beeswarm-dodge/example.tsx b/benchmarks/conformance/cases/52-beeswarm-dodge/example.tsx index e151fc30..2dfa7852 100644 --- a/benchmarks/conformance/cases/52-beeswarm-dodge/example.tsx +++ b/benchmarks/conformance/cases/52-beeswarm-dodge/example.tsx @@ -1,10 +1,10 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart, dodgeY, dot } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' type CarWithEconomy = CarsRow & { 'economy (mpg)': number } @@ -19,48 +19,39 @@ const margin = { left: 20, } -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - dot(completeCars.slice(input.revision * 8, input.revision * 8 + 72), { - x: 'economy (mpg)', - key: (row) => `${row.name}:${row.year}:${row['weight (lb)']}`, - r: 4, - fill: '#0d9488', - stroke: '#ffffff', - strokeWidth: 1, - layout: dodgeY({ - anchor: 'middle', - padding: 1, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + dot(completeCars.slice(input.revision * 8, input.revision * 8 + 72), { + x: 'economy (mpg)', + key: (row) => `${row.name}:${row.year}:${row['weight (lb)']}`, + r: 4, + fill: '#0d9488', + stroke: '#ffffff', + strokeWidth: 1, + layout: dodgeY({ + anchor: 'middle', + padding: 1, + }), }), - }), - ], - guides: false, - margin, - x: { - scale: scaleLinear().domain([5, 50]), + ], + guides: false, + margin, + x: { + scale: scaleLinear().domain([5, 50]), + }, }, - }) -export interface ExampleOptions { - width: number - height: number + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Beeswarm distribution' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/52-beeswarm-dodge/plot.ts b/benchmarks/conformance/cases/52-beeswarm-dodge/plot.ts index 6d4752e0..aa3e8b37 100644 --- a/benchmarks/conformance/cases/52-beeswarm-dodge/plot.ts +++ b/benchmarks/conformance/cases/52-beeswarm-dodge/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/53-log-scale-scatter/example.tsx b/benchmarks/conformance/cases/53-log-scale-scatter/example.tsx index 7912e0b5..ad25b5a1 100644 --- a/benchmarks/conformance/cases/53-log-scale-scatter/example.tsx +++ b/benchmarks/conformance/cases/53-log-scale-scatter/example.tsx @@ -1,70 +1,60 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { defineChart, dot } from '@tanstack/charts' import { scaleLinear, scaleLog } from 'd3-scale' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' type SizedFlareRow = FlareRow & { readonly size: number } -function logScaleRows(input: ExampleOptions) { +function logScaleRows(input: ChartOptions) { return flare .filter((row): row is SizedFlareRow => row.size !== null && row.size > 0) .slice(input.revision * 8, input.revision * 8 + 200) } -function logScaleChart(rows: readonly SizedFlareRow[]) { - return defineChart({ - marks: [ - dot(rows, { - id: 'class-size-points', - x: 'size', - y: (row) => row.name.split('.').length - 1, - key: 'name', - r: 3.5, - fill: '#f97316', - stroke: '#9a3412', - strokeWidth: 0.75, - }), - ], - margin: { - top: 16, - right: 20, - bottom: 40, - left: 50, +export const createExampleChart = (input: ChartOptions) => { + const rows = logScaleRows(input) + + return defineChart( + { + marks: [ + dot(rows, { + id: 'class-size-points', + x: 'size', + y: (row) => row.name.split('.').length - 1, + key: 'name', + r: 3.5, + fill: '#f97316', + stroke: '#9a3412', + strokeWidth: 0.75, + }), + ], + margin: { + top: 16, + right: 20, + bottom: 40, + left: 50, + }, + x: { + scale: scaleLog().domain([200, 30_000]), + grid: true, + axis: { label: 'Class size' }, + }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Hierarchy depth' } }, }, - x: { - scale: scaleLog().domain([200, 30_000]), - grid: true, - axis: { label: 'Class size' }, - }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Hierarchy depth' } }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } - -export const logScaleScatterDefinition = (input: ExampleOptions) => - logScaleChart(logScaleRows(input)) -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Flare class size on a logarithmic scale' -export const createExampleChart = (options: ExampleOptions) => - defineChart(logScaleScatterDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/53-log-scale-scatter/plot.ts b/benchmarks/conformance/cases/53-log-scale-scatter/plot.ts index 28d04cc5..9b97d1b2 100644 --- a/benchmarks/conformance/cases/53-log-scale-scatter/plot.ts +++ b/benchmarks/conformance/cases/53-log-scale-scatter/plot.ts @@ -1,4 +1,4 @@ -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/53-log-scale-scatter/tanstack.test.ts b/benchmarks/conformance/cases/53-log-scale-scatter/tanstack.test.ts index 0ddd2e3c..a8000777 100644 --- a/benchmarks/conformance/cases/53-log-scale-scatter/tanstack.test.ts +++ b/benchmarks/conformance/cases/53-log-scale-scatter/tanstack.test.ts @@ -2,9 +2,9 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { logScaleScatterDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ChartPoint } from '@tanstack/charts' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { ConformanceInput } from '../../types' const input = { @@ -48,10 +48,7 @@ describe('native log-scale scatter preparation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - logScaleScatterDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function points(source: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/54-bump-ranking/example.tsx b/benchmarks/conformance/cases/54-bump-ranking/example.tsx index f0da5322..e24f6ae3 100644 --- a/benchmarks/conformance/cases/54-bump-ranking/example.tsx +++ b/benchmarks/conformance/cases/54-bump-ranking/example.tsx @@ -12,7 +12,7 @@ import { } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' import { curveBumpX } from 'd3-shape' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' const colors = ['#2563eb', '#ea580c', '#059669', '#7c3aed', '#db2777'] const includedIndustries = [ @@ -30,7 +30,7 @@ const observations = industries.filter( includedIndustrySet.has(row.industry), ) -export const bumpRankingDefinition = (input?: ExampleOptions) => { +export const createExampleChart = (input?: ChartOptions) => { const rows = rank(observations, { by: 'date', value: 'unemployed', @@ -43,77 +43,68 @@ export const bumpRankingDefinition = (input?: ExampleOptions) => { select: 'max', }) - return defineChart({ - marks: [ - lineY(rows, { - id: 'industry-ranks', - x: 'date', - y: 'rank', - color: 'industry', - curve: d3Curve(curveBumpX), - strokeWidth: 2.25, - }), - dot(rows, { - id: 'industry-rank-points', - x: 'date', - y: 'rank', - color: 'industry', - r: 3, - }), - ...(input?.preview === true - ? [] - : [ - text(labels, { - id: 'newest-industry-labels', - x: 'date', - y: 'rank', - text: 'industry', - color: 'industry', - anchor: 'start', - dx: 6, - }), - ]), - ], - x: { - scale: scaleUtc, - axis: { - ticks: { count: 7, format: (date) => `${date.getUTCFullYear()}` }, - label: 'Year', + return defineChart( + { + marks: [ + lineY(rows, { + id: 'industry-ranks', + x: 'date', + y: 'rank', + color: 'industry', + curve: d3Curve(curveBumpX), + strokeWidth: 2.25, + }), + dot(rows, { + id: 'industry-rank-points', + x: 'date', + y: 'rank', + color: 'industry', + r: 3, + }), + ...(input?.preview === true + ? [] + : [ + text(labels, { + id: 'newest-industry-labels', + x: 'date', + y: 'rank', + text: 'industry', + color: 'industry', + anchor: 'start', + dx: 6, + }), + ]), + ], + x: { + scale: scaleUtc, + axis: { + ticks: { count: 7, format: (date) => `${date.getUTCFullYear()}` }, + label: 'Year', + }, }, - }, - y: { - scale: scaleLinear().domain([5.2, 0.8]), - grid: true, - axis: { - ticks: { count: 5, format: (value) => `#${value}` }, - label: 'Rank', + y: { + scale: scaleLinear().domain([5.2, 0.8]), + grid: true, + axis: { + ticks: { count: 5, format: (value) => `#${value}` }, + label: 'Rank', + }, + }, + color: { + domain: includedIndustries, + range: colors, }, }, - color: { - domain: includedIndustries, - range: colors, - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number - revision: number +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Annual unemployment rank by industry' -export const createExampleChart = (options: ExampleOptions) => - defineChart(bumpRankingDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/54-bump-ranking/plot.ts b/benchmarks/conformance/cases/54-bump-ranking/plot.ts index 5a3927aa..7d26317d 100644 --- a/benchmarks/conformance/cases/54-bump-ranking/plot.ts +++ b/benchmarks/conformance/cases/54-bump-ranking/plot.ts @@ -1,7 +1,7 @@ import * as Plot from '@observablehq/plot' import { group, rank } from 'd3-array' -import { industries } from '@charts-poc/demo-data/industries' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/54-bump-ranking/tanstack.test.ts b/benchmarks/conformance/cases/54-bump-ranking/tanstack.test.ts index a1b665b0..9fc74714 100644 --- a/benchmarks/conformance/cases/54-bump-ranking/tanstack.test.ts +++ b/benchmarks/conformance/cases/54-bump-ranking/tanstack.test.ts @@ -2,8 +2,8 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' -import { bumpRankingDefinition } from './tanstack' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { createExampleChart } from './tanstack' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import type { ChartPoint } from '@tanstack/charts' type RankedIndustry = IndustriesRow & { @@ -15,11 +15,11 @@ type RankedIndustry = IndustriesRow & { describe('native bump-ranking labels', () => { it('selects each industry label by maximum date instead of input position', () => { const runtime = createChartRuntime() - const first = runtime.render(bumpRankingDefinition(), { + const first = runtime.render(createExampleChart(), { width: 640, height: 400, }) - const repeated = runtime.render(bumpRankingDefinition(), { + const repeated = runtime.render(createExampleChart(), { width: 640, height: 400, }) diff --git a/benchmarks/conformance/cases/55-indexed-multi-line/example.tsx b/benchmarks/conformance/cases/55-indexed-multi-line/example.tsx index fbbc2ddc..4f21d0ee 100644 --- a/benchmarks/conformance/cases/55-indexed-multi-line/example.tsx +++ b/benchmarks/conformance/cases/55-indexed-multi-line/example.tsx @@ -10,8 +10,8 @@ import { text, } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' const colors = ['#2563eb', '#ea580c', '#059669', '#7c3aed'] const formatIndex = (value: number) => `${Math.round((value - 1) * 100)}%` @@ -27,10 +27,9 @@ export const indexedIndustryObservations = industries.filter( includedIndustries.has(row.industry), ) -export const indexedIndustryDefinition = ( - source: readonly IndustriesRow[], - preview = false, -) => { +export const createExampleChart = (input: ChartOptions) => { + const source: readonly IndustriesRow[] = indexedIndustryObservations + const preview = input.preview === true const rows = normalize( [...source].sort( (left, right) => left.date.getTime() - right.date.getTime(), @@ -47,77 +46,68 @@ export const indexedIndustryDefinition = ( value: (datum) => datum.date.getTime(), select: 'max', }) - return defineChart({ - marks: [ - ruleY([1], { strokeOpacity: 0.65 }), - lineY(rows, { - id: 'indexed-lines', - x: 'date', - y: 'indexed', - color: 'industry', - strokeWidth: 2.25, - }), - ...(preview - ? [] - : [ - text(labels, { - id: 'end-labels', - x: 'date', - y: 'indexed', - text: 'industry', - color: 'industry', - anchor: 'start', - dx: 5, - }), - ]), - ], - x: { scale: scaleUtc, axis: { label: 'Month' } }, - y: { - scale: scaleLinear, - grid: true, - axis: { - ticks: { format: formatIndex }, - label: 'Change from January 2008', + return defineChart( + { + marks: [ + ruleY([1], { strokeOpacity: 0.65 }), + lineY(rows, { + id: 'indexed-lines', + x: 'date', + y: 'indexed', + color: 'industry', + strokeWidth: 2.25, + }), + ...(preview + ? [] + : [ + text(labels, { + id: 'end-labels', + x: 'date', + y: 'indexed', + text: 'industry', + color: 'industry', + anchor: 'start', + dx: 5, + }), + ]), + ], + x: { scale: scaleUtc, axis: { label: 'Month' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { + ticks: { format: formatIndex }, + label: 'Change from January 2008', + }, + }, + color: { + range: colors, }, + margin: { right: 108 }, }, - color: { - range: colors, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { + month: 'short', + year: 'numeric', + timeZone: 'UTC', + })} · ${formatIndex(datum.indexed)} from start`, + }, + }, }, - margin: { right: 108 }, - }) + ) } -export interface ExampleOptions { - width: number - height: number - revision: number +export interface ChartOptions { preview?: boolean } -export const createExampleDefinition = (input: ExampleOptions) => - indexedIndustryDefinition(indexedIndustryObservations, input.preview === true) - export const exampleAriaLabel = 'Indexed U.S. industry unemployment' -export const createExampleChart = (options: ExampleOptions) => - defineChart(createExampleDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.industry} · ${datum.date.toLocaleDateString('en-US', { - month: 'short', - year: 'numeric', - timeZone: 'UTC', - })} · ${formatIndex(datum.indexed)} from start`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/55-indexed-multi-line/plot.ts b/benchmarks/conformance/cases/55-indexed-multi-line/plot.ts index bcc28831..6c7e22d2 100644 --- a/benchmarks/conformance/cases/55-indexed-multi-line/plot.ts +++ b/benchmarks/conformance/cases/55-indexed-multi-line/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/55-indexed-multi-line/tanstack.test.ts b/benchmarks/conformance/cases/55-indexed-multi-line/tanstack.test.ts index bda96feb..0d48280d 100644 --- a/benchmarks/conformance/cases/55-indexed-multi-line/tanstack.test.ts +++ b/benchmarks/conformance/cases/55-indexed-multi-line/tanstack.test.ts @@ -2,18 +2,15 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { - indexedIndustryDefinition, - indexedIndustryObservations, -} from './tanstack' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { createExampleChart, indexedIndustryObservations } from './tanstack' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import type { ChartPoint, ChartSpecDatum } from '@tanstack/charts' -type IndexedDatum = ChartSpecDatum> +type IndexedDatum = ChartSpecDatum> describe('definition-owned indexed industry lines', () => { it('normalizes within each industry and preserves one-row lineage', () => { - const scene = render(indexedIndustryObservations) + const scene = render() const lines = points(scene.points, 'indexed-lines') const labels = points(scene.points, 'end-labels') const chronological = [...indexedIndustryObservations].sort( @@ -54,33 +51,6 @@ describe('definition-owned indexed industry lines', () => { } }) - it('keeps baselines and newest labels stable when input rows are reordered', () => { - const canonical = render(indexedIndustryObservations) - const reorderedRows = [...indexedIndustryObservations].reverse() - const reordered = render(reorderedRows) - const canonicalValues = new Map( - points(canonical.points, 'indexed-lines').map(({ datum }) => [ - datumKey(datum), - datum.indexed, - ]), - ) - - for (const { datum } of points(reordered.points, 'indexed-lines')) { - expect(datum.indexed).toBeCloseTo(canonicalValues.get(datumKey(datum))!) - expect(reorderedRows).toContain(datum.source[0]) - } - - expect( - points(reordered.points, 'end-labels') - .map(({ datum }) => [datum.industry, datum.date.getTime()]) - .sort(([left], [right]) => String(left).localeCompare(String(right))), - ).toEqual( - points(canonical.points, 'end-labels') - .map(({ datum }) => [datum.industry, datum.date.getTime()]) - .sort(([left], [right]) => String(left).localeCompare(String(right))), - ) - }) - it('keeps normalization and endpoint selection in the definition source closure', () => { const source = readFileSync( resolve( @@ -104,10 +74,15 @@ describe('definition-owned indexed industry lines', () => { }) }) -function render(source: readonly IndustriesRow[]) { +function render() { + const input = { + width: 640, + height: 400, + revision: 0, + } return createChartRuntime().render( - indexedIndustryDefinition(source), - { width: 640, height: 400 }, + createExampleChart({}), + input, ) } @@ -124,7 +99,3 @@ function groupByIndustry(source: readonly IndustriesRow[]) { } return groups } - -function datumKey(datum: IndexedDatum) { - return `${datum.industry}:${datum.date.getTime()}` -} diff --git a/benchmarks/conformance/cases/56-connected-scatter/example.tsx b/benchmarks/conformance/cases/56-connected-scatter/example.tsx index 08e03b8d..d46a1a42 100644 --- a/benchmarks/conformance/cases/56-connected-scatter/example.tsx +++ b/benchmarks/conformance/cases/56-connected-scatter/example.tsx @@ -12,7 +12,7 @@ import { } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' import { curveCatmullRom } from 'd3-shape' -import { driving } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' export const directionTargetIndexes = [14, 28, 42] as const const directionTargetIndexSet: ReadonlySet = new Set( @@ -28,78 +28,69 @@ export const directionPairs = rollingWindow(driving, { ) const labels = driving.filter((row) => row.year % 5 === 0) -export const connectedScatterDefinition = (input?: ExampleOptions) => - defineChart({ - marks: [ - lineY(driving, { - id: 'driving-path', - x: 'miles', - y: 'gas', - stroke: '#64748b', - strokeWidth: 2.25, - curve: d3Curve(curveCatmullRom.alpha(0.5)), - }), - dot(driving, { - id: 'driving-points', - x: 'miles', - y: 'gas', - fill: '#0f766e', - r: 3.25, - }), - arrow(directionPairs, { - id: 'direction-arrows', - x1: ({ source }) => source[0]?.miles, - y1: ({ source }) => source[0]?.gas, - x2: 'miles', - y2: 'gas', - stroke: '#0f766e', - strokeWidth: 1.5, - headLength: 7, - }), - ...(input?.preview === true - ? [] - : [ - text(labels, { - id: 'year-labels', - x: 'miles', - y: 'gas', - text: (row) => `${row.year}`, - fill: '#0f172a', - anchor: 'middle', - dy: -9, - }), - ]), - ], - x: { - scale: scaleLinear, - grid: true, - axis: { label: 'Miles driven per person' }, +export const createExampleChart = (input?: ChartOptions) => + defineChart( + { + marks: [ + lineY(driving, { + id: 'driving-path', + x: 'miles', + y: 'gas', + stroke: '#64748b', + strokeWidth: 2.25, + curve: d3Curve(curveCatmullRom.alpha(0.5)), + }), + dot(driving, { + id: 'driving-points', + x: 'miles', + y: 'gas', + fill: '#0f766e', + r: 3.25, + }), + arrow(directionPairs, { + id: 'direction-arrows', + x1: ({ source }) => source[0]?.miles, + y1: ({ source }) => source[0]?.gas, + x2: 'miles', + y2: 'gas', + stroke: '#0f766e', + strokeWidth: 1.5, + headLength: 7, + }), + ...(input?.preview === true + ? [] + : [ + text(labels, { + id: 'year-labels', + x: 'miles', + y: 'gas', + text: (row) => `${row.year}`, + fill: '#0f172a', + anchor: 'middle', + dy: -9, + }), + ]), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: 'Miles driven per person' }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Cost of gasoline ($ per gallon)' }, + }, }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Cost of gasoline ($ per gallon)' }, - }, - }) -export interface ExampleOptions { - width: number - height: number - revision: number + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Directed connected scatterplot over time' -export const createExampleChart = (options: ExampleOptions) => - defineChart(connectedScatterDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/56-connected-scatter/plot.ts b/benchmarks/conformance/cases/56-connected-scatter/plot.ts index 9de07ac4..a7f91648 100644 --- a/benchmarks/conformance/cases/56-connected-scatter/plot.ts +++ b/benchmarks/conformance/cases/56-connected-scatter/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { driving } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' import { directionSegments } from './transform' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/56-connected-scatter/tanstack.test.ts b/benchmarks/conformance/cases/56-connected-scatter/tanstack.test.ts index 6c61e6c3..25de2adf 100644 --- a/benchmarks/conformance/cases/56-connected-scatter/tanstack.test.ts +++ b/benchmarks/conformance/cases/56-connected-scatter/tanstack.test.ts @@ -1,19 +1,17 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { driving } from '@charts-poc/demo-data/driving' +import { driving } from '@tanstack/charts-data/driving' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { - connectedScatterDefinition, + createExampleChart, directionPairs, directionTargetIndexes, } from './tanstack' -import type { DrivingRow } from '@charts-poc/demo-data/driving' +import type { DrivingRow } from '@tanstack/charts-data/driving' import type { ChartSpecDatum } from '@tanstack/charts' -type ConnectedDatum = ChartSpecDatum< - ReturnType -> +type ConnectedDatum = ChartSpecDatum> type DirectionDatum = (typeof directionPairs)[number] describe('definition-owned connected-scatter direction', () => { @@ -40,7 +38,7 @@ describe('definition-owned connected-scatter direction', () => { it('feeds the window rows directly to native arrows', () => { const scene = createChartRuntime().render( - connectedScatterDefinition(), + createExampleChart(), { width: 640, height: 400 }, ) const arrows = scene.points.filter( diff --git a/benchmarks/conformance/cases/56-connected-scatter/transform.ts b/benchmarks/conformance/cases/56-connected-scatter/transform.ts index 1f1de4de..595dd0a9 100644 --- a/benchmarks/conformance/cases/56-connected-scatter/transform.ts +++ b/benchmarks/conformance/cases/56-connected-scatter/transform.ts @@ -1,4 +1,4 @@ -import type { DrivingRow } from '@charts-poc/demo-data/driving' +import type { DrivingRow } from '@tanstack/charts-data/driving' export interface DirectionSegment { fromYear: number diff --git a/benchmarks/conformance/cases/57-scatter-marginal-histograms/example.tsx b/benchmarks/conformance/cases/57-scatter-marginal-histograms/example.tsx index c9f6f736..6151c212 100644 --- a/benchmarks/conformance/cases/57-scatter-marginal-histograms/example.tsx +++ b/benchmarks/conformance/cases/57-scatter-marginal-histograms/example.tsx @@ -1,7 +1,6 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' import { binX, binY, @@ -9,10 +8,12 @@ import { defineChart, dot, rect, + type ChartPoint, } from '@tanstack/charts' import { viewGrid } from '@tanstack/charts/view' import { scaleLinear } from 'd3-scale' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export type CompletePenguin = PenguinsRow & { readonly flipper_length_mm: number @@ -26,20 +27,16 @@ export const massBoundaries = [ const colors = ['#2563eb', '#ea580c', '#059669'] -function scatterRows(input: ExampleOptions) { - return penguins +export const createExampleChart = (input: ChartOptions) => { + const rows = penguins .filter((row): row is CompletePenguin => { return row.flipper_length_mm !== null && row.body_mass_g !== null }) .slice(input.revision * 8, input.revision * 8 + 320) -} + const scatter = rows + const showLegend = input.preview !== true + const preview = input.preview === true -function scatterMarginalChart( - rows: readonly CompletePenguin[], - scatter: readonly CompletePenguin[], - showLegend: boolean, - preview: boolean, -) { const xBins = binX(rows, { value: 'flipper_length_mm', thresholds: flipperBoundaries, @@ -50,6 +47,8 @@ function scatterMarginalChart( thresholds: massBoundaries, outputs: { count: { reduce: 'count' } }, }) + type MarginalDatum = + CompletePenguin | (typeof xBins)[number] | (typeof yBins)[number] const flipperScale = scaleLinear().domain([ flipperBoundaries[0]!, flipperBoundaries.at(-1)!, @@ -59,157 +58,143 @@ function scatterMarginalChart( massBoundaries.at(-1)!, ]) - return viewGrid({ - id: 'penguin-marginals', - rows: [ - { id: 'top', size: preview ? 48 : 82 }, - { id: 'main', grow: 1 }, - ], - columns: [ - { id: 'main', grow: 1 }, - { id: 'right', size: preview ? 48 : 82 }, - ], - gap: preview ? 4 : 8, - views: [ - { - id: 'main', - row: 'main', - column: 'main', - chart: defineChart({ - marks: [ - dot(scatter, { - id: 'penguins', - x: 'flipper_length_mm', - y: 'body_mass_g', - color: 'species', - key: (row) => - JSON.stringify([ - row.species, - row.island, - row.culmen_length_mm, - row.culmen_depth_mm, - row.flipper_length_mm, - row.body_mass_g, - row.sex, - ]), - r: 3, - fillOpacity: 0.78, - }), - ], - x: { - scale: flipperScale, - grid: true, - axis: { label: 'Flipper length (mm)' }, - }, - y: { - scale: massScale, - grid: true, - axis: { label: 'Body mass (g)' }, - }, - color: { - range: colors, - ...(showLegend - ? { legend: colorLegend({ label: 'Species' }) } - : {}), + return defineChart( + viewGrid({ + id: 'penguin-marginals', + rows: [ + { id: 'top', size: preview ? 48 : 82 }, + { id: 'main', grow: 1 }, + ], + columns: [ + { id: 'main', grow: 1 }, + { id: 'right', size: preview ? 48 : 82 }, + ], + gap: preview ? 4 : 8, + views: [ + { + id: 'main', + row: 'main', + column: 'main', + chart: defineChart({ + marks: [ + dot(scatter, { + id: 'penguins', + x: 'flipper_length_mm', + y: 'body_mass_g', + color: 'species', + key: (row) => + JSON.stringify([ + row.species, + row.island, + row.culmen_length_mm, + row.culmen_depth_mm, + row.flipper_length_mm, + row.body_mass_g, + row.sex, + ]), + r: 3, + fillOpacity: 0.78, + }), + ], + x: { + scale: flipperScale, + grid: true, + axis: { label: 'Flipper length (mm)' }, + }, + y: { + scale: massScale, + grid: true, + axis: { label: 'Body mass (g)' }, + }, + color: { + range: colors, + ...(showLegend + ? { legend: colorLegend({ label: 'Species' }) } + : {}), + }, + ...(preview ? { guides: false, margin: 0 } : {}), + }), + }, + { + id: 'top', + row: 'top', + column: 'main', + share: { x: 'main' }, + chart: defineChart({ + marks: [ + rect(xBins, { + id: 'flipper-histogram', + x: 'x', + x1: 'x1', + x2: 'x2', + y: 'count', + y1: () => 0, + y2: 'count', + fill: '#0ea5e9', + fillOpacity: 0.78, + inset: 1, + }), + ], + x: { scale: flipperScale }, + y: { scale: scaleLinear }, + guides: false, + }), + }, + { + id: 'right', + row: 'main', + column: 'right', + share: { y: 'main' }, + chart: defineChart({ + marks: [ + rect(yBins, { + id: 'mass-histogram', + x: 'count', + x1: () => 0, + x2: 'count', + y: 'y', + y1: 'y1', + y2: 'y2', + fill: '#f97316', + fillOpacity: 0.78, + inset: 1, + }), + ], + x: { scale: scaleLinear }, + y: { scale: massScale }, + guides: false, + }), + }, + ], + }), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: (point: ChartPoint) => { + const datum = point.datum + if ('source' in datum && 'x1' in datum) { + return `Flipper length: ${datum.x1}–${datum.x2} mm · ${datum.count} penguins` + } + if ('source' in datum && 'y1' in datum) { + return `Body mass: ${datum.y1}–${datum.y2} g · ${datum.count} penguins` + } + return `${datum.species} · ${datum.flipper_length_mm} mm · ${datum.body_mass_g} g` }, - ...(preview ? { guides: false, margin: 0 } : {}), - }), - }, - { - id: 'top', - row: 'top', - column: 'main', - share: { x: 'main' }, - chart: defineChart({ - marks: [ - rect(xBins, { - id: 'flipper-histogram', - x: 'x', - x1: 'x1', - x2: 'x2', - y: 'count', - y1: () => 0, - y2: 'count', - fill: '#0ea5e9', - fillOpacity: 0.78, - inset: 1, - }), - ], - x: { scale: flipperScale }, - y: { scale: scaleLinear }, - guides: false, - }), - }, - { - id: 'right', - row: 'main', - column: 'right', - share: { y: 'main' }, - chart: defineChart({ - marks: [ - rect(yBins, { - id: 'mass-histogram', - x: 'count', - x1: () => 0, - x2: 'count', - y: 'y', - y1: 'y1', - y2: 'y2', - fill: '#f97316', - fillOpacity: 0.78, - inset: 1, - }), - ], - x: { scale: scaleLinear }, - y: { scale: massScale }, - guides: false, - }), + }, }, - ], - }) -} - -export const scatterMarginalDefinition = (input: ExampleOptions) => { - const rows = scatterRows(input) - return scatterMarginalChart( - rows, - rows, - input.preview !== true, - input.preview === true, + }, ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Scatterplot with marginal histograms' -export const createExampleChart = (options: ExampleOptions) => - defineChart(scatterMarginalDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: (point) => { - const datum = point.datum - if ('source' in datum && 'x1' in datum) { - return `Flipper length: ${datum.x1}–${datum.x2} mm · ${datum.count} penguins` - } - if ('source' in datum && 'y1' in datum) { - return `Body mass: ${datum.y1}–${datum.y2} g · ${datum.count} penguins` - } - return `${datum.species} · ${datum.flipper_length_mm} mm · ${datum.body_mass_g} g` - }, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/57-scatter-marginal-histograms/plot.ts b/benchmarks/conformance/cases/57-scatter-marginal-histograms/plot.ts index 54429fa9..410cd0e9 100644 --- a/benchmarks/conformance/cases/57-scatter-marginal-histograms/plot.ts +++ b/benchmarks/conformance/cases/57-scatter-marginal-histograms/plot.ts @@ -1,8 +1,8 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { bin, max } from 'd3-array' import { mountObservablePlot } from '../../shared/mount' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' import type { ConformanceMount } from '../../types' type CompletePenguin = PenguinsRow & { diff --git a/benchmarks/conformance/cases/57-scatter-marginal-histograms/tanstack.test.ts b/benchmarks/conformance/cases/57-scatter-marginal-histograms/tanstack.test.ts index 6a39cc8a..8b4eef73 100644 --- a/benchmarks/conformance/cases/57-scatter-marginal-histograms/tanstack.test.ts +++ b/benchmarks/conformance/cases/57-scatter-marginal-histograms/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { describe, expect, expectTypeOf, it } from 'vitest' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartScene } from '@tanstack/charts' import { flipperBoundaries, massBoundaries, - scatterMarginalDefinition, + createExampleChart, } from './tanstack' import type { CompletePenguin } from './tanstack' import type { @@ -26,9 +26,7 @@ describe('scatterplot with marginal histograms', () => { return row.flipper_length_mm !== null && row.body_mass_g !== null }) .slice(revision * 8, revision * 8 + 320) - const definition = scatterMarginalDefinition({ - width: 720, - height: 480, + const definition = createExampleChart({ revision, }) type Datum = ChartSpecDatum @@ -77,10 +75,10 @@ describe('scatterplot with marginal histograms', () => { it.each([320, 640, 960])( 'keeps marginal plot ranges aligned at %spx', (width) => { - const scene = createChartScene( - scatterMarginalDefinition({ width, height: 480, revision: 0 }), - { width, height: 480 }, - ) + const scene = createChartScene(createExampleChart({ revision: 0 }), { + width, + height: 480, + }) const views = directViews(scene.nodes) const main = views.get('penguin-marginals:main:view')! const top = views.get('penguin-marginals:top:view')! diff --git a/benchmarks/conformance/cases/58-select-extrema/example.tsx b/benchmarks/conformance/cases/58-select-extrema/example.tsx index 6400bcfc..1b987eab 100644 --- a/benchmarks/conformance/cases/58-select-extrema/example.tsx +++ b/benchmarks/conformance/cases/58-select-extrema/example.tsx @@ -4,8 +4,8 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, dot, lineY, select, text } from '@tanstack/charts' import { decorative } from '@tanstack/charts/mark/decorative' import { scaleLinear, scaleUtc } from 'd3-scale' -import { aapl } from '@charts-poc/demo-data/aapl' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' const annotationColor = '#dc2626' const dateKey = (row: AaplRow) => row.Date.getTime() @@ -19,82 +19,82 @@ export const maximumAapl = select(aapl, { select: 'max', }) -function selectExtremaChart(rows: readonly AaplRow[], preview = false) { - return defineChart({ - marks: [ - lineY(rows, { - id: 'close-line', - x: 'Date', - y: 'Close', - key: dateKey, - stroke: '#2563eb', - strokeWidth: 2.25, - }), - dot(minimumAapl, { - id: 'minimum-point', - x: 'Date', - y: 'Close', - key: dateKey, - fill: annotationColor, - r: 5, - }), - dot(maximumAapl, { - id: 'maximum-point', - x: 'Date', - y: 'Close', - key: dateKey, - fill: annotationColor, - r: 5, - }), - decorative( - text(minimumAapl, { - id: 'minimum-label', +export interface ChartOptions { + compact?: boolean +} + +export const createExampleChart = ({ compact = false }: ChartOptions = {}) => { + const rows = aapl + const preview = compact ?? false + + return defineChart( + { + marks: [ + lineY(rows, { + id: 'close-line', + x: 'Date', + y: 'Close', + key: dateKey, + stroke: '#2563eb', + strokeWidth: 2.25, + }), + dot(minimumAapl, { + id: 'minimum-point', x: 'Date', y: 'Close', key: dateKey, - text: ({ Close }) => `Low $${Close.toFixed(2)}`, fill: annotationColor, - anchor: preview ? 'start' : 'middle', - dx: preview ? 6 : 0, - dy: preview ? -13 : 13, + r: 5, }), - ), - decorative( - text(maximumAapl, { - id: 'maximum-label', + dot(maximumAapl, { + id: 'maximum-point', x: 'Date', y: 'Close', key: dateKey, - text: ({ Close }) => `High $${Close.toFixed(2)}`, fill: annotationColor, - anchor: 'end', - dx: -7, - dy: preview ? 13 : -13, + r: 5, }), - ), - ], - x: { scale: scaleUtc, axis: { label: 'Date' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Apple close (USD)' } }, - }) -} - -export interface ExampleOptions { - compact?: boolean + decorative( + text(minimumAapl, { + id: 'minimum-label', + x: 'Date', + y: 'Close', + key: dateKey, + text: ({ Close }) => `Low $${Close.toFixed(2)}`, + fill: annotationColor, + anchor: preview ? 'start' : 'middle', + dx: preview ? 6 : 0, + dy: preview ? -13 : 13, + }), + ), + decorative( + text(maximumAapl, { + id: 'maximum-label', + x: 'Date', + y: 'Close', + key: dateKey, + text: ({ Close }) => `High $${Close.toFixed(2)}`, + fill: annotationColor, + anchor: 'end', + dx: -7, + dy: preview ? 13 : -13, + }), + ), + ], + x: { scale: scaleUtc, axis: { label: 'Date' } }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Apple close (USD)' }, + }, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export const selectExtremaDefinition = ({ - compact = false, -}: ExampleOptions = {}) => selectExtremaChart(aapl, compact) - export const exampleAriaLabel = 'Apple closing price with minimum and maximum annotations' -export const createExampleChart = (options: ExampleOptions = {}) => - defineChart(selectExtremaDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/58-select-extrema/plot.ts b/benchmarks/conformance/cases/58-select-extrema/plot.ts index de8db7c2..8708c173 100644 --- a/benchmarks/conformance/cases/58-select-extrema/plot.ts +++ b/benchmarks/conformance/cases/58-select-extrema/plot.ts @@ -1,6 +1,6 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/58-select-extrema/tanstack.test.ts b/benchmarks/conformance/cases/58-select-extrema/tanstack.test.ts index d9ae0689..2cff956a 100644 --- a/benchmarks/conformance/cases/58-select-extrema/tanstack.test.ts +++ b/benchmarks/conformance/cases/58-select-extrema/tanstack.test.ts @@ -1,13 +1,13 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' -import { maximumAapl, minimumAapl, selectExtremaDefinition } from './tanstack' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { maximumAapl, minimumAapl, createExampleChart } from './tanstack' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartSpecDatum, SceneLabel, SceneNode } from '@tanstack/charts' -type ExtremaDatum = ChartSpecDatum> +type ExtremaDatum = ChartSpecDatum> describe('definition-owned extrema annotations', () => { it('selects the original minimum and maximum rows', () => { @@ -26,10 +26,10 @@ describe('definition-owned extrema annotations', () => { }) it('keeps dots as the sole interaction owners for decorative labels', () => { - const scene = createChartRuntime().render( - selectExtremaDefinition(), - { width: 640, height: 400 }, - ) + const scene = createChartRuntime().render(createExampleChart(), { + width: 640, + height: 400, + }) const minimumPoint = point(scene, 'minimum-point') const maximumPoint = point(scene, 'maximum-point') const labels = flatten(scene.nodes).filter( diff --git a/benchmarks/conformance/cases/59-grouped-reducer-bars/example.tsx b/benchmarks/conformance/cases/59-grouped-reducer-bars/example.tsx index b0ad2586..5895a140 100644 --- a/benchmarks/conformance/cases/59-grouped-reducer-bars/example.tsx +++ b/benchmarks/conformance/cases/59-grouped-reducer-bars/example.tsx @@ -3,8 +3,8 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { barY, defineChart, groupBy, text } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' -import { penguins } from '@charts-poc/demo-data/penguins' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' type PenguinWithMass = PenguinsRow & { body_mass_g: number } @@ -14,7 +14,7 @@ const observations = penguins.filter( const formatMass = (value: number) => value.toLocaleString('en-US', { maximumFractionDigits: 3 }) -export const definition = (input?: ExampleOptions) => { +export const createExampleChart = (input?: ChartOptions) => { const rows = groupBy(observations, { by: 'species', outputs: { @@ -22,51 +22,42 @@ export const definition = (input?: ExampleOptions) => { }, }) - return defineChart({ - marks: [ - barY(rows, { - x: 'species', - y: 'meanBodyMass', - fill: '#0ea5e9', - inset: 1, - }), - text(rows, { - x: 'species', - y: 'meanBodyMass', - text: (row) => formatMass(row.meanBodyMass), - fill: '#0c4a6e', - dy: input?.preview === true ? 10 : -8, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + return defineChart( + { + marks: [ + barY(rows, { + x: 'species', + y: 'meanBodyMass', + fill: '#0ea5e9', + inset: 1, + }), + text(rows, { + x: 'species', + y: 'meanBodyMass', + text: (row) => formatMass(row.meanBodyMass), + fill: '#0c4a6e', + dy: input?.preview === true ? 10 : -8, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + }, + y: { + scale: scaleLinear, + grid: true, + axis: { label: 'Mean body mass (g)' }, + }, }, - y: { - scale: scaleLinear, - grid: true, - axis: { label: 'Mean body mass (g)' }, - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number - revision: number +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Mean penguin body mass by species' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/59-grouped-reducer-bars/plot.ts b/benchmarks/conformance/cases/59-grouped-reducer-bars/plot.ts index 7df552ae..3b50359a 100644 --- a/benchmarks/conformance/cases/59-grouped-reducer-bars/plot.ts +++ b/benchmarks/conformance/cases/59-grouped-reducer-bars/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/60-lag-autocorrelation/example.tsx b/benchmarks/conformance/cases/60-lag-autocorrelation/example.tsx index d1e197c3..1e45b5ef 100644 --- a/benchmarks/conformance/cases/60-lag-autocorrelation/example.tsx +++ b/benchmarks/conformance/cases/60-lag-autocorrelation/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, dot, first, lineY, rollingWindow } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' interface ReferencePoint { PreviousClose: number @@ -17,7 +17,7 @@ const identity: readonly ReferencePoint[] = [ { PreviousClose: closeDomain[1], Close: closeDomain[1] }, ] -export const lagAutocorrelationDefinition = () => { +export const createExampleChart = () => { const rows = rollingWindow(observations, { size: 2, orderBy: 'Date', @@ -25,44 +25,41 @@ export const lagAutocorrelationDefinition = () => { outputs: { PreviousClose: { value: 'Close', reduce: first } }, }) - return defineChart({ - marks: [ - lineY(identity, { - x: 'PreviousClose', - y: 'Close', - stroke: '#94a3b8', - strokeDasharray: '5,4', - }), - dot(rows, { - x: 'PreviousClose', - y: 'Close', - fill: '#7c3aed', - fillOpacity: 0.78, - r: 4, - }), - ], - x: { - scale: scaleLinear().domain(closeDomain), - grid: true, - axis: { label: 'Previous close (USD)' }, + return defineChart( + { + marks: [ + lineY(identity, { + x: 'PreviousClose', + y: 'Close', + stroke: '#94a3b8', + strokeDasharray: '5,4', + }), + dot(rows, { + x: 'PreviousClose', + y: 'Close', + fill: '#7c3aed', + fillOpacity: 0.78, + r: 4, + }), + ], + x: { + scale: scaleLinear().domain(closeDomain), + grid: true, + axis: { label: 'Previous close (USD)' }, + }, + y: { + scale: scaleLinear().domain(closeDomain), + grid: true, + axis: { label: 'Current close (USD)' }, + }, }, - y: { - scale: scaleLinear().domain(closeDomain), - grid: true, - axis: { label: 'Current close (USD)' }, - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } export const exampleAriaLabel = 'Lag-one autocorrelation of Apple closing prices' -export const createExampleChart = () => - defineChart(lagAutocorrelationDefinition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/60-lag-autocorrelation/plot.ts b/benchmarks/conformance/cases/60-lag-autocorrelation/plot.ts index 6321f113..34fabd43 100644 --- a/benchmarks/conformance/cases/60-lag-autocorrelation/plot.ts +++ b/benchmarks/conformance/cases/60-lag-autocorrelation/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/61-quantile-ribbon/example.tsx b/benchmarks/conformance/cases/61-quantile-ribbon/example.tsx index ac212f73..338836c8 100644 --- a/benchmarks/conformance/cases/61-quantile-ribbon/example.tsx +++ b/benchmarks/conformance/cases/61-quantile-ribbon/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { areaY, defineChart, groupBy, lineY, quantile } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' export const quantileRows = groupBy(industries, { by: 'date', @@ -16,55 +16,49 @@ export const quantileRows = groupBy(industries, { const dateKey = ({ date }: (typeof quantileRows)[number]) => date.getTime() -function quantileRibbonChart( - rows: readonly (typeof quantileRows)[number][], - showAxisLabels: boolean, -) { - return defineChart({ - marks: [ - areaY(rows, { - id: 'quantile-ribbon', - x: 'date', - y1: 'lower', - y2: 'upper', - key: dateKey, - fill: '#0ea5e9', - fillOpacity: 0.22, - }), - lineY(rows, { - id: 'median-line', - x: 'date', - y: 'median', - key: dateKey, - stroke: '#0369a1', - strokeWidth: 2.25, - }), - ], - x: { - scale: scaleUtc, - axis: showAxisLabels ? { label: 'Month' } : {}, - }, - y: { - scale: scaleLinear, - grid: true, - axis: showAxisLabels - ? { label: 'Unemployed people by industry (thousands)' } - : {}, +export const createExampleChart = () => { + const rows = quantileRows + const showAxisLabels = true + + return defineChart( + { + marks: [ + areaY(rows, { + id: 'quantile-ribbon', + x: 'date', + y1: 'lower', + y2: 'upper', + key: dateKey, + fill: '#0ea5e9', + fillOpacity: 0.22, + }), + lineY(rows, { + id: 'median-line', + x: 'date', + y: 'median', + key: dateKey, + stroke: '#0369a1', + strokeWidth: 2.25, + }), + ], + x: { + scale: scaleUtc, + axis: showAxisLabels ? { label: 'Month' } : {}, + }, + y: { + scale: scaleLinear, + grid: true, + axis: showAxisLabels + ? { label: 'Unemployed people by industry (thousands)' } + : {}, + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export const quantileRibbonDefinition = () => - quantileRibbonChart(quantileRows, true) - export const exampleAriaLabel = 'Monthly industry unemployment distribution' -export const createExampleChart = () => - defineChart(quantileRibbonDefinition(), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart() export default function Example() { diff --git a/benchmarks/conformance/cases/61-quantile-ribbon/plot.ts b/benchmarks/conformance/cases/61-quantile-ribbon/plot.ts index 9bc47cec..b0dfaedf 100644 --- a/benchmarks/conformance/cases/61-quantile-ribbon/plot.ts +++ b/benchmarks/conformance/cases/61-quantile-ribbon/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/61-quantile-ribbon/tanstack.test.ts b/benchmarks/conformance/cases/61-quantile-ribbon/tanstack.test.ts index 71961722..6c9945bc 100644 --- a/benchmarks/conformance/cases/61-quantile-ribbon/tanstack.test.ts +++ b/benchmarks/conformance/cases/61-quantile-ribbon/tanstack.test.ts @@ -1,14 +1,14 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { createChartRuntime, groupBy, quantile } from '@tanstack/charts' import { quantile as d3Quantile } from 'd3-array' import { describe, expect, expectTypeOf, it } from 'vitest' -import { quantileRibbonDefinition, quantileRows } from './tanstack' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import { createExampleChart, quantileRows } from './tanstack' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import type { ChartSpecDatum } from '@tanstack/charts' -type QuantileDatum = ChartSpecDatum> +type QuantileDatum = ChartSpecDatum> describe('definition-owned quantile ribbon', () => { it('groups public quantile reducers with exact source lineage', () => { @@ -72,7 +72,7 @@ describe('definition-owned quantile ribbon', () => { it('feeds the same aggregate rows to the ribbon and median line', () => { const scene = createChartRuntime().render( - quantileRibbonDefinition(), + createExampleChart(), { width: 640, height: 400 }, ) const ribbon = scene.points.filter( @@ -104,7 +104,8 @@ describe('definition-owned quantile ribbon', () => { expect(source).toContain('quantile(0.1)') expect(source).toContain('quantile(0.5)') expect(source).toContain('quantile(0.9)') - expect(source).toContain('quantileRibbonChart(quantileRows, true)') + expect(source).toContain('const rows = quantileRows') + expect(source).toContain('const showAxisLabels = true') expect(source).toContain('areaY(rows') expect(source).toContain('lineY(rows') expect(source).not.toContain('summarizeQuantiles') diff --git a/benchmarks/conformance/cases/62-ridgeline-density/example.tsx b/benchmarks/conformance/cases/62-ridgeline-density/example.tsx index 762b9199..e64640c8 100644 --- a/benchmarks/conformance/cases/62-ridgeline-density/example.tsx +++ b/benchmarks/conformance/cases/62-ridgeline-density/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import { binX, d3Curve, @@ -17,7 +17,7 @@ import type { RatedEpisode } from './selection' const colors = ['#2563eb', '#0d9488', '#d97706'] -export const ridgelineDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const seasons = ridgeSeasons(input.revision) const episodes = simpsons.filter( (row): row is RatedEpisode => @@ -38,66 +38,57 @@ export const ridgelineDefinition = (input: ExampleOptions) => { const overlap = 0.78 const curve = d3Curve(curveBasis) - return defineChart({ - marks: [ - ruleY(seasons, { - id: 'season-guides', - stroke: '#94a3b8', - strokeOpacity: 0.5, - }), - ridgelineY(rows, { - id: 'rating-ridges', - x: 'x', - y: 'season', - height: 'height', - key: (row) => `${row.season}:${row.x}`, - overlap, - color: 'season', - fillOpacity: 0.52, - strokeWidth: 1.5, - curve, - }), - ], - x: { - scale: scaleLinear().domain([4, 10]), - grid: true, - axis: { label: 'IMDb rating' }, - }, - y: { - scale: scalePoint().domain(seasons).padding(overlap), - reverse: true, - axis: { - ticks: { - values: seasons, - format: (season) => `Season ${season}`, + return defineChart( + { + marks: [ + ruleY(seasons, { + id: 'season-guides', + stroke: '#94a3b8', + strokeOpacity: 0.5, + }), + ridgelineY(rows, { + id: 'rating-ridges', + x: 'x', + y: 'season', + height: 'height', + key: (row) => `${row.season}:${row.x}`, + overlap, + color: 'season', + fillOpacity: 0.52, + strokeWidth: 1.5, + curve, + }), + ], + x: { + scale: scaleLinear().domain([4, 10]), + grid: true, + axis: { label: 'IMDb rating' }, + }, + y: { + scale: scalePoint().domain(seasons).padding(overlap), + reverse: true, + axis: { + ticks: { + values: seasons, + format: (season) => `Season ${season}`, + }, }, }, + color: { + range: colors, + }, }, - color: { - range: colors, - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Ridgeline density comparison' -export const createExampleChart = (options: ExampleOptions) => - defineChart(ridgelineDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/62-ridgeline-density/plot.ts b/benchmarks/conformance/cases/62-ridgeline-density/plot.ts index 9bf9814c..bdf37657 100644 --- a/benchmarks/conformance/cases/62-ridgeline-density/plot.ts +++ b/benchmarks/conformance/cases/62-ridgeline-density/plot.ts @@ -1,4 +1,4 @@ -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import * as Plot from '@observablehq/plot' import { isRatedEpisode, ridgeSeasons } from './selection' import { ridgeDensity } from './transform' diff --git a/benchmarks/conformance/cases/62-ridgeline-density/selection.ts b/benchmarks/conformance/cases/62-ridgeline-density/selection.ts index 56374785..6678c93d 100644 --- a/benchmarks/conformance/cases/62-ridgeline-density/selection.ts +++ b/benchmarks/conformance/cases/62-ridgeline-density/selection.ts @@ -1,4 +1,4 @@ -import type { SimpsonsRow } from '@charts-poc/demo-data/simpsons' +import type { SimpsonsRow } from '@tanstack/charts-data/simpsons' export type RatedEpisode = SimpsonsRow & { readonly imdb_rating: number diff --git a/benchmarks/conformance/cases/62-ridgeline-density/tanstack.test.ts b/benchmarks/conformance/cases/62-ridgeline-density/tanstack.test.ts index 1adfce94..588ff8ac 100644 --- a/benchmarks/conformance/cases/62-ridgeline-density/tanstack.test.ts +++ b/benchmarks/conformance/cases/62-ridgeline-density/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { isRatedEpisode, ratingBoundaries, ridgeSeasons } from './selection' -import { ridgelineDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { RatedEpisode } from './selection' import type { ChartSpecDatum, @@ -23,9 +23,7 @@ describe('ridgeline density comparison', () => { (row): row is RatedEpisode => isRatedEpisode(row) && seasons.includes(row.season), ) - const definition = ridgelineDefinition({ - width: 720, - height: 480, + const definition = createExampleChart({ revision, }) type Datum = ChartSpecDatum @@ -95,9 +93,7 @@ describe('ridgeline density comparison', () => { it.each([320, 640, 960])( 'derives responsive ridge offsets from the semantic category step at %spx', (width) => { - const definition = ridgelineDefinition({ - width, - height: 480, + const definition = createExampleChart({ revision: 0, }) const scene = createChartScene(definition, { width, height: 480 }) @@ -152,9 +148,7 @@ describe('ridgeline density comparison', () => { ) it('keeps stable semantic identities while resizing', () => { - const definition = ridgelineDefinition({ - width: 640, - height: 480, + const definition = createExampleChart({ revision: 0, }) const narrow = createChartScene(definition, { width: 320, height: 360 }) diff --git a/benchmarks/conformance/cases/62-ridgeline-density/transform.test.ts b/benchmarks/conformance/cases/62-ridgeline-density/transform.test.ts index 0fd24931..ee554a64 100644 --- a/benchmarks/conformance/cases/62-ridgeline-density/transform.test.ts +++ b/benchmarks/conformance/cases/62-ridgeline-density/transform.test.ts @@ -1,4 +1,4 @@ -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import { describe, expect, it } from 'vitest' import { isRatedEpisode, ridgeSeasons } from './selection' import { ridgeDensity } from './transform' diff --git a/benchmarks/conformance/cases/63-violin-distributions/example.tsx b/benchmarks/conformance/cases/63-violin-distributions/example.tsx index 9f616c09..f145243b 100644 --- a/benchmarks/conformance/cases/63-violin-distributions/example.tsx +++ b/benchmarks/conformance/cases/63-violin-distributions/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { binY, d3AreaXCurve, @@ -19,7 +19,7 @@ import { isPenguinMass, massBoundaries, violinSpecies } from './selection' const colors = ['#64748b', '#0d9488', '#7c3aed'] -export const violinDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const observations = penguins .filter(isPenguinMass) .slice(input.revision * 8, input.revision * 8 + 320) @@ -42,81 +42,75 @@ export const violinDefinition = (input: ExampleOptions) => { }, }) - return defineChart({ - marks: [ - violinY(profiles, { - id: 'mass-violins', - x: 'species', - y: 'y', - width: 'width', - key: (row) => `${row.species}:${row.y}`, - span: 0.76, - color: 'species', - fillOpacity: 0.58, - curve: d3AreaXCurve(curveBasis), - }), - tickY(summaries, { - id: 'median-ticks', - x: 'species', - y: 'median', - key: 'species', - span: 0.36, - stroke: '#0f172a', - strokeWidth: 2, - }), - dot(summaries, { - id: 'median-dots', - x: 'species', - y: 'median', - key: 'species', - color: 'species', - stroke: '#ffffff', - strokeWidth: 1, - r: 3.5, - }), - ], - x: { - scale: scalePoint().domain(violinSpecies).padding(0.5), + return defineChart( + { + marks: [ + violinY(profiles, { + id: 'mass-violins', + x: 'species', + y: 'y', + width: 'width', + key: (row) => `${row.species}:${row.y}`, + span: 0.76, + color: 'species', + fillOpacity: 0.58, + curve: d3AreaXCurve(curveBasis), + }), + tickY(summaries, { + id: 'median-ticks', + x: 'species', + y: 'median', + key: 'species', + span: 0.36, + stroke: '#0f172a', + strokeWidth: 2, + }), + dot(summaries, { + id: 'median-dots', + x: 'species', + y: 'median', + key: 'species', + color: 'species', + stroke: '#ffffff', + strokeWidth: 1, + r: 3.5, + }), + ], + x: { + scale: scalePoint().domain(violinSpecies).padding(0.5), + }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Body mass (g)' } }, + color: { + domain: violinSpecies, + range: colors, + }, }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Body mass (g)' } }, - color: { - domain: violinSpecies, - range: colors, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'median' in datum + ? `${datum.species} · median body mass ${datum.median.toLocaleString( + 'en-US', + )} g` + : `${datum.species} · distribution at ${datum.y.toLocaleString( + 'en-US', + )} g`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Violin distribution comparison' -export const createExampleChart = (options: ExampleOptions) => - defineChart(violinDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'median' in datum - ? `${datum.species} · median body mass ${datum.median.toLocaleString( - 'en-US', - )} g` - : `${datum.species} · distribution at ${datum.y.toLocaleString( - 'en-US', - )} g`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/63-violin-distributions/plot.ts b/benchmarks/conformance/cases/63-violin-distributions/plot.ts index f2c6e76c..2d49842f 100644 --- a/benchmarks/conformance/cases/63-violin-distributions/plot.ts +++ b/benchmarks/conformance/cases/63-violin-distributions/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import { isPenguinMass, violinSpecies } from './selection' import { violinDensity, violinMedians } from './transform' diff --git a/benchmarks/conformance/cases/63-violin-distributions/selection.ts b/benchmarks/conformance/cases/63-violin-distributions/selection.ts index fa0b8dd0..533f6b59 100644 --- a/benchmarks/conformance/cases/63-violin-distributions/selection.ts +++ b/benchmarks/conformance/cases/63-violin-distributions/selection.ts @@ -1,4 +1,4 @@ -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export const violinSpecies = ['Adelie', 'Chinstrap', 'Gentoo'] as const export type ViolinSpecies = (typeof violinSpecies)[number] diff --git a/benchmarks/conformance/cases/63-violin-distributions/tanstack.test.ts b/benchmarks/conformance/cases/63-violin-distributions/tanstack.test.ts index 86d98488..3731dd25 100644 --- a/benchmarks/conformance/cases/63-violin-distributions/tanstack.test.ts +++ b/benchmarks/conformance/cases/63-violin-distributions/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { isPenguinMass, massBoundaries, violinSpecies } from './selection' -import { violinDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ViolinSpecies } from './selection' import type { ChartPoint, @@ -27,9 +27,7 @@ describe('violin distribution comparison', () => { const observations = penguins .filter(isPenguinMass) .slice(revision * 8, revision * 8 + 320) - const definition = violinDefinition({ - width: 720, - height: 480, + const definition = createExampleChart({ revision, }) type Datum = ChartSpecDatum @@ -121,10 +119,10 @@ describe('violin distribution comparison', () => { it.each([320, 640, 960])( 'keeps envelopes and median ticks symmetric in category-step units at %spx', (width) => { - const scene = createChartScene( - violinDefinition({ width, height: 480, revision: 0 }), - { width, height: 480 }, - ) + const scene = createChartScene(createExampleChart({ revision: 0 }), { + width, + height: 480, + }) const areas = sceneAreas(scene.nodes) const rules = sceneRules(scene.nodes).filter((rule) => rule.key.startsWith('median-ticks:'), @@ -171,9 +169,7 @@ describe('violin distribution comparison', () => { ) it('keeps semantic identities stable while resizing', () => { - const definition = violinDefinition({ - width: 640, - height: 480, + const definition = createExampleChart({ revision: 0, }) const narrow = createChartScene(definition, { width: 320, height: 360 }) diff --git a/benchmarks/conformance/cases/63-violin-distributions/transform.test.ts b/benchmarks/conformance/cases/63-violin-distributions/transform.test.ts index f74c7a95..b284686a 100644 --- a/benchmarks/conformance/cases/63-violin-distributions/transform.test.ts +++ b/benchmarks/conformance/cases/63-violin-distributions/transform.test.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { describe, expect, it } from 'vitest' import { isPenguinMass } from './selection' import { violinDensity, violinMedians } from './transform' diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/example.tsx b/benchmarks/conformance/cases/64-marimekko-mosaic/example.tsx index 01be5b28..b68b398b 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/example.tsx +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/example.tsx @@ -12,13 +12,13 @@ import { } from '@tanstack/charts' import { format } from 'd3-format' import { scaleLinear } from 'd3-scale' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { isMosaicResponse, mosaicResponses } from './selection' const percent = format('.0%') const colors = ['#991b1b', '#ef4444', '#cbd5e1', '#60a5fa', '#1d4ed8'] -export const marimekkoDefinition = (input?: ExampleOptions) => { +export const createExampleChart = (input?: ChartOptions) => { const observations = survey.filter(isMosaicResponse) const counts = groupBy(observations, { by: { @@ -38,68 +38,59 @@ export const marimekkoDefinition = (input?: ExampleOptions) => { select: 'first', }) - return defineChart({ - marks: [ - rect(cells, { - id: 'response-cells', - x: 'x', - x1: 'x1', - x2: 'x2', - y: 'y', - y1: 'y1', - y2: 'y2', - color: 'yValue', - key: (datum) => `${datum.xValue}:${datum.yValue}`, - inset: 1, - }), - ...(input?.preview === true - ? [] - : [ - text(labels, { - id: 'question-labels', - x: 'x', - y: () => 1.055, - text: 'Question', - key: 'xValue', - fill: '#334155', - fontSize: 11, - }), - ]), - ], - x: { - scale: scaleLinear().domain([0, 1]), - axis: { ticks: { format: percent }, label: 'Share of responses' }, + return defineChart( + { + marks: [ + rect(cells, { + id: 'response-cells', + x: 'x', + x1: 'x1', + x2: 'x2', + y: 'y', + y1: 'y1', + y2: 'y2', + color: 'yValue', + key: (datum) => `${datum.xValue}:${datum.yValue}`, + inset: 1, + }), + ...(input?.preview === true + ? [] + : [ + text(labels, { + id: 'question-labels', + x: 'x', + y: () => 1.055, + text: 'Question', + key: 'xValue', + fill: '#334155', + fontSize: 11, + }), + ]), + ], + x: { + scale: scaleLinear().domain([0, 1]), + axis: { ticks: { format: percent }, label: 'Share of responses' }, + }, + y: { + scale: scaleLinear().domain([0, 1.12]), + axis: { ticks: { format: percent }, label: 'Within-question share' }, + }, + color: { + domain: mosaicResponses, + range: colors, + legend: colorLegend({ label: 'Response' }), + }, }, - y: { - scale: scaleLinear().domain([0, 1.12]), - axis: { ticks: { format: percent }, label: 'Within-question share' }, - }, - color: { - domain: mosaicResponses, - range: colors, - legend: colorLegend({ label: 'Response' }), - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number - revision: number +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Marimekko survey composition' -export const createExampleChart = (options: ExampleOptions) => - defineChart(marimekkoDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/layout.test.ts b/benchmarks/conformance/cases/64-marimekko-mosaic/layout.test.ts index 0c76e31a..2ce5e96e 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/layout.test.ts +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/layout.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' import { group, sum } from 'd3-array' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { mosaicLayout, mosaicResponses } from './layout' describe('mosaicLayout', () => { diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/layout.ts b/benchmarks/conformance/cases/64-marimekko-mosaic/layout.ts index 43c8095a..a5506e4d 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/layout.ts +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/layout.ts @@ -1,5 +1,5 @@ import { cumsum, group, rollup, sum } from 'd3-array' -import type { SurveyRow } from '@charts-poc/demo-data/survey' +import type { SurveyRow } from '@tanstack/charts-data/survey' import { mosaicResponses } from './selection' export { mosaicResponses } from './selection' diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/plot.ts b/benchmarks/conformance/cases/64-marimekko-mosaic/plot.ts index 5c3fdf22..ef901f58 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/plot.ts +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { mosaicLayout, mosaicResponses } from './layout' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/selection.ts b/benchmarks/conformance/cases/64-marimekko-mosaic/selection.ts index 7b69c527..9a85ce93 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/selection.ts +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/selection.ts @@ -1,4 +1,4 @@ -import type { SurveyRow } from '@charts-poc/demo-data/survey' +import type { SurveyRow } from '@tanstack/charts-data/survey' export const mosaicResponses = [ 'Strongly Disagree', diff --git a/benchmarks/conformance/cases/64-marimekko-mosaic/tanstack.test.ts b/benchmarks/conformance/cases/64-marimekko-mosaic/tanstack.test.ts index 7104fa50..47b6e9ab 100644 --- a/benchmarks/conformance/cases/64-marimekko-mosaic/tanstack.test.ts +++ b/benchmarks/conformance/cases/64-marimekko-mosaic/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { isMosaicResponse, mosaicResponses } from './selection' -import { marimekkoDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ChartPoint, ChartSpecDatum, @@ -24,7 +24,7 @@ const expectedQuestionTotals = { describe('Marimekko survey composition', () => { it('keeps aggregation policy explicit and allocates both denominators declaratively', () => { const observations = survey.filter(isMosaicResponse) - const definition = marimekkoDefinition() + const definition = createExampleChart() type Datum = ChartSpecDatum expectTypeOf().toEqualTypeOf() expectTypeOf().toEqualTypeOf() @@ -111,7 +111,7 @@ describe('Marimekko survey composition', () => { it.each([320, 640, 960])( 'renders ordinary rectangles and labels at %spx', (width) => { - const scene = createChartScene(marimekkoDefinition(), { + const scene = createChartScene(createExampleChart(), { width, height: 480, }) @@ -151,7 +151,7 @@ describe('Marimekko survey composition', () => { ) it('keeps cell and label identity stable while resizing', () => { - const definition = marimekkoDefinition() + const definition = createExampleChart() const narrow = createChartScene(definition, { width: 320, height: 360 }) const wide = createChartScene(definition, { width: 960, height: 600 }) const narrowPoints = narrow.points.filter((point) => diff --git a/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/example.tsx b/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/example.tsx index eaa38824..b7e4d205 100644 --- a/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/example.tsx +++ b/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/example.tsx @@ -1,5 +1,5 @@ -import { cars } from '@charts-poc/demo-data/cars' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' import { defineChart, dot } from '@tanstack/charts' import { Chart } from '@tanstack/charts/react/tooltip' import { voronoi } from '@tanstack/charts/spatial/voronoi' @@ -8,7 +8,7 @@ import { scaleLinear } from 'd3-scale' import type { ChartTooltipOptions } from '@tanstack/charts' export type CompleteCar = CarsRow & { readonly 'economy (mpg)': number } -export interface ExampleOptions { +export interface ChartOptions { revision?: number } @@ -24,7 +24,7 @@ const interactiveTooltip: ChartTooltipOptions = { ], } -export function createExampleChart({ revision = 0 }: ExampleOptions = {}) { +export function createExampleChart({ revision = 0 }: ChartOptions = {}) { const rows = selectedCars(revision) return defineChart( { diff --git a/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/plot.ts b/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/plot.ts index 51857d3b..128387fe 100644 --- a/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/plot.ts +++ b/benchmarks/conformance/cases/65-voronoi-nearest-tooltip/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount, ConformanceTestDriver } from '../../types' diff --git a/benchmarks/conformance/cases/70-composed-chart/example.tsx b/benchmarks/conformance/cases/70-composed-chart/example.tsx index 42af244b..3758097e 100644 --- a/benchmarks/conformance/cases/70-composed-chart/example.tsx +++ b/benchmarks/conformance/cases/70-composed-chart/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { areaY, barY, d3Curve, defineChart, dot, lineY } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' import { curveMonotoneX } from 'd3-shape' @@ -13,71 +13,62 @@ const dateFormat = new Intl.DateTimeFormat('en-US', { timeZone: 'UTC', }) -export const composedChartDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const start = input.revision % 2 === 0 ? 37 : 68 const rows = weather.slice(start, start + 6) - return defineChart({ - marks: [ - areaY(rows, { - x: 'date', - y: 'temp_max', - fill: '#8884d8', - fillOpacity: 0.2, - stroke: '#8884d8', - curve: monotone, - }), - barY(rows, { - id: 'precipitation-bars', - x: 'date', - y: 'precipitation', - fill: '#413ea0', - maxThickness: 20, - }), - lineY(rows, { - x: 'date', - y: 'temp_min', - stroke: '#ff7300', - strokeWidth: 2, - curve: monotone, - }), - dot(rows, { - x: 'date', - y: 'wind', - fill: '#ef4444', - r: 4.5, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), - axis: { - ticks: { format: (value: Date) => dateFormat.format(value) }, + return defineChart( + { + marks: [ + areaY(rows, { + x: 'date', + y: 'temp_max', + fill: '#8884d8', + fillOpacity: 0.2, + stroke: '#8884d8', + curve: monotone, + }), + barY(rows, { + id: 'precipitation-bars', + x: 'date', + y: 'precipitation', + fill: '#413ea0', + maxThickness: 20, + }), + lineY(rows, { + x: 'date', + y: 'temp_min', + stroke: '#ff7300', + strokeWidth: 2, + curve: monotone, + }), + dot(rows, { + x: 'date', + y: 'wind', + fill: '#ef4444', + r: 4.5, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + axis: { + ticks: { format: (value: Date) => dateFormat.format(value) }, + }, }, + y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 5 } } }, + margin: { top: 20, right: 20, bottom: 50, left: 80 }, }, - y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 5 } } }, - margin: { top: 20, right: 20, bottom: 50, left: 80 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Layered Seattle weather' -export const createExampleChart = (options: ExampleOptions) => - defineChart(composedChartDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/70-composed-chart/recharts.ts b/benchmarks/conformance/cases/70-composed-chart/recharts.ts index 42fa0325..a5ff8449 100644 --- a/benchmarks/conformance/cases/70-composed-chart/recharts.ts +++ b/benchmarks/conformance/cases/70-composed-chart/recharts.ts @@ -1,4 +1,4 @@ -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { createElement } from 'react' import { Area, diff --git a/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts b/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts index ec26dd1d..16733b7e 100644 --- a/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts +++ b/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts @@ -1,7 +1,7 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { loadTanStackSources } from '../../native-catalog' -import { composedChartDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -58,10 +58,7 @@ describe('native composed-chart bar sizing', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - composedChartDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function flatten(nodes: readonly SceneNode[]): SceneNode[] { diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/example.tsx b/benchmarks/conformance/cases/71-recharts-population-pyramid/example.tsx index 351c5e19..4047710b 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/example.tsx +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/example.tsx @@ -1,14 +1,14 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { barX, defineChart, groupBy, stack } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' import { isSexedPenguin, pyramidSexes } from './selection' const colors = ['#2563eb', '#db2777'] -export const populationPyramidDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const sourceRows = input.revision % 2 === 0 ? penguins : penguins.slice(0, -8) const observations = sourceRows.filter(isSexedPenguin) const counts = groupBy(observations, { @@ -19,60 +19,51 @@ export const populationPyramidDefinition = (input: ExampleOptions) => { outputs: { count: { reduce: 'count' } }, }) - return defineChart({ - marks: [ - barX(counts, { - id: 'population-bars', - x: (row) => (row.sex === 'MALE' ? -row.count : row.count), - y: 'species', - z: 'sex', - color: 'sex', - layout: stack({ offset: 'diverging', order: pyramidSexes }), - key: (row) => `${row.species}:${row.sex}`, - inset: 0.5, - }), - ], - x: { - scale: scaleLinear().domain([-80, 80]), - grid: true, - axis: { - ticks: { - count: 5, - format: (value) => Math.abs(value).toLocaleString('en-US'), + return defineChart( + { + marks: [ + barX(counts, { + id: 'population-bars', + x: (row) => (row.sex === 'MALE' ? -row.count : row.count), + y: 'species', + z: 'sex', + color: 'sex', + layout: stack({ offset: 'diverging', order: pyramidSexes }), + key: (row) => `${row.species}:${row.sex}`, + inset: 0.5, + }), + ], + x: { + scale: scaleLinear().domain([-80, 80]), + grid: true, + axis: { + ticks: { + count: 5, + format: (value) => Math.abs(value).toLocaleString('en-US'), + }, + label: 'Penguins observed', }, - label: 'Penguins observed', }, + y: { + scale: () => scaleBand().paddingInner(0.02).paddingOuter(0.01), + }, + color: { + domain: pyramidSexes, + range: colors, + }, + margin: { top: 20, right: 20, bottom: 70, left: 80 }, }, - y: { - scale: () => scaleBand().paddingInner(0.02).paddingOuter(0.01), - }, - color: { - domain: pyramidSexes, - range: colors, - }, - margin: { top: 20, right: 20, bottom: 70, left: 80 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Palmer penguins by species and sex' -export const createExampleChart = (options: ExampleOptions) => - defineChart(populationPyramidDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/recharts.ts b/benchmarks/conformance/cases/71-recharts-population-pyramid/recharts.ts index 82fb3ed7..07845824 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/recharts.ts +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/recharts.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createElement } from 'react' import { Bar, BarChart, XAxis, YAxis } from 'recharts' import { countPenguinsBySpecies, divergeMaleCounts } from './transform' diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/selection.ts b/benchmarks/conformance/cases/71-recharts-population-pyramid/selection.ts index 829f8ed6..eb4d50e3 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/selection.ts +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/selection.ts @@ -1,4 +1,4 @@ -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export const pyramidSexes = ['MALE', 'FEMALE'] as const diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/tanstack.test.ts b/benchmarks/conformance/cases/71-recharts-population-pyramid/tanstack.test.ts index cfba4e14..af496a0f 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/tanstack.test.ts +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { isSexedPenguin, pyramidSexes } from './selection' -import { populationPyramidDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ChartPoint, ChartSpecDatum, @@ -38,9 +38,7 @@ describe('definition-owned population pyramid', () => { (revision) => { const sourceRows = revision === 0 ? penguins : penguins.slice(0, -8) const observations = sourceRows.filter(isSexedPenguin) - const definition = populationPyramidDefinition({ - width: 640, - height: 400, + const definition = createExampleChart({ revision, }) type Datum = ChartSpecDatum @@ -89,10 +87,10 @@ describe('definition-owned population pyramid', () => { it('keeps semantic bar identities stable across data revisions', () => { const keys = [0, 1].map((revision) => - createChartScene( - populationPyramidDefinition({ width: 640, height: 400, revision }), - { width: 640, height: 400 }, - ) + createChartScene(createExampleChart({ revision }), { + width: 640, + height: 400, + }) .points.filter((point) => point.markId === 'population-bars') .map((point) => point.key), ) @@ -103,10 +101,10 @@ describe('definition-owned population pyramid', () => { it.each([320, 640, 960])( 'keeps both sexes joined to the shared zero baseline at %spx', (width) => { - const scene = createChartScene( - populationPyramidDefinition({ width, height: 400, revision: 0 }), - { width, height: 400 }, - ) + const scene = createChartScene(createExampleChart({ revision: 0 }), { + width, + height: 400, + }) const zero = scene.scales.x.map(0) const rectangles = sceneRects(scene.nodes).filter((node) => node.key.startsWith('population-bars:'), @@ -127,9 +125,7 @@ describe('definition-owned population pyramid', () => { ) it('keeps semantic identities stable while resizing', () => { - const definition = populationPyramidDefinition({ - width: 640, - height: 400, + const definition = createExampleChart({ revision: 0, }) const narrow = createChartScene(definition, { width: 320, height: 360 }) diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.test.ts b/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.test.ts index 9c3584e3..4dc2459c 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.test.ts +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.test.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { describe, expect, it } from 'vitest' import { countPenguinsBySpecies, divergeMaleCounts } from './transform' diff --git a/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.ts b/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.ts index 02ccddd2..4ba90848 100644 --- a/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.ts +++ b/benchmarks/conformance/cases/71-recharts-population-pyramid/transform.ts @@ -1,4 +1,4 @@ -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export interface PenguinSpeciesCount { species: string diff --git a/benchmarks/conformance/cases/72-recharts-mixed-bars/example.tsx b/benchmarks/conformance/cases/72-recharts-mixed-bars/example.tsx index f008f575..ab597a5d 100644 --- a/benchmarks/conformance/cases/72-recharts-mixed-bars/example.tsx +++ b/benchmarks/conformance/cases/72-recharts-mixed-bars/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { barY, defineChart, group } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' @@ -16,67 +16,58 @@ const groupScale = scaleBand() .domain(['stack', 'independent']) .paddingInner(0.08) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const start = input.revision % 2 === 0 ? 37 : 68 const rows = weather.slice(start, start + 7) - return defineChart({ - marks: [ - barY(rows, { - x: 'date', - y1: 0, - y2: 'precipitation', - z: () => 'stack', - fill: '#8884d8', - layout: group({ scale: groupScale }), - inset: 1, - }), - barY(rows, { - x: 'date', - y1: 'precipitation', - y2: (row) => row.precipitation + row.wind, - z: () => 'stack', - fill: '#82ca9d', - layout: group({ scale: groupScale }), - inset: 1, - }), - barY(rows, { - x: 'date', - y: 'temp_max', - z: () => 'independent', - fill: '#ffc658', - layout: group({ scale: groupScale }), - inset: 1, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), - axis: { ticks: { format: (value) => dateFormat.format(value) } }, + return defineChart( + { + marks: [ + barY(rows, { + x: 'date', + y1: 0, + y2: 'precipitation', + z: () => 'stack', + fill: '#8884d8', + layout: group({ scale: groupScale }), + inset: 1, + }), + barY(rows, { + x: 'date', + y1: 'precipitation', + y2: (row) => row.precipitation + row.wind, + z: () => 'stack', + fill: '#82ca9d', + layout: group({ scale: groupScale }), + inset: 1, + }), + barY(rows, { + x: 'date', + y: 'temp_max', + z: () => 'independent', + fill: '#ffc658', + layout: group({ scale: groupScale }), + inset: 1, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + axis: { ticks: { format: (value) => dateFormat.format(value) } }, + }, + y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 5 } } }, + margin: { top: 20, right: 20, bottom: 50, left: 80 }, }, - y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 5 } } }, - margin: { top: 20, right: 20, bottom: 50, left: 80 }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Stacked and adjacent Seattle weather bars' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/72-recharts-mixed-bars/recharts.ts b/benchmarks/conformance/cases/72-recharts-mixed-bars/recharts.ts index c85fe0ae..66defc91 100644 --- a/benchmarks/conformance/cases/72-recharts-mixed-bars/recharts.ts +++ b/benchmarks/conformance/cases/72-recharts-mixed-bars/recharts.ts @@ -1,4 +1,4 @@ -import { weather } from '@charts-poc/demo-data/weather' +import { weather } from '@tanstack/charts-data/weather' import { createElement } from 'react' import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from 'recharts' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/73-many-point-scatter/example.tsx b/benchmarks/conformance/cases/73-many-point-scatter/example.tsx index b1150114..2b179e2e 100644 --- a/benchmarks/conformance/cases/73-many-point-scatter/example.tsx +++ b/benchmarks/conformance/cases/73-many-point-scatter/example.tsx @@ -2,59 +2,52 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart, dot } from '@tanstack/charts' -import { cars } from '@charts-poc/demo-data/cars' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' import { scaleLinear, scaleSqrt } from 'd3-scale' import { selectManyPointData } from './selection' const colors = ['#2563eb', '#7c3aed', '#db2777', '#f97316', '#0f766e'] -export const manyPointScatterDefinition = (points: readonly CarsRow[]) => - defineChart({ - marks: [ - dot(points, { - id: 'cars', - x: 'weight (lb)', - y: '0-60 mph (s)', - color: 'cylinders', - key: (row) => JSON.stringify([row.name, row.year, row['weight (lb)']]), - r: 'displacement (cc)', - rScale: { - scale: () => scaleSqrt().range([2.25, 4.5]), - }, - fillOpacity: 0.72, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, - y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, - color: { - range: colors, +export const createExampleChart = (input: ChartOptions) => { + const points: readonly CarsRow[] = selectManyPointData(cars, input.revision) + + return defineChart( + { + marks: [ + dot(points, { + id: 'cars', + x: 'weight (lb)', + y: '0-60 mph (s)', + color: 'cylinders', + key: (row) => + JSON.stringify([row.name, row.year, row['weight (lb)']]), + r: 'displacement (cc)', + rScale: { + scale: () => scaleSqrt().range([2.25, 4.5]), + }, + fillOpacity: 0.72, + }), + ], + x: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, + y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 6 } } }, + color: { + range: colors, + }, + margin: { top: 20, right: 20, bottom: 50, left: 80 }, }, - margin: { top: 20, right: 20, bottom: 50, left: 80 }, - }) - -export const definition = (input: ExampleOptions) => - manyPointScatterDefinition(selectManyPointData(cars, input.revision)) -export interface ExampleOptions { - width: number - height: number + { keyboard: true, tooltip: exampleTooltip }, + ) +} + +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Automobile specifications scatter' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/73-many-point-scatter/recharts.ts b/benchmarks/conformance/cases/73-many-point-scatter/recharts.ts index f663353f..7ff7acb6 100644 --- a/benchmarks/conformance/cases/73-many-point-scatter/recharts.ts +++ b/benchmarks/conformance/cases/73-many-point-scatter/recharts.ts @@ -7,7 +7,7 @@ import { YAxis, ZAxis, } from 'recharts' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { selectManyPointData } from './selection' import { groupCarsByCylinder } from './transform' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/73-many-point-scatter/selection.ts b/benchmarks/conformance/cases/73-many-point-scatter/selection.ts index 443cf5f5..6438af2c 100644 --- a/benchmarks/conformance/cases/73-many-point-scatter/selection.ts +++ b/benchmarks/conformance/cases/73-many-point-scatter/selection.ts @@ -1,4 +1,4 @@ -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' const pointsPerView = 300 diff --git a/benchmarks/conformance/cases/73-many-point-scatter/tanstack.test.ts b/benchmarks/conformance/cases/73-many-point-scatter/tanstack.test.ts index 7d34be41..e693de51 100644 --- a/benchmarks/conformance/cases/73-many-point-scatter/tanstack.test.ts +++ b/benchmarks/conformance/cases/73-many-point-scatter/tanstack.test.ts @@ -1,21 +1,21 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { selectManyPointData } from './selection' -import { manyPointScatterDefinition } from './tanstack' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import { createExampleChart } from './tanstack' +import type { CarsRow } from '@tanstack/charts-data/cars' import type { ChartPoint, ChartSpecDatum } from '@tanstack/charts' -type CarDatum = ChartSpecDatum> +type CarDatum = ChartSpecDatum> describe('many-point scatter identity', () => { it('keeps raw car identity and stable keys across overlapping windows', () => { const firstRows = selectManyPointData(cars, 0) const secondRows = selectManyPointData(cars, 1) - const first = pointKeys(firstRows) - const second = pointKeys(secondRows) + const first = pointKeys(0) + const second = pointKeys(1) const overlap = firstRows.filter((row) => second.has(row)) expectTypeOf().toEqualTypeOf() @@ -30,14 +30,14 @@ describe('many-point scatter identity', () => { } }) - it('keeps each raw row key when the same window is reordered', () => { + it('keeps each raw row key across repeated renders', () => { const rows = selectManyPointData(cars, 0) - const canonical = pointKeys(rows) - const reordered = pointKeys([...rows].reverse()) + const canonical = pointKeys(0) + const repeated = pointKeys(0) - expect(reordered.size).toBe(canonical.size) + expect(repeated.size).toBe(canonical.size) for (const row of rows) { - expect(reordered.get(row)).toBe(canonical.get(row)) + expect(repeated.get(row)).toBe(canonical.get(row)) } }) @@ -59,10 +59,12 @@ describe('many-point scatter identity', () => { }) }) -function pointKeys(rows: readonly CarsRow[]) { +function pointKeys(revision: number) { + const rows = selectManyPointData(cars, revision) + const input = { width: 640, height: 400, revision } const scene = createChartRuntime().render( - manyPointScatterDefinition(rows), - { width: 640, height: 400 }, + createExampleChart(input), + input, ) const points = scene.points.filter( (point): point is ChartPoint => diff --git a/benchmarks/conformance/cases/73-many-point-scatter/transform.ts b/benchmarks/conformance/cases/73-many-point-scatter/transform.ts index 6d4cacc7..1cf0753e 100644 --- a/benchmarks/conformance/cases/73-many-point-scatter/transform.ts +++ b/benchmarks/conformance/cases/73-many-point-scatter/transform.ts @@ -1,4 +1,4 @@ -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' export interface CarSeries { cylinders: number diff --git a/benchmarks/conformance/cases/74-recharts-treemap/example.tsx b/benchmarks/conformance/cases/74-recharts-treemap/example.tsx index 65d083b4..8c5b515f 100644 --- a/benchmarks/conformance/cases/74-recharts-treemap/example.tsx +++ b/benchmarks/conformance/cases/74-recharts-treemap/example.tsx @@ -3,56 +3,47 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { treemap } from '@tanstack/charts/hierarchy/treemap' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { selectTreemapData } from './selection' const colors = ['#2563eb', '#8b5cf6', '#10b981'] const rows = selectTreemapData(flare) -export const treemapDefinition = (input?: ExampleOptions) => - defineChart({ - marks: [ - treemap(rows, { - id: 'treemap-cells', - path: 'name', - delimiter: '.', - value: 'size', - ratio: 4 / 3, - round: true, - color: (node) => node.ancestorIds.at(-1) ?? node.id, - inset: 1, - stroke: '#ffffff', - strokeWidth: 1, - label: input?.preview === true ? undefined : 'name', - labelFill: '#ffffff', - labelFontSize: 8, - labelFontWeight: 600, - }), - ], - color: { range: colors }, - guides: false, - margin: 0, - }) -export interface ExampleOptions { - width: number - height: number - revision: number +export const createExampleChart = (input?: ChartOptions) => + defineChart( + { + marks: [ + treemap(rows, { + id: 'treemap-cells', + path: 'name', + delimiter: '.', + value: 'size', + ratio: 4 / 3, + round: true, + color: (node) => node.ancestorIds.at(-1) ?? node.id, + inset: 1, + stroke: '#ffffff', + strokeWidth: 1, + label: input?.preview === true ? undefined : 'name', + labelFill: '#ffffff', + labelFontSize: 8, + labelFontWeight: 600, + }), + ], + color: { range: colors }, + guides: false, + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'Flare analytics treemap' -export const createExampleChart = (options: ExampleOptions) => - defineChart(treemapDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/74-recharts-treemap/recharts.ts b/benchmarks/conformance/cases/74-recharts-treemap/recharts.ts index 9b6b793c..04699718 100644 --- a/benchmarks/conformance/cases/74-recharts-treemap/recharts.ts +++ b/benchmarks/conformance/cases/74-recharts-treemap/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Treemap } from 'recharts' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { selectTreemapData } from './selection' import { flareLabel, flareTree } from './transform' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/74-recharts-treemap/selection.ts b/benchmarks/conformance/cases/74-recharts-treemap/selection.ts index 0c91cabf..00a56bb2 100644 --- a/benchmarks/conformance/cases/74-recharts-treemap/selection.ts +++ b/benchmarks/conformance/cases/74-recharts-treemap/selection.ts @@ -1,4 +1,4 @@ -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' const subtree = 'flare.analytics' diff --git a/benchmarks/conformance/cases/74-recharts-treemap/tanstack.test.ts b/benchmarks/conformance/cases/74-recharts-treemap/tanstack.test.ts index 75315ff3..2526a430 100644 --- a/benchmarks/conformance/cases/74-recharts-treemap/tanstack.test.ts +++ b/benchmarks/conformance/cases/74-recharts-treemap/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { describe, expect, it } from 'vitest' import { selectTreemapData } from './selection' -import { treemapDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { TreemapNode } from '@tanstack/charts/hierarchy/treemap' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { ChartPoint, ChartScene, @@ -98,7 +98,7 @@ describe('native responsive treemap', () => { }) function render(width: number, height: number) { - return createChartRuntime().render(treemapDefinition(), { width, height }) + return createChartRuntime().render(createExampleChart(), { width, height }) } function pointData(scene: ChartScene): TreemapNode[] { diff --git a/benchmarks/conformance/cases/74-recharts-treemap/transform.ts b/benchmarks/conformance/cases/74-recharts-treemap/transform.ts index db2a6add..d0655e89 100644 --- a/benchmarks/conformance/cases/74-recharts-treemap/transform.ts +++ b/benchmarks/conformance/cases/74-recharts-treemap/transform.ts @@ -1,5 +1,5 @@ import { stratify } from 'd3-hierarchy' -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' import type { HierarchyNode } from 'd3-hierarchy' export interface FlareTreeNode { diff --git a/benchmarks/conformance/cases/75-radar/example.tsx b/benchmarks/conformance/cases/75-radar/example.tsx index 21df3837..9c0339d4 100644 --- a/benchmarks/conformance/cases/75-radar/example.tsx +++ b/benchmarks/conformance/cases/75-radar/example.tsx @@ -9,7 +9,7 @@ import { radialArea, radialGrid, } from '@tanstack/charts/polar' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' import { radarEvents, timedEvents } from './selection' @@ -44,87 +44,83 @@ function angleLabelDy({ angle, y }: PolarGuideLabelContext): number { return y > 0 ? -1.1 : 0 } -export const radarDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const margin = input.width < 480 ? { top: 20, right: 55, bottom: 20, left: 105 } : { top: 20, right: 20, bottom: 20, left: 20 } - return defineChart({ - marks: [ - polar({ - angle: { scale: angleScale, wrap: true }, - radius: { scale: radiusScale }, - inset: 0, - radiusRatio: input.preview === true ? 0.94 : 0.8, - guides: [ - radialGrid({ - values: ringValues, - shape: 'polygon', - labels: input.preview !== true, - labelAngle: Math.PI / 3, - labelRotate: 60, - labelBaseline: 'auto', - labelFontSize: 12, - format: (value) => String(Number(value) * 100), - labelFill: '#cccccc', - stroke: '#cbd5e1', - }), - angleGrid({ - values: radarEvents, - labels: input.preview !== true, - labelOffset: 8, - labelDy: angleLabelDy, - labelFill: '#808080', - labelFontSize: 12, - format: String, - stroke: '#cbd5e1', - }), - ], - marks: [ - radialArea(radarProfile, { - id: 'athlete-profile', - angle: 'event', - radius: 'relativePerformance', - key: 'event', - className: 'ts-chart__radar', - curve: curveLinearClosed, - fill: '#8884d8', - fillOpacity: 0.6, - stroke: '#8884d8', - strokeWidth: 2, - }), - ], - }), - ], - margin: input.preview === true ? 0 : margin, - }) + return defineChart( + { + marks: [ + polar({ + angle: { scale: angleScale, wrap: true }, + radius: { scale: radiusScale }, + inset: 0, + radiusRatio: input.preview === true ? 0.94 : 0.8, + guides: [ + radialGrid({ + values: ringValues, + shape: 'polygon', + labels: input.preview !== true, + labelAngle: Math.PI / 3, + labelRotate: 60, + labelBaseline: 'auto', + labelFontSize: 12, + format: (value) => String(Number(value) * 100), + labelFill: '#cccccc', + stroke: '#cbd5e1', + }), + angleGrid({ + values: radarEvents, + labels: input.preview !== true, + labelOffset: 8, + labelDy: angleLabelDy, + labelFill: '#808080', + labelFontSize: 12, + format: String, + stroke: '#cbd5e1', + }), + ], + marks: [ + radialArea(radarProfile, { + id: 'athlete-profile', + angle: 'event', + radius: 'relativePerformance', + key: 'event', + className: 'ts-chart__radar', + curve: curveLinearClosed, + fill: '#8884d8', + fillOpacity: 0.6, + stroke: '#8884d8', + strokeWidth: 2, + }), + ], + }), + ], + margin: input.preview === true ? 0 : margin, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.Country} · ${datum.event} · ${(datum.relativePerformance * 100).toFixed(1)}%`, + }, + }, + }, + ) } -export interface ExampleOptions { +export interface ChartOptions { width: number - height: number - revision: number preview?: boolean } export const exampleAriaLabel = 'Decathlon radar chart' -export const createExampleChart = (options: ExampleOptions) => - defineChart(radarDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.Country} · ${datum.event} · ${(datum.relativePerformance * 100).toFixed(1)}%`, - }, - }, - }) - export const chart = createExampleChart({ width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/75-radar/recharts.ts b/benchmarks/conformance/cases/75-radar/recharts.ts index 87e6b6a6..ef847e7a 100644 --- a/benchmarks/conformance/cases/75-radar/recharts.ts +++ b/benchmarks/conformance/cases/75-radar/recharts.ts @@ -6,7 +6,7 @@ import { Radar, RadarChart, } from 'recharts' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { selectRadarAthlete } from './selection' import { radarProfile } from './transform' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/75-radar/selection.ts b/benchmarks/conformance/cases/75-radar/selection.ts index 3792220c..0c5b9fd3 100644 --- a/benchmarks/conformance/cases/75-radar/selection.ts +++ b/benchmarks/conformance/cases/75-radar/selection.ts @@ -1,4 +1,4 @@ -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' export const radarEvents = [ '100 Meters', diff --git a/benchmarks/conformance/cases/75-radar/tanstack.test.ts b/benchmarks/conformance/cases/75-radar/tanstack.test.ts index 4a0b8529..7c432d09 100644 --- a/benchmarks/conformance/cases/75-radar/tanstack.test.ts +++ b/benchmarks/conformance/cases/75-radar/tanstack.test.ts @@ -1,14 +1,14 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { describe, expect, it } from 'vitest' import { catalogPreviewDefinition } from '../../shared/preview' import { radarEvents, timedEvents } from './selection' import { foldedDecathlon, normalizedDecathlon, - radarDefinition, + createExampleChart, radarProfile, } from './tanstack' import type { ConformanceInput } from '../../types' @@ -81,7 +81,7 @@ describe('folded radar profile', () => { preview: true, } satisfies ConformanceInput const scene = createChartRuntime().render( - catalogPreviewDefinition(radarDefinition(previewInput)), + catalogPreviewDefinition(createExampleChart(previewInput)), previewInput, ) const nodes = flatten(scene.nodes) @@ -120,7 +120,7 @@ describe('folded radar profile', () => { }) function render() { - return createChartRuntime().render(radarDefinition(input), input) + return createChartRuntime().render(createExampleChart(input), input) } function flatten(nodes: readonly SceneNode[]): SceneNode[] { diff --git a/benchmarks/conformance/cases/75-radar/transform.test.ts b/benchmarks/conformance/cases/75-radar/transform.test.ts index 3fbb4aa4..0ba517ae 100644 --- a/benchmarks/conformance/cases/75-radar/transform.test.ts +++ b/benchmarks/conformance/cases/75-radar/transform.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { selectRadarAthlete } from './selection' import { radarProfile } from './transform' diff --git a/benchmarks/conformance/cases/75-radar/transform.ts b/benchmarks/conformance/cases/75-radar/transform.ts index ebcd1a68..e637c87f 100644 --- a/benchmarks/conformance/cases/75-radar/transform.ts +++ b/benchmarks/conformance/cases/75-radar/transform.ts @@ -1,5 +1,5 @@ import { extent } from 'd3-array' -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' import { radarEvents, timedEvents } from './selection' import type { RadarEvent } from './selection' diff --git a/benchmarks/conformance/cases/76-pie/example.tsx b/benchmarks/conformance/cases/76-pie/example.tsx index 23f91cb2..c215870b 100644 --- a/benchmarks/conformance/cases/76-pie/example.tsx +++ b/benchmarks/conformance/cases/76-pie/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectPieData } from './selection' const colors = ['#2563eb', '#7c3aed', '#db2777', '#f59e0b'] @@ -12,55 +12,49 @@ const percentage = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2, }) -export const pieDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const arcs = pie(selectPieData(alphabet, input.revision), { value: 'frequency', }) - return defineChart({ - marks: [ - polar({ - inset: 0, - radiusRatio: 0.8, - marks: [ - radialArc(arcs, { - id: 'letter-slices', - key: 'letter', - color: 'letter', - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + inset: 0, + radiusRatio: 0.8, + marks: [ + radialArc(arcs, { + id: 'letter-slices', + key: 'letter', + color: 'letter', + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.letter} · ${percentage.format(datum.frequency)}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'English letter frequency pie' -export const createExampleChart = (options: ExampleOptions) => - defineChart(pieDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.letter} · ${percentage.format(datum.frequency)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/76-pie/recharts.ts b/benchmarks/conformance/cases/76-pie/recharts.ts index 6a9012c9..f3148fb2 100644 --- a/benchmarks/conformance/cases/76-pie/recharts.ts +++ b/benchmarks/conformance/cases/76-pie/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectPieData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/76-pie/selection.ts b/benchmarks/conformance/cases/76-pie/selection.ts index 7cfeddc7..a47eb71d 100644 --- a/benchmarks/conformance/cases/76-pie/selection.ts +++ b/benchmarks/conformance/cases/76-pie/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 4 diff --git a/benchmarks/conformance/cases/76-pie/tanstack.test.ts b/benchmarks/conformance/cases/76-pie/tanstack.test.ts index 8925bd9c..f696a708 100644 --- a/benchmarks/conformance/cases/76-pie/tanstack.test.ts +++ b/benchmarks/conformance/cases/76-pie/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { selectPieData } from './selection' -import { pieDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { PieDatum } from '@tanstack/charts/polar' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -74,7 +74,7 @@ describe('native pie allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(pieDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function piePoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/77-donut/example.tsx b/benchmarks/conformance/cases/77-donut/example.tsx index efbc6965..ee35345d 100644 --- a/benchmarks/conformance/cases/77-donut/example.tsx +++ b/benchmarks/conformance/cases/77-donut/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectDonutData } from './selection' const colors = ['#0ea5e9', '#6366f1', '#a855f7', '#ec4899', '#f97316'] @@ -12,56 +12,50 @@ const percentage = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2, }) -export const donutDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const arcs = pie(selectDonutData(alphabet, input.revision), { value: 'frequency', }) - return defineChart({ - marks: [ - polar({ - inset: 0, - radiusRatio: 0.8, - marks: [ - radialArc(arcs, { - id: 'letter-slices', - key: 'letter', - innerRadius: ({ radius }) => radius * 0.58, - color: 'letter', - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + inset: 0, + radiusRatio: 0.8, + marks: [ + radialArc(arcs, { + id: 'letter-slices', + key: 'letter', + innerRadius: ({ radius }) => radius * 0.58, + color: 'letter', + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.letter} · ${percentage.format(datum.frequency)}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'English letter frequency donut' -export const createExampleChart = (options: ExampleOptions) => - defineChart(donutDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.letter} · ${percentage.format(datum.frequency)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/77-donut/recharts.ts b/benchmarks/conformance/cases/77-donut/recharts.ts index d13ccc9d..f4c1da15 100644 --- a/benchmarks/conformance/cases/77-donut/recharts.ts +++ b/benchmarks/conformance/cases/77-donut/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectDonutData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/77-donut/selection.ts b/benchmarks/conformance/cases/77-donut/selection.ts index 9491ed46..d2a420eb 100644 --- a/benchmarks/conformance/cases/77-donut/selection.ts +++ b/benchmarks/conformance/cases/77-donut/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 5 diff --git a/benchmarks/conformance/cases/77-donut/tanstack.test.ts b/benchmarks/conformance/cases/77-donut/tanstack.test.ts index 2eb61d1c..a6bb82a7 100644 --- a/benchmarks/conformance/cases/77-donut/tanstack.test.ts +++ b/benchmarks/conformance/cases/77-donut/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { selectDonutData } from './selection' -import { donutDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { PieDatum } from '@tanstack/charts/polar' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -83,7 +83,7 @@ describe('native donut allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(donutDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function donutPoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/78-gauge/example.tsx b/benchmarks/conformance/cases/78-gauge/example.tsx index f87354a7..5ee22a08 100644 --- a/benchmarks/conformance/cases/78-gauge/example.tsx +++ b/benchmarks/conformance/cases/78-gauge/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc } from '@tanstack/charts/polar' import { agreementPercent, gaugeSegments } from './transform' @@ -12,7 +12,7 @@ const endAngle = (Math.PI * 3) / 4 const ids: readonly GaugeDatum['id'][] = ['value', 'remainder'] const colors = ['#ef4444', '#e2e8f0'] -export const gaugeDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const question = `Q${(input.revision % 2) + 1}` const agreement = agreementPercent(survey, question) const segments = gaugeSegments(agreement) @@ -22,50 +22,44 @@ export const gaugeDefinition = (input: ExampleOptions) => { endAngle, }) - return defineChart({ - marks: [ - polar({ - inset: 0, - radiusRatio: 0.8, - marks: [ - radialArc(arcs, { - id: 'gauge-segments', - key: 'id', - innerRadius: ({ radius }) => radius * 0.72, - color: 'id', - }), - ], - }), - ], - color: { domain: ids, range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + inset: 0, + radiusRatio: 0.8, + marks: [ + radialArc(arcs, { + id: 'gauge-segments', + key: 'id', + innerRadius: ({ radius }) => radius * 0.72, + color: 'id', + }), + ], + }), + ], + color: { domain: ids, range: colors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => `${datum.label} · ${datum.value}%`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Survey agreement share gauge' -export const createExampleChart = (options: ExampleOptions) => - defineChart(gaugeDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => `${datum.label} · ${datum.value}%`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/78-gauge/recharts.ts b/benchmarks/conformance/cases/78-gauge/recharts.ts index 088a6b88..0a5c4eea 100644 --- a/benchmarks/conformance/cases/78-gauge/recharts.ts +++ b/benchmarks/conformance/cases/78-gauge/recharts.ts @@ -1,4 +1,4 @@ -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' import { agreementPercent, gaugeSegments } from './transform' diff --git a/benchmarks/conformance/cases/78-gauge/tanstack.test.ts b/benchmarks/conformance/cases/78-gauge/tanstack.test.ts index 5e0f8246..cf5d01d6 100644 --- a/benchmarks/conformance/cases/78-gauge/tanstack.test.ts +++ b/benchmarks/conformance/cases/78-gauge/tanstack.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { agreementPercent } from './transform' -import { gaugeDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { PieDatum } from '@tanstack/charts/polar' import type { GaugeDatum } from './transform' @@ -102,7 +102,7 @@ describe('native gauge allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(gaugeDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function gaugePoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/78-gauge/transform.test.ts b/benchmarks/conformance/cases/78-gauge/transform.test.ts index 821ce948..7cf0918c 100644 --- a/benchmarks/conformance/cases/78-gauge/transform.test.ts +++ b/benchmarks/conformance/cases/78-gauge/transform.test.ts @@ -1,4 +1,4 @@ -import { survey } from '@charts-poc/demo-data/survey' +import { survey } from '@tanstack/charts-data/survey' import { describe, expect, it } from 'vitest' import { agreementPercent, gaugeSegments } from './transform' diff --git a/benchmarks/conformance/cases/78-gauge/transform.ts b/benchmarks/conformance/cases/78-gauge/transform.ts index 77ac1cdd..322e2743 100644 --- a/benchmarks/conformance/cases/78-gauge/transform.ts +++ b/benchmarks/conformance/cases/78-gauge/transform.ts @@ -27,4 +27,4 @@ export function agreementPercent( ? 0 : Math.round((agreements.length / responses.length) * 100) } -import type { SurveyRow } from '@charts-poc/demo-data/survey' +import type { SurveyRow } from '@tanstack/charts-data/survey' diff --git a/benchmarks/conformance/cases/80-echarts-axis-pointer/echarts.ts b/benchmarks/conformance/cases/80-echarts-axis-pointer/echarts.ts index 1826ffca..d75ebc77 100644 --- a/benchmarks/conformance/cases/80-echarts-axis-pointer/echarts.ts +++ b/benchmarks/conformance/cases/80-echarts-axis-pointer/echarts.ts @@ -15,7 +15,7 @@ import type { TooltipComponentOption, } from 'echarts/components' import type { ComposeOption, EChartsType } from 'echarts/core' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { clientPointBounds } from '../../shared/driver-geometry' import { echartsMount } from '../../shared/echarts-mount' import { axisPointerColors } from './colors' diff --git a/benchmarks/conformance/cases/80-echarts-axis-pointer/example.tsx b/benchmarks/conformance/cases/80-echarts-axis-pointer/example.tsx index c5af0005..1e5ea8ba 100644 --- a/benchmarks/conformance/cases/80-echarts-axis-pointer/example.tsx +++ b/benchmarks/conformance/cases/80-echarts-axis-pointer/example.tsx @@ -1,5 +1,5 @@ import { Chart } from '@tanstack/charts/react/tooltip' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { colorLegend, defineChart, dot, lineY } from '@tanstack/charts' import { focusGuideX } from '@tanstack/charts/focus/guide' import { tooltip } from '@tanstack/charts/tooltip' @@ -9,14 +9,7 @@ import { axisPointerDateKey } from './model' import { axisPointerData, axisPointerIndustries } from './selection' import type { ChartTooltipOptions } from '@tanstack/charts' import type { AxisPointerDatum } from './selection' -export interface ExampleOptions { - width: number - height: number - revision: number - preview?: boolean -} -export const createExampleChart = axisPointerDefinition export const exampleAriaLabel = 'Snapped axis pointer with grouped tooltip' const month = new Intl.DateTimeFormat('en-US', { @@ -51,77 +44,83 @@ const axisPointerTooltip: ChartTooltipOptions = { ], } -export function axisPointerDefinition(input: ExampleChartInput) { +export function createExampleChart(input: ExampleChartInput) { const rows = axisPointerData(industries, input.revision) - return defineChart({ - marks: [ - lineY(rows, { - id: 'industry-lines', - x: 'date', - y: 'unemployed', - z: 'industry', - color: 'industry', - key: axisPointerKey, - strokeWidth: 2, - }), - dot(rows, { - id: 'industry-points', - x: 'date', - y: 'unemployed', - z: 'industry', - color: 'industry', - key: axisPointerKey, - r: 3, - stroke: '#ffffff', - strokeWidth: 1, - }), - focusGuideX(rows, { - id: 'axis-pointer-guide', - x: 'date', - y: 'unemployed', - z: 'industry', - key: axisPointerKey, - xRule: { - stroke: '#64748b', + return defineChart( + { + marks: [ + lineY(rows, { + id: 'industry-lines', + x: 'date', + y: 'unemployed', + z: 'industry', + color: 'industry', + key: axisPointerKey, + strokeWidth: 2, + }), + dot(rows, { + id: 'industry-points', + x: 'date', + y: 'unemployed', + z: 'industry', + color: 'industry', + key: axisPointerKey, + r: 3, + stroke: '#ffffff', strokeWidth: 1, - strokeDasharray: '4 4', + }), + focusGuideX(rows, { + id: 'axis-pointer-guide', + x: 'date', + y: 'unemployed', + z: 'industry', + key: axisPointerKey, + xRule: { + stroke: '#64748b', + strokeWidth: 1, + strokeDasharray: '4 4', + }, + }), + ], + x: { + scale: scaleUtc, + axis: { ticks: { format: (value) => month.format(value) } }, + }, + y: { + scale: scaleLinear, + grid: input.preview !== true, + axis: { + ticks: { count: 5 }, + ...(input.preview === true + ? {} + : { label: 'Unemployed (thousands)' }), }, - }), - ], - x: { - scale: scaleUtc, - axis: { ticks: { format: (value) => month.format(value) } }, - }, - y: { - scale: scaleLinear, - grid: input.preview !== true, - axis: { - ticks: { count: 5 }, - ...(input.preview === true ? {} : { label: 'Unemployed (thousands)' }), }, + color: { + domain: axisPointerIndustries, + range: axisPointerIndustries.map( + (industry) => axisPointerColors[industry], + ), + legend: colorLegend({ itemWidth: 100 }), + }, + focus: 'group-x', + focusRing: false, + maxFocusDistance: Number.POSITIVE_INFINITY, + svgAnimation: false, + margin: + input.preview === true + ? { top: 4, right: 4, bottom: 22, left: 38 } + : { top: 38, right: 24, bottom: 45, left: 60 }, }, - color: { - domain: axisPointerIndustries, - range: axisPointerIndustries.map( - (industry) => axisPointerColors[industry], - ), - legend: colorLegend({ itemWidth: 100 }), - }, - focus: 'group-x', - focusRing: false, - maxFocusDistance: Number.POSITIVE_INFINITY, - svgAnimation: false, - keyboard: true, - tooltip: { - use: tooltip, - ...axisPointerTooltip, + { + keyboard: true, + tooltip: { + use: tooltip, + ...axisPointerTooltip, + }, }, - margin: - input.preview === true - ? { top: 4, right: 4, bottom: 22, left: 38 } - : { top: 38, right: 24, bottom: 45, left: 60 }, - }) + ) } function axisPointerKey(row: AxisPointerDatum) { @@ -140,6 +139,7 @@ export const chart = createExampleChart({ width: 640, height: 480, revision: 0, + preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/80-echarts-axis-pointer/selection.ts b/benchmarks/conformance/cases/80-echarts-axis-pointer/selection.ts index ec734938..abcf1f0a 100644 --- a/benchmarks/conformance/cases/80-echarts-axis-pointer/selection.ts +++ b/benchmarks/conformance/cases/80-echarts-axis-pointer/selection.ts @@ -1,4 +1,4 @@ -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' export const axisPointerIndustries = [ 'Manufacturing', diff --git a/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.test.ts b/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.test.ts index bc33e65e..bdac3c3d 100644 --- a/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.test.ts +++ b/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.test.ts @@ -1,10 +1,10 @@ import { existsSync, readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { createChartScene, resolveFocusScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it, vi } from 'vitest' import { axisPointerData, axisPointerIndustries } from './selection' -import { axisPointerDefinition, catalogCase, mount } from './tanstack' +import { createExampleChart, catalogCase, mount } from './tanstack' import type { ChartDefinition, ChartFocusState, @@ -28,7 +28,7 @@ describe('definition-owned snapped axis pointer', () => { it.each([0, 1])( 'keeps raw observations and guide candidates typed for revision %s', (revision) => { - const definition = axisPointerDefinition({ ...input, revision }) + const definition = createExampleChart({ ...input, revision }) const rows = axisPointerData(industries, revision) const scene = createChartScene(definition, { width: input.width, @@ -75,10 +75,10 @@ describe('definition-owned snapped axis pointer', () => { it.each([320, 640, 960])( 'retargets one full-height dashed rule with stable structure at %spx', (width) => { - const scene = createChartScene( - axisPointerDefinition({ ...input, width }), - { width, height: input.height }, - ) + const scene = createChartScene(createExampleChart({ ...input, width }), { + width, + height: input.height, + }) const april = resolveAtDate(scene, '2005-04-01') const august = resolveAtDate(scene, '2005-08-01') const aprilLayer = focusLayer(april) diff --git a/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.ts b/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.ts index b663d013..1f718cb3 100644 --- a/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.ts +++ b/benchmarks/conformance/cases/80-echarts-axis-pointer/tanstack.ts @@ -1,6 +1,6 @@ -import { axisPointerDefinition } from './example' -export { axisPointerDefinition } from './example' -import { industries } from '@charts-poc/demo-data/industries' +import { createExampleChart } from './example' +export { createExampleChart } from './example' +import { industries } from '@tanstack/charts-data/industries' import { mountChart } from '@tanstack/charts' import { tooltip } from '@tanstack/charts/tooltip' import { @@ -67,7 +67,7 @@ const axisPointerTooltip: ChartTooltipOptions = { } export const catalogCase = tanstackCase( - axisPointerDefinition, + createExampleChart, 'Snapped axis pointer with grouped tooltip', axisPointerTooltip, { @@ -90,7 +90,7 @@ export const mount: ConformanceMount = (container, input) => { let currentInput = input let focusedPoints: readonly ChartPoint[] = [] const options = (): ChartHostOptions => ({ - definition: axisPointerDefinition(currentInput), + definition: createExampleChart(currentInput), width: currentInput.width, height: currentInput.height, ariaLabel: 'Snapped axis pointer with grouped tooltip', diff --git a/benchmarks/conformance/cases/81-recharts-interactive-legend/example.tsx b/benchmarks/conformance/cases/81-recharts-interactive-legend/example.tsx index 4c5df12b..53ad27ad 100644 --- a/benchmarks/conformance/cases/81-recharts-interactive-legend/example.tsx +++ b/benchmarks/conformance/cases/81-recharts-interactive-legend/example.tsx @@ -3,7 +3,7 @@ import { colorLegend, defineChart, lineY } from '@tanstack/charts' import { controlledSignal } from '@tanstack/charts/interaction/signal' import { interactiveColorLegend } from '@tanstack/charts/legend' import { Chart } from '@tanstack/charts/react' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { scaleLinear, scaleUtc } from 'd3-scale' import { legendRows, legendSeries } from './model' import type { LegendSeriesId } from './model' @@ -31,7 +31,7 @@ export function interactiveLegendDefinition( ) { const rows = legendRows(industries, revision) return defineChart( - defineChart({ + { marks: [ lineY(rows, { id: 'industry-lines', @@ -68,7 +68,7 @@ export function interactiveLegendDefinition( }), }, margin: { top: 20, right: 24, left: 62 }, - }), + }, { keyboard: true }, ) } diff --git a/benchmarks/conformance/cases/81-recharts-interactive-legend/model.ts b/benchmarks/conformance/cases/81-recharts-interactive-legend/model.ts index 8c46a62b..0452a5c9 100644 --- a/benchmarks/conformance/cases/81-recharts-interactive-legend/model.ts +++ b/benchmarks/conformance/cases/81-recharts-interactive-legend/model.ts @@ -1,4 +1,4 @@ -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' export const legendSeries = [ { id: 'Manufacturing', label: 'Manufacturing' }, diff --git a/benchmarks/conformance/cases/81-recharts-interactive-legend/recharts.ts b/benchmarks/conformance/cases/81-recharts-interactive-legend/recharts.ts index d50fbc26..f2b8062a 100644 --- a/benchmarks/conformance/cases/81-recharts-interactive-legend/recharts.ts +++ b/benchmarks/conformance/cases/81-recharts-interactive-legend/recharts.ts @@ -2,7 +2,7 @@ import { createElement, useState } from 'react' import { flushSync } from 'react-dom' import { createRoot } from 'react-dom/client' import { CartesianGrid, Line, LineChart, XAxis, YAxis } from 'recharts' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { isLegendSeriesId, legendRows, diff --git a/benchmarks/conformance/cases/81-recharts-interactive-legend/tanstack.test.ts b/benchmarks/conformance/cases/81-recharts-interactive-legend/tanstack.test.ts index 787e19be..9646918d 100644 --- a/benchmarks/conformance/cases/81-recharts-interactive-legend/tanstack.test.ts +++ b/benchmarks/conformance/cases/81-recharts-interactive-legend/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { industries } from '@charts-poc/demo-data/industries' +import { industries } from '@tanstack/charts-data/industries' import { createChartScene } from '@tanstack/charts' import { act } from 'react' import { describe, expect, expectTypeOf, it } from 'vitest' import { legendRows, legendSeries } from './model' import { interactiveLegendDefinition, mount } from './tanstack' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import type { ChartDefinition, ChartSpecDatum } from '@tanstack/charts' import type { LegendSeriesId } from './model' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/82-chart-table-selection/example.tsx b/benchmarks/conformance/cases/82-chart-table-selection/example.tsx index aee670f4..0f85ce1a 100644 --- a/benchmarks/conformance/cases/82-chart-table-selection/example.tsx +++ b/benchmarks/conformance/cases/82-chart-table-selection/example.tsx @@ -3,7 +3,7 @@ import { defineChart, dot } from '@tanstack/charts' import { controlledSignal } from '@tanstack/charts/interaction/signal' import { keyedSelection, whenSelected } from '@tanstack/charts/selection' import { Chart } from '@tanstack/charts/react' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { scaleLinear } from 'd3-scale' import { penguinSelectionId, diff --git a/benchmarks/conformance/cases/82-chart-table-selection/model.ts b/benchmarks/conformance/cases/82-chart-table-selection/model.ts index 98ae2d95..d4864b3c 100644 --- a/benchmarks/conformance/cases/82-chart-table-selection/model.ts +++ b/benchmarks/conformance/cases/82-chart-table-selection/model.ts @@ -1,4 +1,4 @@ -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export type CompletePenguin = PenguinsRow & { readonly culmen_length_mm: number diff --git a/benchmarks/conformance/cases/82-chart-table-selection/recharts.ts b/benchmarks/conformance/cases/82-chart-table-selection/recharts.ts index c7f7cf48..e79d52ab 100644 --- a/benchmarks/conformance/cases/82-chart-table-selection/recharts.ts +++ b/benchmarks/conformance/cases/82-chart-table-selection/recharts.ts @@ -2,7 +2,7 @@ import { createElement, useState } from 'react' import { flushSync } from 'react-dom' import { createRoot } from 'react-dom/client' import { CartesianGrid, Scatter, ScatterChart, XAxis, YAxis } from 'recharts' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { isSelectionId, penguinSelectionId, diff --git a/benchmarks/conformance/cases/82-chart-table-selection/tanstack.test.ts b/benchmarks/conformance/cases/82-chart-table-selection/tanstack.test.ts index 9efb781e..4075fa28 100644 --- a/benchmarks/conformance/cases/82-chart-table-selection/tanstack.test.ts +++ b/benchmarks/conformance/cases/82-chart-table-selection/tanstack.test.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { diff --git a/benchmarks/conformance/cases/82-chart-table-selection/view.tsx b/benchmarks/conformance/cases/82-chart-table-selection/view.tsx index 608c5f4c..acae19c9 100644 --- a/benchmarks/conformance/cases/82-chart-table-selection/view.tsx +++ b/benchmarks/conformance/cases/82-chart-table-selection/view.tsx @@ -7,7 +7,7 @@ import { useState, } from 'react' import { Chart } from '@tanstack/charts/react' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { catalogPreviewDefinition } from '../../shared/preview' import { reactMount } from '../../shared/react-mount' import { diff --git a/benchmarks/conformance/cases/83-focus-context-window/example.tsx b/benchmarks/conformance/cases/83-focus-context-window/example.tsx index a89971ec..1f00f3ad 100644 --- a/benchmarks/conformance/cases/83-focus-context-window/example.tsx +++ b/benchmarks/conformance/cases/83-focus-context-window/example.tsx @@ -4,7 +4,7 @@ import { brushX } from '@tanstack/charts/interaction/brush' import { controlledSignal } from '@tanstack/charts/interaction/signal' import { keyedSelection, whenSelected } from '@tanstack/charts/selection' import { Chart } from '@tanstack/charts/react' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { scaleLinear, scaleUtc } from 'd3-scale' import { dateKey, @@ -20,7 +20,7 @@ import type { BrushXChange, } from '@tanstack/charts/interaction/brush' import type { KeyedSelectionChange } from '@tanstack/charts/selection' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { FocusContextWindow } from './model' interface BrushStatus { @@ -50,7 +50,7 @@ export function focusContextDetailDefinition(window: FocusContextWindow) { key: (row) => dateKey(row.Date), }) return defineChart( - defineChart({ + { marks: [ lineY(rows, { id: 'detail-line', @@ -89,7 +89,7 @@ export function focusContextDetailDefinition(window: FocusContextWindow) { axis: { label: 'Close ($)' }, }, margin: detailMargin, - }), + }, { svgAnimation: false, keyboard: false }, ) } @@ -99,7 +99,7 @@ export function focusContextOverviewDefinition( onChange: (range: BrushRange, reason: BrushXChange) => void, ) { return defineChart( - defineChart({ + { marks: [ lineY(focusContextRows, { id: 'overview-line', @@ -146,7 +146,7 @@ export function focusContextOverviewDefinition( handleStyle: { fill: '#2563eb', fillOpacity: 0.9 }, }), ], - }), + }, { svgAnimation: false, keyboard: false }, ) } diff --git a/benchmarks/conformance/cases/83-focus-context-window/model.ts b/benchmarks/conformance/cases/83-focus-context-window/model.ts index f0412cb9..974c4616 100644 --- a/benchmarks/conformance/cases/83-focus-context-window/model.ts +++ b/benchmarks/conformance/cases/83-focus-context-window/model.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export interface FocusContextWindow { selected: Date diff --git a/benchmarks/conformance/cases/83-focus-context-window/plot.ts b/benchmarks/conformance/cases/83-focus-context-window/plot.ts index 78474614..46b4ff8c 100644 --- a/benchmarks/conformance/cases/83-focus-context-window/plot.ts +++ b/benchmarks/conformance/cases/83-focus-context-window/plot.ts @@ -1,5 +1,5 @@ import * as Plot from '@observablehq/plot' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { brushX } from 'd3-brush' import { select } from 'd3-selection' import { diff --git a/benchmarks/conformance/cases/83-focus-context-window/tanstack.test.ts b/benchmarks/conformance/cases/83-focus-context-window/tanstack.test.ts index d5fa753b..671f9a3f 100644 --- a/benchmarks/conformance/cases/83-focus-context-window/tanstack.test.ts +++ b/benchmarks/conformance/cases/83-focus-context-window/tanstack.test.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { createChartScene } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { @@ -13,7 +13,7 @@ import { monthlyAaplRows, rowsInWindow, } from './model' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartDefinition, ChartSpecDatum, diff --git a/benchmarks/conformance/cases/83-focus-context-window/view.tsx b/benchmarks/conformance/cases/83-focus-context-window/view.tsx index ab135231..d125bd32 100644 --- a/benchmarks/conformance/cases/83-focus-context-window/view.tsx +++ b/benchmarks/conformance/cases/83-focus-context-window/view.tsx @@ -11,7 +11,7 @@ import { useState, } from 'react' import { Chart } from '@tanstack/charts/react' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { catalogPreviewDefinition } from '../../shared/preview' import { reactMount } from '../../shared/react-mount' import { @@ -27,7 +27,7 @@ import type { BrushRange, BrushXChange, } from '@tanstack/charts/interaction/brush' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { FocusContextWindow } from './model' import type { ConformanceTarget, ConformanceTestDriver } from '../../types' import type { ReactConformanceProps } from '../../shared/react-mount' diff --git a/benchmarks/conformance/cases/84-pinned-nested-chart-tooltip/example.tsx b/benchmarks/conformance/cases/84-pinned-nested-chart-tooltip/example.tsx index 8961b6a3..0634b1bf 100644 --- a/benchmarks/conformance/cases/84-pinned-nested-chart-tooltip/example.tsx +++ b/benchmarks/conformance/cases/84-pinned-nested-chart-tooltip/example.tsx @@ -39,7 +39,7 @@ export function energyDefinition( ? ('right' as const) : (['right', 'left', 'top', 'bottom'] as const) return defineChart( - defineChart({ + { marks: [ areaY(rows, { id: 'consumption-area', @@ -181,7 +181,7 @@ export function energyDefinition( stops: exportedHatchStops, }, ], - }), + }, { svgAnimation: false, keyboard: true, @@ -211,7 +211,7 @@ export function ConsumptionMixChart({ const definition = useMemo(() => { const parts = consumptionBreakdown(month) return defineChart( - defineChart({ + { marks: [ barX(parts, { id: 'consumption-breakdown', @@ -231,7 +231,7 @@ export function ConsumptionMixChart({ axis: false, }, margin: 0, - }), + }, { svgAnimation: false, keyboard: false, tooltip: false }, ) }, [month]) diff --git a/benchmarks/conformance/cases/85-scrollable-resource-lanes/example.tsx b/benchmarks/conformance/cases/85-scrollable-resource-lanes/example.tsx index d49810da..1af2d999 100644 --- a/benchmarks/conformance/cases/85-scrollable-resource-lanes/example.tsx +++ b/benchmarks/conformance/cases/85-scrollable-resource-lanes/example.tsx @@ -76,7 +76,7 @@ export const resourceTimelineDefinition = (input: ExampleChartInput) => { const rows = resourceTasks(input.revision) return defineChart( - defineChart(({ width }) => { + ({ width }) => { return { marks: [ rect(rows, { @@ -110,7 +110,7 @@ export const resourceTimelineDefinition = (input: ExampleChartInput) => { }, margin: timelineMargin, } - }), + }, { svgAnimation: false, keyboard: true, diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/data.test.ts b/benchmarks/conformance/cases/86-streaming-window-preservation/data.test.ts index 70116f95..2f5c696f 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/data.test.ts +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/data.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { downloads } from '@charts-poc/demo-data/downloads' +import { downloads } from '@tanstack/charts-data/downloads' import { streamingStatus, streamingViewportForMode, diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/echarts.ts b/benchmarks/conformance/cases/86-streaming-window-preservation/echarts.ts index 43b39b13..8ebbb5e9 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/echarts.ts +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/echarts.ts @@ -8,7 +8,7 @@ import type { GridComponentOption, } from 'echarts/components' import type { ComposeOption, EChartsType } from 'echarts/core' -import { downloads } from '@charts-poc/demo-data/downloads' +import { downloads } from '@tanstack/charts-data/downloads' import { clientPointBounds } from '../../shared/driver-geometry' import { echartsMount } from '../../shared/echarts-mount' import { streamingData } from './selection' @@ -21,7 +21,7 @@ import { visibleStreamingData, } from './model' import { createStreamingControls, updateStreamingControls } from './controls' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' import type { StreamingControls } from './controls' import type { StreamingViewportMode } from './model' import type { diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/example.tsx b/benchmarks/conformance/cases/86-streaming-window-preservation/example.tsx index 45823252..526025d6 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/example.tsx +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/example.tsx @@ -3,7 +3,7 @@ import { defineChart, dot, lineY } from '@tanstack/charts' import { decorative } from '@tanstack/charts/mark/decorative' import { tooltip } from '@tanstack/charts/tooltip' import { Chart } from '@tanstack/charts/react' -import { downloads } from '@charts-poc/demo-data/downloads' +import { downloads } from '@tanstack/charts-data/downloads' import { scaleLinear, scaleUtc } from 'd3-scale' import { streamingData } from './selection' import { @@ -14,7 +14,7 @@ import { visibleStreamingData, } from './model' import type { ChartScene } from '@tanstack/charts' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' import type { StreamingViewportMode } from './model' const color = '#2563eb' diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/model.ts b/benchmarks/conformance/cases/86-streaming-window-preservation/model.ts index 1cf0663d..a7eee862 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/model.ts +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/model.ts @@ -1,4 +1,4 @@ -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' export type StreamingViewportMode = 'locked' | 'latest' | 'all' diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/selection.ts b/benchmarks/conformance/cases/86-streaming-window-preservation/selection.ts index eba9b869..398c28aa 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/selection.ts +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/selection.ts @@ -1,4 +1,4 @@ -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' const streamingStart = Date.parse('2018-10-01T00:00:00.000Z') const streamingEnd = Date.parse('2018-10-31T00:00:00.000Z') diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/tanstack.test.ts b/benchmarks/conformance/cases/86-streaming-window-preservation/tanstack.test.ts index ae3932c4..75b499e3 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/tanstack.test.ts +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/tanstack.test.ts @@ -1,13 +1,13 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { downloads } from '@charts-poc/demo-data/downloads' +import { downloads } from '@tanstack/charts-data/downloads' import { createChartScene, mountChart } from '@tanstack/charts' import { describe, expect, expectTypeOf, it } from 'vitest' import { streamingViewportForMode, visibleStreamingData } from './model' import { streamingData } from './selection' import { streamingWindowDefinition } from './tanstack' import type { ChartDefinition, ChartPoint, SceneNode } from '@tanstack/charts' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' const size = { width: 640, height: 360 } diff --git a/benchmarks/conformance/cases/86-streaming-window-preservation/view.tsx b/benchmarks/conformance/cases/86-streaming-window-preservation/view.tsx index b66f1beb..903dfcf0 100644 --- a/benchmarks/conformance/cases/86-streaming-window-preservation/view.tsx +++ b/benchmarks/conformance/cases/86-streaming-window-preservation/view.tsx @@ -8,7 +8,7 @@ import { useState, } from 'react' import { Chart } from '@tanstack/charts/react' -import { downloads } from '@charts-poc/demo-data/downloads' +import { downloads } from '@tanstack/charts-data/downloads' import { catalogPreviewDefinition } from '../../shared/preview' import { clientPointBounds } from '../../shared/driver-geometry' import { reactMount } from '../../shared/react-mount' @@ -22,7 +22,7 @@ import { visibleStreamingData, } from './model' import type { ChartScene } from '@tanstack/charts' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' import type { StreamingViewportMode } from './model' import type { ConformanceGeometryQuery, diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/data.test.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/data.test.ts index 16497aa3..428a7538 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/data.test.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/data.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { selectSynchronizedCursorData } from './selection' describe('synchronized traveler cursors', () => { diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/echarts.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/echarts.ts index c152b3d7..b5f5ef39 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/echarts.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/echarts.ts @@ -15,7 +15,7 @@ import type { TooltipComponentOption, } from 'echarts/components' import type { ComposeOption, EChartsType } from 'echarts/core' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { echartsMount } from '../../shared/echarts-mount' import { selectSynchronizedCursorData, diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/example.tsx b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/example.tsx index 67132a00..fe7e1833 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/example.tsx +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/example.tsx @@ -1,5 +1,5 @@ import { useMemo, useRef, useState } from 'react' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { Chart } from '@tanstack/charts/react' import { synchronizedCursorColors } from './colors' import { @@ -9,7 +9,7 @@ import { import { selectSynchronizedCursorData } from './selection' import type { ChartScene } from '@tanstack/charts' import type { ChartInteractionController } from '@tanstack/charts' -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' import { defineChart, dot, lineY } from '@tanstack/charts' import { focusGuideX } from '@tanstack/charts/focus/guide' import { decorative } from '@tanstack/charts/mark/decorative' diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/model.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/model.ts index 173c22c0..ea17e9eb 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/model.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/model.ts @@ -1,4 +1,4 @@ -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' export type SynchronizedCursorView = 'current' | 'previous' diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/selection.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/selection.ts index b92680db..4332f911 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/selection.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/selection.ts @@ -1,4 +1,4 @@ -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' export function selectSynchronizedCursorData( rows: readonly TravelersRow[], diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/summary.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/summary.ts index 7c5235a0..aece26d7 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/summary.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/summary.ts @@ -2,7 +2,7 @@ import { synchronizedCursorDateKey, synchronizedCursorDatumAtDate, } from './model' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { selectSynchronizedCursorData } from './selection' import { synchronizedCursorColors } from './colors' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.test.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.test.ts index 535689db..e738e069 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.test.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.test.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { createChartScene, resolveFocusScene } from '@tanstack/charts' import { act } from 'react' import { describe, expect, expectTypeOf, it } from 'vitest' @@ -16,7 +16,7 @@ import type { SceneNode, SceneRule, } from '@tanstack/charts' -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' import type { ConformanceInput } from '../../types' const input = { diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.ts b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.ts index 33bfba52..c77c614e 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.ts +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/tanstack.ts @@ -4,7 +4,7 @@ export { synchronizedCursorDefinition, chartHeight, } from './example' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { clientPointBounds, scenePointToClient, @@ -24,7 +24,7 @@ import type { SceneGroup, SceneNode, } from '@tanstack/charts' -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' import type { SynchronizedCursorView } from './model' import type { ConformanceGeometryQuery, diff --git a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/view.tsx b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/view.tsx index fa0813e6..9b19e809 100644 --- a/benchmarks/conformance/cases/87-echarts-synchronized-cursors/view.tsx +++ b/benchmarks/conformance/cases/87-echarts-synchronized-cursors/view.tsx @@ -5,7 +5,7 @@ import { useRef, useState, } from 'react' -import { travelers } from '@charts-poc/demo-data/travelers' +import { travelers } from '@tanstack/charts-data/travelers' import { Chart } from '@tanstack/charts/react' import { reactMount } from '../../shared/react-mount' import { synchronizedCursorColors } from './colors' @@ -22,7 +22,7 @@ import { } from './example' import type { ChartScene } from '@tanstack/charts' import type { ChartInteractionController } from '@tanstack/charts' -import type { TravelersRow } from '@charts-poc/demo-data/travelers' +import type { TravelersRow } from '@tanstack/charts-data/travelers' import type { ConformanceTestDriver } from '../../types' import type { ReactConformanceProps } from '../../shared/react-mount' diff --git a/benchmarks/conformance/cases/88-echarts-free-cursor/echarts.ts b/benchmarks/conformance/cases/88-echarts-free-cursor/echarts.ts index bcefaefa..1ec38987 100644 --- a/benchmarks/conformance/cases/88-echarts-free-cursor/echarts.ts +++ b/benchmarks/conformance/cases/88-echarts-free-cursor/echarts.ts @@ -7,7 +7,7 @@ import { } from 'echarts/components' import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import type { LineSeriesOption } from 'echarts/charts' import type { AriaComponentOption, diff --git a/benchmarks/conformance/cases/88-echarts-free-cursor/example.tsx b/benchmarks/conformance/cases/88-echarts-free-cursor/example.tsx index 6853d6a9..fec9b242 100644 --- a/benchmarks/conformance/cases/88-echarts-free-cursor/example.tsx +++ b/benchmarks/conformance/cases/88-echarts-free-cursor/example.tsx @@ -9,7 +9,7 @@ import type { ContinuousCursorPosition, } from '@tanstack/charts/interaction/cursor' import type { CompleteCar } from './model' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { defineChart, dot, lineY } from '@tanstack/charts' import { continuousCursor } from '@tanstack/charts/interaction/cursor' import { controlledSignal } from '@tanstack/charts/interaction/signal' diff --git a/benchmarks/conformance/cases/88-echarts-free-cursor/model.ts b/benchmarks/conformance/cases/88-echarts-free-cursor/model.ts index 797ccb87..c638fa74 100644 --- a/benchmarks/conformance/cases/88-echarts-free-cursor/model.ts +++ b/benchmarks/conformance/cases/88-echarts-free-cursor/model.ts @@ -1,4 +1,4 @@ -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' export type CompleteCar = CarsRow & { readonly 'economy (mpg)': number diff --git a/benchmarks/conformance/cases/88-echarts-free-cursor/tanstack.ts b/benchmarks/conformance/cases/88-echarts-free-cursor/tanstack.ts index 90c27270..f2fef830 100644 --- a/benchmarks/conformance/cases/88-echarts-free-cursor/tanstack.ts +++ b/benchmarks/conformance/cases/88-echarts-free-cursor/tanstack.ts @@ -16,7 +16,7 @@ export { freeCursorDefinition, } from './example' export type { CursorState } from './example' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { clientPointBounds, scenePointToClient, diff --git a/benchmarks/conformance/cases/89-brush-range-selection/echarts.ts b/benchmarks/conformance/cases/89-brush-range-selection/echarts.ts index 35d24751..0017bbd8 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/echarts.ts +++ b/benchmarks/conformance/cases/89-brush-range-selection/echarts.ts @@ -6,7 +6,7 @@ import { } from 'echarts/components' import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import type { LineSeriesOption } from 'echarts/charts' import type { BrushComponentOption, diff --git a/benchmarks/conformance/cases/89-brush-range-selection/example.tsx b/benchmarks/conformance/cases/89-brush-range-selection/example.tsx index 78bfe550..fad10159 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/example.tsx +++ b/benchmarks/conformance/cases/89-brush-range-selection/example.tsx @@ -1,13 +1,13 @@ import { useCallback, useMemo, useRef, useState } from 'react' import { Chart } from '@tanstack/charts/react' import { initialBrushRange, observedBrushDates, monthlyAaplRows } from './model' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { BrushRange, BrushXChange, } from '@tanstack/charts/interaction/brush' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export interface BrushState { range: BrushRange diff --git a/benchmarks/conformance/cases/89-brush-range-selection/model.ts b/benchmarks/conformance/cases/89-brush-range-selection/model.ts index 02c91ee0..12651799 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/model.ts +++ b/benchmarks/conformance/cases/89-brush-range-selection/model.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export interface BrushRange { start: Date diff --git a/benchmarks/conformance/cases/89-brush-range-selection/tanstack.test.ts b/benchmarks/conformance/cases/89-brush-range-selection/tanstack.test.ts index 270e18fe..d0925648 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/tanstack.test.ts +++ b/benchmarks/conformance/cases/89-brush-range-selection/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { createChartScene } from '@tanstack/charts' import { act } from 'react' import { describe, expect, expectTypeOf, it } from 'vitest' import { initialBrushRange, monthlyAaplRows, observedBrushDates } from './model' import { brushRangeDefinition, mount } from './tanstack' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartDefinition, ChartSpecDatum, diff --git a/benchmarks/conformance/cases/89-brush-range-selection/tanstack.ts b/benchmarks/conformance/cases/89-brush-range-selection/tanstack.ts index f2ebb883..570977a1 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/tanstack.ts +++ b/benchmarks/conformance/cases/89-brush-range-selection/tanstack.ts @@ -2,7 +2,7 @@ import { brushRangeDefinition, brushRangeStatus, copyRange } from './example' import type { BrushState } from './example' export { brushRangeDefinition, brushRangeStatus, copyRange } from './example' export type { BrushState } from './example' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { clientPointBounds, scenePointToClient, @@ -17,7 +17,7 @@ import { observedBrushDates, } from './model' import { normalizedElementFill } from './paint' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { BrushRange } from '@tanstack/charts/interaction/brush' import type { ChartScene } from '@tanstack/charts' import type { diff --git a/benchmarks/conformance/cases/89-brush-range-selection/view.tsx b/benchmarks/conformance/cases/89-brush-range-selection/view.tsx index b379313d..0311c78d 100644 --- a/benchmarks/conformance/cases/89-brush-range-selection/view.tsx +++ b/benchmarks/conformance/cases/89-brush-range-selection/view.tsx @@ -9,7 +9,7 @@ import { import { Chart } from '@tanstack/charts/react' import { reactMount } from '../../shared/react-mount' import { initialBrushRange, observedBrushDates, monthlyAaplRows } from './model' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { createDriver } from './tanstack' import { brushRangeDefinition, brushRangeStatus, copyRange } from './example' import type { ChartScene } from '@tanstack/charts' @@ -17,7 +17,7 @@ import type { BrushRange, BrushXChange, } from '@tanstack/charts/interaction/brush' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { BrushState } from './example' import type { ConformanceTestDriver } from '../../types' import type { ReactConformanceProps } from '../../shared/react-mount' diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/echarts.ts b/benchmarks/conformance/cases/90-zoomable-time-window/echarts.ts index cf5430ce..9a705549 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/echarts.ts +++ b/benchmarks/conformance/cases/90-zoomable-time-window/echarts.ts @@ -2,7 +2,7 @@ import { LineChart } from 'echarts/charts' import { DataZoomInsideComponent, GridComponent } from 'echarts/components' import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import type { LineSeriesOption } from 'echarts/charts' import type { DataZoomComponentOption, diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/example.tsx b/benchmarks/conformance/cases/90-zoomable-time-window/example.tsx index ef7c4da6..0540b1cf 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/example.tsx +++ b/benchmarks/conformance/cases/90-zoomable-time-window/example.tsx @@ -1,13 +1,13 @@ import { useCallback, useMemo, useRef, useState } from 'react' import { Chart } from '@tanstack/charts/react' import { initialZoomWindow } from './model' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { ZoomXChange, ZoomXWindow, } from '@tanstack/charts/interaction/zoom' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { defineChart, dot, lineY } from '@tanstack/charts' import { zoomX } from '@tanstack/charts/interaction/zoom' import { controlledSignal } from '@tanstack/charts/interaction/signal' diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/model.ts b/benchmarks/conformance/cases/90-zoomable-time-window/model.ts index 0e539078..d0483e3b 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/model.ts +++ b/benchmarks/conformance/cases/90-zoomable-time-window/model.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export interface ZoomWindow { start: Date diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.test.ts b/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.test.ts index f3f7fdaa..61a0ef4c 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.test.ts +++ b/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.test.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { createChartScene } from '@tanstack/charts' import { act } from 'react' import { describe, expect, expectTypeOf, it } from 'vitest' @@ -11,7 +11,7 @@ import { zoomSpanDays, } from './model' import { mount, zoomTimeWindowDefinition } from './tanstack' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartDefinition, ChartSpecDatum } from '@tanstack/charts' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.ts b/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.ts index 09915788..76d6fb5f 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.ts +++ b/benchmarks/conformance/cases/90-zoomable-time-window/tanstack.ts @@ -10,7 +10,7 @@ export { copyWindow, } from './example' export type { ZoomState } from './example' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { clientPointBounds, scenePointToClient, @@ -24,7 +24,7 @@ import { zoomDateKey, zoomSpanDays, } from './model' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ZoomXWindow } from '@tanstack/charts/interaction/zoom' import type { ChartScene } from '@tanstack/charts' import type { diff --git a/benchmarks/conformance/cases/90-zoomable-time-window/view.tsx b/benchmarks/conformance/cases/90-zoomable-time-window/view.tsx index 34d11274..a4694a7e 100644 --- a/benchmarks/conformance/cases/90-zoomable-time-window/view.tsx +++ b/benchmarks/conformance/cases/90-zoomable-time-window/view.tsx @@ -15,7 +15,7 @@ import { zoomStatusLabel, zoomTimeWindowDefinition, } from './example' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { ZoomXChange, diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/echarts.ts b/benchmarks/conformance/cases/91-timeline-playback-scrubber/echarts.ts index dc2f32b3..afff6e26 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/echarts.ts +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/echarts.ts @@ -2,8 +2,8 @@ import { LineChart } from 'echarts/charts' import { AriaComponent, GridComponent } from 'echarts/components' import { use } from 'echarts/core' import { SVGRenderer } from 'echarts/renderers' -import { aapl } from '@charts-poc/demo-data/aapl' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { LineSeriesOption } from 'echarts/charts' import type { AriaComponentOption, diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/example.tsx b/benchmarks/conformance/cases/91-timeline-playback-scrubber/example.tsx index e0ff5815..56b9ece8 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/example.tsx +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/example.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Chart } from '@tanstack/charts/react' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { HandleXChange } from '@tanstack/charts/interaction/handle' @@ -11,7 +11,7 @@ export interface PlaybackState { playing: boolean } import { defineChart, dot, lineY } from '@tanstack/charts' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { handleX } from '@tanstack/charts/interaction/handle' import { controlledSignal } from '@tanstack/charts/interaction/signal' import { decorative } from '@tanstack/charts/mark/decorative' diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/model.ts b/benchmarks/conformance/cases/91-timeline-playback-scrubber/model.ts index 6e831fa1..5f7617dd 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/model.ts +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/model.ts @@ -1,4 +1,4 @@ -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' export const initialPlaybackIndex = 2 diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.test.ts b/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.test.ts index 4ede1267..b75267ac 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.test.ts +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.test.ts @@ -4,9 +4,9 @@ import { createChartScene } from '@tanstack/charts' import { act } from 'react' import { describe, expect, expectTypeOf, it, vi } from 'vitest' import { initialPlaybackIndex, selectPlaybackRows } from './model' -import { aapl } from '@charts-poc/demo-data/aapl' +import { aapl } from '@tanstack/charts-data/aapl' import { mount, playbackDefinition } from './tanstack' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartDefinition, ChartSpecDatum } from '@tanstack/charts' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.ts b/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.ts index a1b517ce..fd0364a7 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.ts +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/tanstack.ts @@ -24,7 +24,7 @@ import { } from '../../shared/driver-geometry' import { playbackDateKey, playbackIndexFromAnchor } from './model' import { tanstackCase } from '../../shared/mount' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { ConformanceGeometryQuery, diff --git a/benchmarks/conformance/cases/91-timeline-playback-scrubber/view.tsx b/benchmarks/conformance/cases/91-timeline-playback-scrubber/view.tsx index b6183a5d..36474bcb 100644 --- a/benchmarks/conformance/cases/91-timeline-playback-scrubber/view.tsx +++ b/benchmarks/conformance/cases/91-timeline-playback-scrubber/view.tsx @@ -19,7 +19,7 @@ import { playbackValueText, rowForDate, } from './example' -import type { AaplRow } from '@charts-poc/demo-data/aapl' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { ChartScene } from '@tanstack/charts' import type { HandleXChange } from '@tanstack/charts/interaction/handle' import type { ReactConformanceProps } from '../../shared/react-mount' diff --git a/benchmarks/conformance/cases/93-labeled-pie/example.tsx b/benchmarks/conformance/cases/93-labeled-pie/example.tsx index 50153ebd..76be7d2f 100644 --- a/benchmarks/conformance/cases/93-labeled-pie/example.tsx +++ b/benchmarks/conformance/cases/93-labeled-pie/example.tsx @@ -9,7 +9,7 @@ import { radialRule, radialText, } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { scaleLinear } from 'd3-scale' import { selectLabeledPieData } from './selection' @@ -18,72 +18,63 @@ const radiusRatio = 0.56 const labelOffset = 20 const colors = ['#2563eb', '#7c3aed', '#db2777', '#f59e0b'] -export const labeledPieDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const arcs = pie(selectLabeledPieData(alphabet, input.revision), { value: 'frequency', }) - return defineChart({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scaleLinear().domain([0, tau]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(arcs, { - id: 'letter-slices', - key: 'letter', - color: 'letter', - }), - radialRule(arcs, { - id: 'letter-leaders', - angle: 'angle', - radius1: 1, - radius2: 1, - radius2Offset: labelOffset, - key: 'letter', - stroke: '#94a3b8', - strokeWidth: 1, - }), - radialText(arcs, { - id: 'letter-labels', - angle: 'angle', - radius: 1, - radiusOffset: labelOffset, - text: 'letter', - key: 'letter', - color: 'letter', - fontSize: 12, - fontWeight: 500, - anchor: 'outside', - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio, + angle: { scale: scaleLinear().domain([0, tau]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks: [ + radialArc(arcs, { + id: 'letter-slices', + key: 'letter', + color: 'letter', + }), + radialRule(arcs, { + id: 'letter-leaders', + angle: 'angle', + radius1: 1, + radius2: 1, + radius2Offset: labelOffset, + key: 'letter', + stroke: '#94a3b8', + strokeWidth: 1, + }), + radialText(arcs, { + id: 'letter-labels', + angle: 'angle', + radius: 1, + radiusOffset: labelOffset, + text: 'letter', + key: 'letter', + color: 'letter', + fontSize: 12, + fontWeight: 500, + anchor: 'outside', + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Letter frequency pie with labels' -export const createExampleChart = (options: ExampleOptions) => - defineChart(labeledPieDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/93-labeled-pie/recharts.ts b/benchmarks/conformance/cases/93-labeled-pie/recharts.ts index 6efee6fa..fbdccbc9 100644 --- a/benchmarks/conformance/cases/93-labeled-pie/recharts.ts +++ b/benchmarks/conformance/cases/93-labeled-pie/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectLabeledPieData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/93-labeled-pie/selection.ts b/benchmarks/conformance/cases/93-labeled-pie/selection.ts index ac6d7b58..6a9ff263 100644 --- a/benchmarks/conformance/cases/93-labeled-pie/selection.ts +++ b/benchmarks/conformance/cases/93-labeled-pie/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 4 diff --git a/benchmarks/conformance/cases/93-labeled-pie/tanstack.test.ts b/benchmarks/conformance/cases/93-labeled-pie/tanstack.test.ts index 2c6b252b..a2335935 100644 --- a/benchmarks/conformance/cases/93-labeled-pie/tanstack.test.ts +++ b/benchmarks/conformance/cases/93-labeled-pie/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { selectLabeledPieData } from './selection' -import { labeledPieDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { PieDatum } from '@tanstack/charts/polar' import type { ConformanceInput } from '../../types' @@ -157,7 +157,7 @@ describe('native labeled pie composition', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render(labeledPieDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function markPoints(points: readonly ChartPoint[], markId: string) { diff --git a/benchmarks/conformance/cases/94-center-donut/example.tsx b/benchmarks/conformance/cases/94-center-donut/example.tsx index 3fc826fb..b78eb5eb 100644 --- a/benchmarks/conformance/cases/94-center-donut/example.tsx +++ b/benchmarks/conformance/cases/94-center-donut/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc, radialText } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { scaleLinear } from 'd3-scale' import { selectCenterDonutData } from './selection' @@ -14,7 +14,7 @@ const percentage = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1, }) -export const centerDonutDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const data = selectCenterDonutData(alphabet, input.revision) const arcs = pie(data, { value: 'frequency' }) const total = data.reduce((sum, row) => sum + row.frequency, 0) @@ -22,64 +22,58 @@ export const centerDonutDefinition = (input: ExampleOptions) => { { id: 'total', angle: 0, radius: 0, text: percentage.format(total) }, ] - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.8, - angle: { scale: scaleLinear().domain([0, tau]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(arcs, { - id: 'letter-slices', - key: 'letter', - innerRadius: ({ radius }) => radius * 0.62, - color: 'letter', - }), - radialText(center, { - id: 'center-total', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - fill: '#0f172a', - fontSize: 20, - fontWeight: 700, - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.8, + angle: { scale: scaleLinear().domain([0, tau]) }, + radius: { scale: scaleLinear().domain([0, 1]) }, + marks: [ + radialArc(arcs, { + id: 'letter-slices', + key: 'letter', + innerRadius: ({ radius }) => radius * 0.62, + color: 'letter', + }), + radialText(center, { + id: 'center-total', + angle: 'angle', + radius: 'radius', + key: 'id', + text: 'text', + fill: '#0f172a', + fontSize: 20, + fontWeight: 700, + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + 'letter' in datum + ? `${datum.letter} · ${percentage.format(datum.frequency)}` + : `Total · ${datum.text}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Letter frequency donut with total' -export const createExampleChart = (options: ExampleOptions) => - defineChart(centerDonutDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - 'letter' in datum - ? `${datum.letter} · ${percentage.format(datum.frequency)}` - : `Total · ${datum.text}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/94-center-donut/recharts.ts b/benchmarks/conformance/cases/94-center-donut/recharts.ts index 0db8a269..22f382fb 100644 --- a/benchmarks/conformance/cases/94-center-donut/recharts.ts +++ b/benchmarks/conformance/cases/94-center-donut/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, Label, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectCenterDonutData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/94-center-donut/selection.ts b/benchmarks/conformance/cases/94-center-donut/selection.ts index 7eb7309e..fd08b3dd 100644 --- a/benchmarks/conformance/cases/94-center-donut/selection.ts +++ b/benchmarks/conformance/cases/94-center-donut/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 3 diff --git a/benchmarks/conformance/cases/94-center-donut/tanstack.test.ts b/benchmarks/conformance/cases/94-center-donut/tanstack.test.ts index 9e91b397..54949538 100644 --- a/benchmarks/conformance/cases/94-center-donut/tanstack.test.ts +++ b/benchmarks/conformance/cases/94-center-donut/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { selectCenterDonutData } from './selection' -import { centerDonutDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { PieDatum } from '@tanstack/charts/polar' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -154,10 +154,7 @@ describe('native center-donut allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - centerDonutDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function slicePoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/95-rounded-donut/example.tsx b/benchmarks/conformance/cases/95-rounded-donut/example.tsx index d9aa8205..5cdf076d 100644 --- a/benchmarks/conformance/cases/95-rounded-donut/example.tsx +++ b/benchmarks/conformance/cases/95-rounded-donut/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectRoundedDonutData } from './selection' const gapAngle = (Math.PI / 180) * 3 @@ -13,57 +13,51 @@ const percentage = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2, }) -export const roundedDonutDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const arcs = pie(selectRoundedDonutData(alphabet, input.revision), { value: 'frequency', gapAngle, }) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.8, - marks: [ - radialArc(arcs, { - id: 'letter-slices', - key: 'letter', - innerRadius: ({ radius }) => radius * 0.58, - cornerRadius: 8, - color: 'letter', - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.8, + marks: [ + radialArc(arcs, { + id: 'letter-slices', + key: 'letter', + innerRadius: ({ radius }) => radius * 0.58, + cornerRadius: 8, + color: 'letter', + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.letter} · ${percentage.format(datum.frequency)}`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Rounded letter frequency donut' -export const createExampleChart = (options: ExampleOptions) => - defineChart(roundedDonutDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.letter} · ${percentage.format(datum.frequency)}`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/95-rounded-donut/recharts.ts b/benchmarks/conformance/cases/95-rounded-donut/recharts.ts index 190798cd..f2f93beb 100644 --- a/benchmarks/conformance/cases/95-rounded-donut/recharts.ts +++ b/benchmarks/conformance/cases/95-rounded-donut/recharts.ts @@ -1,6 +1,6 @@ import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectRoundedDonutData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' import type { ConformanceInput } from '../../types' diff --git a/benchmarks/conformance/cases/95-rounded-donut/selection.ts b/benchmarks/conformance/cases/95-rounded-donut/selection.ts index 6ca4b7d9..39f4fcfd 100644 --- a/benchmarks/conformance/cases/95-rounded-donut/selection.ts +++ b/benchmarks/conformance/cases/95-rounded-donut/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 5 diff --git a/benchmarks/conformance/cases/95-rounded-donut/tanstack.test.ts b/benchmarks/conformance/cases/95-rounded-donut/tanstack.test.ts index d27b437c..a85de12f 100644 --- a/benchmarks/conformance/cases/95-rounded-donut/tanstack.test.ts +++ b/benchmarks/conformance/cases/95-rounded-donut/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { arc } from 'd3-shape' import { describe, expect, it } from 'vitest' import { selectRoundedDonutData } from './selection' -import { roundedDonutDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { PieDatum } from '@tanstack/charts/polar' import type { ConformanceInput } from '../../types' @@ -129,10 +129,7 @@ describe('native rounded-donut allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - roundedDonutDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function slicePoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/96-nested-donut/example.tsx b/benchmarks/conformance/cases/96-nested-donut/example.tsx index a7cf2425..92f6e624 100644 --- a/benchmarks/conformance/cases/96-nested-donut/example.tsx +++ b/benchmarks/conformance/cases/96-nested-donut/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { defineChart } from '@tanstack/charts' import { pie, polar, radialArc } from '@tanstack/charts/polar' import { nestedFlareDonut } from './transform' @@ -23,7 +23,7 @@ const colors = [ '#a855f7', ] -export const nestedDonutDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const sourceRows = input.revision % 2 === 0 ? flare @@ -32,51 +32,42 @@ export const nestedDonutDefinition = (input: ExampleOptions) => { const innerArcs = pie(data.inner, { value: 'size' }) const outerArcs = pie(data.outer, { value: 'size' }) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.8, - marks: [ - radialArc(innerArcs, { - id: 'family-slices', - key: 'name', - innerRadius: ({ radius }) => radius * 0.12, - outerRadius: ({ radius }) => radius * 0.46, - color: 'name', - }), - radialArc(outerArcs, { - id: 'detail-slices', - key: 'name', - innerRadius: ({ radius }) => radius * 0.56, - color: 'name', - }), - ], - }), - ], - color: { domain: names, range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.8, + marks: [ + radialArc(innerArcs, { + id: 'family-slices', + key: 'name', + innerRadius: ({ radius }) => radius * 0.12, + outerRadius: ({ radius }) => radius * 0.46, + color: 'name', + }), + radialArc(outerArcs, { + id: 'detail-slices', + key: 'name', + innerRadius: ({ radius }) => radius * 0.56, + color: 'name', + }), + ], + }), + ], + color: { domain: names, range: colors }, + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Nested Flare package sizes' -export const createExampleChart = (options: ExampleOptions) => - defineChart(nestedDonutDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/96-nested-donut/recharts.ts b/benchmarks/conformance/cases/96-nested-donut/recharts.ts index f427c60e..d607ea9e 100644 --- a/benchmarks/conformance/cases/96-nested-donut/recharts.ts +++ b/benchmarks/conformance/cases/96-nested-donut/recharts.ts @@ -1,4 +1,4 @@ -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' import { nestedFlareDonut } from './transform' diff --git a/benchmarks/conformance/cases/96-nested-donut/tanstack.test.ts b/benchmarks/conformance/cases/96-nested-donut/tanstack.test.ts index fda69c10..c6efab50 100644 --- a/benchmarks/conformance/cases/96-nested-donut/tanstack.test.ts +++ b/benchmarks/conformance/cases/96-nested-donut/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { createChartRuntime } from '@tanstack/charts' import { arc } from 'd3-shape' import { describe, expect, it } from 'vitest' import { nestedFlareDonut } from './transform' -import { nestedDonutDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { FlareDonutDetail, FlareDonutSlice } from './transform' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { PieDatum } from '@tanstack/charts/polar' @@ -148,10 +148,7 @@ describe('native nested-donut allocation', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - nestedDonutDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function familyPoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/96-nested-donut/transform.test.ts b/benchmarks/conformance/cases/96-nested-donut/transform.test.ts index 8762f888..fde39347 100644 --- a/benchmarks/conformance/cases/96-nested-donut/transform.test.ts +++ b/benchmarks/conformance/cases/96-nested-donut/transform.test.ts @@ -1,4 +1,4 @@ -import { flare } from '@charts-poc/demo-data/flare' +import { flare } from '@tanstack/charts-data/flare' import { describe, expect, it } from 'vitest' import { nestedFlareDonut } from './transform' diff --git a/benchmarks/conformance/cases/96-nested-donut/transform.ts b/benchmarks/conformance/cases/96-nested-donut/transform.ts index 2c259eb8..614df569 100644 --- a/benchmarks/conformance/cases/96-nested-donut/transform.ts +++ b/benchmarks/conformance/cases/96-nested-donut/transform.ts @@ -1,4 +1,4 @@ -import type { FlareRow } from '@charts-poc/demo-data/flare' +import type { FlareRow } from '@tanstack/charts-data/flare' export interface FlareDonutSlice { name: string diff --git a/benchmarks/conformance/cases/97-rose/example.tsx b/benchmarks/conformance/cases/97-rose/example.tsx index e0d316ac..7a15e383 100644 --- a/benchmarks/conformance/cases/97-rose/example.tsx +++ b/benchmarks/conformance/cases/97-rose/example.tsx @@ -3,7 +3,7 @@ import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' import { defineChart } from '@tanstack/charts' import { polar, radialBarRadius } from '@tanstack/charts/polar' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { scaleBand, scaleLinear } from 'd3-scale' import { selectRoseData } from './selection' @@ -17,55 +17,46 @@ const colors = [ ] const maximumFrequency = alphabet[0]?.frequency ?? 1 -export const roseDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const data = selectRoseData(alphabet, input.revision) - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.8, - angle: { scale: () => scaleBand() }, - radius: { - scale: scaleLinear().domain([0, maximumFrequency]), - range: [({ radius }) => radius * 0.3, ({ radius }) => radius], - }, - marks: [ - radialBarRadius(data, { - id: 'letter-bars', - angle: 'letter', - radius: 'frequency', - key: 'letter', - color: 'letter', - stroke: '#ffffff', - strokeWidth: 1, - }), - ], - }), - ], - color: { range: colors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + radiusRatio: 0.8, + angle: { scale: () => scaleBand() }, + radius: { + scale: scaleLinear().domain([0, maximumFrequency]), + range: [({ radius }) => radius * 0.3, ({ radius }) => radius], + }, + marks: [ + radialBarRadius(data, { + id: 'letter-bars', + angle: 'letter', + radius: 'frequency', + key: 'letter', + color: 'letter', + stroke: '#ffffff', + strokeWidth: 1, + }), + ], + }), + ], + color: { range: colors }, + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'English letter frequency rose' -export const createExampleChart = (options: ExampleOptions) => - defineChart(roseDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/97-rose/recharts.ts b/benchmarks/conformance/cases/97-rose/recharts.ts index e083bc66..20ffec6a 100644 --- a/benchmarks/conformance/cases/97-rose/recharts.ts +++ b/benchmarks/conformance/cases/97-rose/recharts.ts @@ -1,9 +1,9 @@ import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { selectRoseData } from './selection' import { rechartsMount } from '../../shared/recharts-mount' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { ConformanceInput } from '../../types' const colors = [ diff --git a/benchmarks/conformance/cases/97-rose/selection.ts b/benchmarks/conformance/cases/97-rose/selection.ts index 9a162967..68a53a2a 100644 --- a/benchmarks/conformance/cases/97-rose/selection.ts +++ b/benchmarks/conformance/cases/97-rose/selection.ts @@ -1,4 +1,4 @@ -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' const sliceSize = 6 diff --git a/benchmarks/conformance/cases/97-rose/tanstack.test.ts b/benchmarks/conformance/cases/97-rose/tanstack.test.ts index 4efa55b9..bd719abd 100644 --- a/benchmarks/conformance/cases/97-rose/tanstack.test.ts +++ b/benchmarks/conformance/cases/97-rose/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { createChartRuntime } from '@tanstack/charts' import { arc, pointRadial } from 'd3-shape' import { describe, expect, it } from 'vitest' import { selectRoseData } from './selection' -import { roseDefinition } from './tanstack' -import type { AlphabetRow } from '@charts-poc/demo-data/alphabet' +import { createExampleChart } from './tanstack' +import type { AlphabetRow } from '@tanstack/charts-data/alphabet' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -172,7 +172,7 @@ function roseRadius(frequency: number, radius: number): number { } function render(nextInput: ConformanceInput) { - return createChartRuntime().render(roseDefinition(nextInput), nextInput) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function barPoints(points: readonly ChartPoint[]) { diff --git a/benchmarks/conformance/cases/98-needle-gauge/example.tsx b/benchmarks/conformance/cases/98-needle-gauge/example.tsx index fef3e3ca..d561fbd6 100644 --- a/benchmarks/conformance/cases/98-needle-gauge/example.tsx +++ b/benchmarks/conformance/cases/98-needle-gauge/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import { defineChart } from '@tanstack/charts' import { pie, @@ -31,104 +31,98 @@ const arcs = pie(gaugeBands, { const bandIds: readonly GaugeBand['id'][] = ['low', 'elevated', 'high'] const bandColors = ['#22c55e', '#f59e0b', '#ef4444'] -export const needleGaugeDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const reading = usCountyUnemployment[(input.revision % 2) * 2] if (!reading) { throw new Error('County unemployment data is incomplete.') } - return defineChart({ - marks: [ - polar({ - angle: { scale: angleScale }, - radius: { scale: radiusScale }, - startAngle, - endAngle, - radiusRatio: 0.82, - marks: [ - radialArc(arcs, { - id: 'gauge-bands', - key: 'id', - innerRadius: ({ radius }) => radius * 0.72, - color: 'id', - }), - radialRule(gaugeTicks, { - id: 'gauge-ticks', - key: 'id', - angle: 'value', - radius1: 0.76, - radius2: 0.94, - stroke: '#ffffff', - strokeOpacity: 0.85, - strokeWidth: 2, - }), - radialRule([reading], { - id: 'gauge-needle', - key: 'id', - angle: 'rate', - radius1: 0, - radius2: 0.64, - stroke: 'currentColor', - strokeWidth: 4, - }), - radialDot([reading], { - id: 'gauge-hub', - key: 'id', - angle: 'rate', - radius: 0, - r: 8, - fill: 'currentColor', - }), - radialText([reading], { - id: 'gauge-value', - key: 'id', - angle: 'rate', - radius: 0, - text: (row) => `${row.rate}%`, - dy: 34, - anchor: 'middle', - baseline: 'middle', - fill: 'currentColor', - fontSize: 18, - fontWeight: 700, - }), - ], - }), - ], - color: { domain: bandIds, range: bandColors }, - margin: 0, - }) + return defineChart( + { + marks: [ + polar({ + angle: { scale: angleScale }, + radius: { scale: radiusScale }, + startAngle, + endAngle, + radiusRatio: 0.82, + marks: [ + radialArc(arcs, { + id: 'gauge-bands', + key: 'id', + innerRadius: ({ radius }) => radius * 0.72, + color: 'id', + }), + radialRule(gaugeTicks, { + id: 'gauge-ticks', + key: 'id', + angle: 'value', + radius1: 0.76, + radius2: 0.94, + stroke: '#ffffff', + strokeOpacity: 0.85, + strokeWidth: 2, + }), + radialRule([reading], { + id: 'gauge-needle', + key: 'id', + angle: 'rate', + radius1: 0, + radius2: 0.64, + stroke: 'currentColor', + strokeWidth: 4, + }), + radialDot([reading], { + id: 'gauge-hub', + key: 'id', + angle: 'rate', + radius: 0, + r: 8, + fill: 'currentColor', + }), + radialText([reading], { + id: 'gauge-value', + key: 'id', + angle: 'rate', + radius: 0, + text: (row) => `${row.rate}%`, + dy: 34, + anchor: 'middle', + baseline: 'middle', + fill: 'currentColor', + fontSize: 18, + fontWeight: 700, + }), + ], + }), + ], + color: { domain: bandIds, range: bandColors }, + margin: 0, + }, + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => { + if ('label' in datum) { + return `${datum.label} · ${datum.value} percentage-point band` + } + return `${datum.county}, ${datum.state} · ${datum.rate}% unemployment` + }, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'County unemployment gauge' -export const createExampleChart = (options: ExampleOptions) => - defineChart(needleGaugeDefinition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => { - if ('label' in datum) { - return `${datum.label} · ${datum.value} percentage-point band` - } - return `${datum.county}, ${datum.state} · ${datum.rate}% unemployment` - }, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/98-needle-gauge/recharts.ts b/benchmarks/conformance/cases/98-needle-gauge/recharts.ts index 5fca0caf..4f3cfc9a 100644 --- a/benchmarks/conformance/cases/98-needle-gauge/recharts.ts +++ b/benchmarks/conformance/cases/98-needle-gauge/recharts.ts @@ -1,4 +1,4 @@ -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import { createElement } from 'react' import { Cell, Pie, PieChart } from 'recharts' import { gaugeBands, gaugeMaximum, gaugeTicks } from './transform' diff --git a/benchmarks/conformance/cases/98-needle-gauge/tanstack.test.ts b/benchmarks/conformance/cases/98-needle-gauge/tanstack.test.ts index 2ae8ade2..5a8b4563 100644 --- a/benchmarks/conformance/cases/98-needle-gauge/tanstack.test.ts +++ b/benchmarks/conformance/cases/98-needle-gauge/tanstack.test.ts @@ -1,11 +1,11 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import { createChartRuntime } from '@tanstack/charts' import { arc } from 'd3-shape' import { describe, expect, it } from 'vitest' import { gaugeBands, gaugeMaximum, gaugeTicks } from './transform' -import { needleGaugeDefinition } from './tanstack' +import { createExampleChart } from './tanstack' import type { GaugeBand } from './transform' import type { ChartPoint, SceneNode } from '@tanstack/charts' import type { PieDatum } from '@tanstack/charts/polar' @@ -208,10 +208,7 @@ describe('native needle-gauge composition', () => { }) function render(nextInput: ConformanceInput) { - return createChartRuntime().render( - needleGaugeDefinition(nextInput), - nextInput, - ) + return createChartRuntime().render(createExampleChart(nextInput), nextInput) } function scaleAngle(value: number) { diff --git a/benchmarks/conformance/cases/99-comparative-radar/example.tsx b/benchmarks/conformance/cases/99-comparative-radar/example.tsx index 49069af8..7367617b 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/example.tsx +++ b/benchmarks/conformance/cases/99-comparative-radar/example.tsx @@ -9,7 +9,7 @@ import { radialArea, radialGrid, } from '@tanstack/charts/polar' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { scaleLinear, scalePoint } from 'd3-scale' import { curveLinearClosed } from 'd3-shape' import { radarCountries, radarEvents, timedEvents } from './selection' @@ -49,83 +49,76 @@ function angleLabelDy({ angle, y }: PolarGuideLabelContext): number { return y > 0 ? -1.1 : 0 } -export const comparativeRadarDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const margin = input.width < 480 ? { top: 20, right: 55, bottom: 20, left: 105 } : { top: 20, right: 20, bottom: 20, left: 20 } - return defineChart({ - marks: [ - polar({ - angle: { scale: angleScale, wrap: true }, - radius: { scale: radiusScale }, - inset: 0, - radiusRatio: input.preview === true ? 0.94 : 0.78, - guides: [ - radialGrid({ - values: ringValues, - shape: 'polygon', - labels: input.preview !== true, - labelAngle: Math.PI / 3, - labelRotate: 60, - labelBaseline: 'auto', - labelFontSize: 12, - format: (value) => String(Number(value) * 100), - labelFill: '#cccccc', - stroke: '#cbd5e1', - }), - angleGrid({ - values: radarEvents, - labels: input.preview !== true, - labelOffset: 8, - labelDy: angleLabelDy, - labelFill: '#808080', - labelFontSize: 12, - format: String, - stroke: '#cbd5e1', - }), - ], - marks: [ - radialArea(radarProfiles, { - id: 'country-profiles', - angle: 'event', - radius: 'relativePerformance', - color: 'Country', - key: ({ Country, event }) => `${Country}:${event}`, - className: 'ts-chart__radar', - curve: curveLinearClosed, - fillOpacity: 0.18, - }), - ], - }), - ], - color: { - domain: radarCountries, - range: colors, + return defineChart( + { + marks: [ + polar({ + angle: { scale: angleScale, wrap: true }, + radius: { scale: radiusScale }, + inset: 0, + radiusRatio: input.preview === true ? 0.94 : 0.78, + guides: [ + radialGrid({ + values: ringValues, + shape: 'polygon', + labels: input.preview !== true, + labelAngle: Math.PI / 3, + labelRotate: 60, + labelBaseline: 'auto', + labelFontSize: 12, + format: (value) => String(Number(value) * 100), + labelFill: '#cccccc', + stroke: '#cbd5e1', + }), + angleGrid({ + values: radarEvents, + labels: input.preview !== true, + labelOffset: 8, + labelDy: angleLabelDy, + labelFill: '#808080', + labelFontSize: 12, + format: String, + stroke: '#cbd5e1', + }), + ], + marks: [ + radialArea(radarProfiles, { + id: 'country-profiles', + angle: 'event', + radius: 'relativePerformance', + color: 'Country', + key: ({ Country, event }) => `${Country}:${event}`, + className: 'ts-chart__radar', + curve: curveLinearClosed, + fillOpacity: 0.18, + }), + ], + }), + ], + color: { + domain: radarCountries, + range: colors, + }, + margin: input.preview === true ? 0 : margin, }, - margin: input.preview === true ? 0 : margin, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { +export interface ChartOptions { width: number - height: number - revision: number preview?: boolean } export const exampleAriaLabel = 'Comparative radar chart' -export const createExampleChart = (options: ExampleOptions) => - defineChart(comparativeRadarDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/99-comparative-radar/recharts.ts b/benchmarks/conformance/cases/99-comparative-radar/recharts.ts index ca64a9c0..306b2514 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/recharts.ts +++ b/benchmarks/conformance/cases/99-comparative-radar/recharts.ts @@ -6,7 +6,7 @@ import { Radar, RadarChart, } from 'recharts' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { selectRadarProfiles } from './selection' import { comparativeRadarData } from './transform' import { rechartsMount } from '../../shared/recharts-mount' diff --git a/benchmarks/conformance/cases/99-comparative-radar/selection.ts b/benchmarks/conformance/cases/99-comparative-radar/selection.ts index 3c8539f3..83b268a8 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/selection.ts +++ b/benchmarks/conformance/cases/99-comparative-radar/selection.ts @@ -1,4 +1,4 @@ -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' export const radarEvents = [ '100 Meters', diff --git a/benchmarks/conformance/cases/99-comparative-radar/tanstack.test.ts b/benchmarks/conformance/cases/99-comparative-radar/tanstack.test.ts index 2c175bc9..ac731298 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/tanstack.test.ts +++ b/benchmarks/conformance/cases/99-comparative-radar/tanstack.test.ts @@ -1,12 +1,12 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { createChartRuntime } from '@tanstack/charts' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { describe, expect, it } from 'vitest' import { catalogPreviewDefinition } from '../../shared/preview' import { radarCountries, radarEvents } from './selection' import { - comparativeRadarDefinition, + createExampleChart, foldedDecathlon, normalizedDecathlon, radarProfiles, @@ -71,7 +71,7 @@ describe('folded comparative radar profiles', () => { preview: true, } satisfies ConformanceInput const scene = createChartRuntime().render( - catalogPreviewDefinition(comparativeRadarDefinition(previewInput)), + catalogPreviewDefinition(createExampleChart(previewInput)), previewInput, ) const nodes = flatten(scene.nodes) @@ -111,7 +111,7 @@ describe('folded comparative radar profiles', () => { }) function render() { - return createChartRuntime().render(comparativeRadarDefinition(input), input) + return createChartRuntime().render(createExampleChart(input), input) } function flatten(nodes: readonly SceneNode[]): SceneNode[] { diff --git a/benchmarks/conformance/cases/99-comparative-radar/transform.test.ts b/benchmarks/conformance/cases/99-comparative-radar/transform.test.ts index 12076032..23b44e8b 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/transform.test.ts +++ b/benchmarks/conformance/cases/99-comparative-radar/transform.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { decathlon } from '@charts-poc/demo-data/decathlon' +import { decathlon } from '@tanstack/charts-data/decathlon' import { selectRadarProfiles } from './selection' import { comparativeRadarData, comparativeRadarPoints } from './transform' diff --git a/benchmarks/conformance/cases/99-comparative-radar/transform.ts b/benchmarks/conformance/cases/99-comparative-radar/transform.ts index 977ea4f6..0a649b4c 100644 --- a/benchmarks/conformance/cases/99-comparative-radar/transform.ts +++ b/benchmarks/conformance/cases/99-comparative-radar/transform.ts @@ -1,5 +1,5 @@ import { extent } from 'd3-array' -import type { DecathlonRow } from '@charts-poc/demo-data/decathlon' +import type { DecathlonRow } from '@tanstack/charts-data/decathlon' import { radarCountries, radarEvents, timedEvents } from './selection' import type { RadarCountry, RadarEvent } from './selection' diff --git a/benchmarks/conformance/cases/bar-grouped/example.tsx b/benchmarks/conformance/cases/bar-grouped/example.tsx index 5f05a0ea..9f678386 100644 --- a/benchmarks/conformance/cases/bar-grouped/example.tsx +++ b/benchmarks/conformance/cases/bar-grouped/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { barY, colorLegend, @@ -10,73 +10,65 @@ import { groupBy, } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' const sexDomain = ['FEMALE', 'MALE'] const sexColors = ['#2563eb', '#f97316'] type SexedPenguin = PenguinsRow & { readonly sex: string } -export const groupedBarDefinition = (input: ExampleOptions) => - defineChart(({ width }) => { - const observations = penguins - .slice(0, penguins.length - input.revision * 12) - .filter((row): row is SexedPenguin => row.sex !== null) - const rows = groupBy(observations, { - by: { species: 'species', sex: 'sex' }, - outputs: { count: { reduce: 'count' } }, - }) +export const createExampleChart = (input: ChartOptions) => + defineChart( + ({ width }) => { + const observations = penguins + .slice(0, penguins.length - input.revision * 12) + .filter((row): row is SexedPenguin => row.sex !== null) + const rows = groupBy(observations, { + by: { species: 'species', sex: 'sex' }, + outputs: { count: { reduce: 'count' } }, + }) - return { - marks: [ - barY(rows, { - id: 'penguin-count-bars', - x: 'species', - y: 'count', - color: 'sex', - layout: group({ - scale: scaleBand().domain(sexDomain).paddingInner(0.08), + return { + marks: [ + barY(rows, { + id: 'penguin-count-bars', + x: 'species', + y: 'count', + color: 'sex', + layout: group({ + scale: scaleBand().domain(sexDomain).paddingInner(0.08), + }), + inset: 1, }), - inset: 1, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.14).paddingOuter(0.06), - axis: { tickLabels: { rotate: width < 640 ? -32 : 0 } }, - }, - y: { - scale: scaleLinear, - grid: true, - axis: { ticks: { count: 5 }, label: 'Penguins' }, - }, - color: { - range: sexColors, - legend: colorLegend({ - label: 'Sex', - }), - }, - } - }) -export interface ExampleOptions { - width: number - height: number + ], + x: { + scale: () => + scaleBand().paddingInner(0.14).paddingOuter(0.06), + axis: { tickLabels: { rotate: width < 640 ? -32 : 0 } }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { ticks: { count: 5 }, label: 'Penguins' }, + }, + color: { + range: sexColors, + legend: colorLegend({ + label: 'Sex', + }), + }, + } + }, + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Penguins grouped by species' -export const createExampleChart = (options: ExampleOptions) => - defineChart(groupedBarDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/bar-grouped/plot.ts b/benchmarks/conformance/cases/bar-grouped/plot.ts index 43705c02..fc121965 100644 --- a/benchmarks/conformance/cases/bar-grouped/plot.ts +++ b/benchmarks/conformance/cases/bar-grouped/plot.ts @@ -1,4 +1,4 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import * as Plot from '@observablehq/plot' import type { ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/bar-grouped/tanstack.test.ts b/benchmarks/conformance/cases/bar-grouped/tanstack.test.ts index 2951c31d..a00b0e88 100644 --- a/benchmarks/conformance/cases/bar-grouped/tanstack.test.ts +++ b/benchmarks/conformance/cases/bar-grouped/tanstack.test.ts @@ -1,9 +1,9 @@ -import { penguins } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { loadTanStackSources } from '../../native-catalog' -import { groupedBarDefinition } from './tanstack' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { createExampleChart } from './tanstack' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' import type { ChartPoint } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -78,7 +78,7 @@ describe('grouped penguin bars', () => { }) function render(input: ConformanceInput) { - return createChartRuntime().render(groupedBarDefinition(input), input) + return createChartRuntime().render(createExampleChart(input), input) } function count( diff --git a/benchmarks/conformance/cases/bar-horizontal-ranking/example.tsx b/benchmarks/conformance/cases/bar-horizontal-ranking/example.tsx index d58102a7..680a75b6 100644 --- a/benchmarks/conformance/cases/bar-horizontal-ranking/example.tsx +++ b/benchmarks/conformance/cases/bar-horizontal-ranking/example.tsx @@ -1,56 +1,49 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import { barX, defineChart, ruleX } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = citywages .slice(input.revision * 4, input.revision * 4 + 8) .sort((left, right) => right.POP_2015 - left.POP_2015) - return defineChart({ - marks: [ - barX(rows, { - x: 'POP_2015', - y: 'Metro', - fill: '#7c3aed', - inset: 1, - }), - ruleX([0]), - ], - x: { - scale: scaleLinear, - grid: input.preview !== true, - axis: - input.preview === true - ? false - : { ticks: { count: 5 }, label: '2015 population' }, + return defineChart( + { + marks: [ + barX(rows, { + x: 'POP_2015', + y: 'Metro', + fill: '#7c3aed', + inset: 1, + }), + ruleX([0]), + ], + x: { + scale: scaleLinear, + grid: input.preview !== true, + axis: + input.preview === true + ? false + : { ticks: { count: 5 }, label: '2015 population' }, + }, + y: { + scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + }, }, - y: { - scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), - }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number preview?: boolean } export const exampleAriaLabel = 'Horizontal ranking with long labels' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/bar-horizontal-ranking/plot.ts b/benchmarks/conformance/cases/bar-horizontal-ranking/plot.ts index 07e4654e..a9e78000 100644 --- a/benchmarks/conformance/cases/bar-horizontal-ranking/plot.ts +++ b/benchmarks/conformance/cases/bar-horizontal-ranking/plot.ts @@ -1,4 +1,4 @@ -import { citywages } from '@charts-poc/demo-data/citywages' +import { citywages } from '@tanstack/charts-data/citywages' import * as Plot from '@observablehq/plot' import type { ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/bar-stacked/example.tsx b/benchmarks/conformance/cases/bar-stacked/example.tsx index 6c684d43..94df51f3 100644 --- a/benchmarks/conformance/cases/bar-stacked/example.tsx +++ b/benchmarks/conformance/cases/bar-stacked/example.tsx @@ -1,68 +1,59 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { crimeanWar } from '@charts-poc/demo-data/crimean-war' +import { crimeanWar } from '@tanstack/charts-data/crimean-war' import { barY, defineChart, fold, ruleY, stack } from '@tanstack/charts' import { scaleLinear, scaleUtc } from 'd3-scale' const causes = ['disease', 'wounds', 'other'] as const const causeColors = ['#4269d0', '#ff725c', '#efb118'] -export const stackedBarDefinition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = fold(crimeanWar.slice(input.revision), { fields: causes, as: { key: 'cause', value: 'deaths' }, }) - return defineChart({ - marks: [ - barY(rows, { - id: 'death-bars', - x: 'date', - y: 'deaths', - z: 'cause', - color: 'cause', - layout: stack({ order: [...causes].reverse() }), - }), - ruleY([0]), - ], - x: { - scale: scaleUtc, - axis: { ticks: { count: 6, format: (value) => month.format(value) } }, + return defineChart( + { + marks: [ + barY(rows, { + id: 'death-bars', + x: 'date', + y: 'deaths', + z: 'cause', + color: 'cause', + layout: stack({ order: [...causes].reverse() }), + }), + ruleY([0]), + ], + x: { + scale: scaleUtc, + axis: { ticks: { count: 6, format: (value) => month.format(value) } }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { ticks: { count: 5 }, label: 'Deaths' }, + }, + color: { domain: causes, range: causeColors }, }, - y: { - scale: scaleLinear, - grid: true, - axis: { ticks: { count: 5 }, label: 'Deaths' }, - }, - color: { domain: causes, range: causeColors }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } const month = new Intl.DateTimeFormat('en-US', { month: 'short', timeZone: 'UTC', }) -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Crimean War deaths by cause' -export const createExampleChart = (options: ExampleOptions) => - defineChart(stackedBarDefinition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/bar-stacked/plot.ts b/benchmarks/conformance/cases/bar-stacked/plot.ts index 6cd3a974..717cecd7 100644 --- a/benchmarks/conformance/cases/bar-stacked/plot.ts +++ b/benchmarks/conformance/cases/bar-stacked/plot.ts @@ -1,4 +1,4 @@ -import { crimeanWar } from '@charts-poc/demo-data/crimean-war' +import { crimeanWar } from '@tanstack/charts-data/crimean-war' import * as Plot from '@observablehq/plot' import type { ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/bar-stacked/tanstack.test.ts b/benchmarks/conformance/cases/bar-stacked/tanstack.test.ts index 9ecf15ad..bb922779 100644 --- a/benchmarks/conformance/cases/bar-stacked/tanstack.test.ts +++ b/benchmarks/conformance/cases/bar-stacked/tanstack.test.ts @@ -1,9 +1,9 @@ -import { crimeanWar } from '@charts-poc/demo-data/crimean-war' +import { crimeanWar } from '@tanstack/charts-data/crimean-war' import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { loadTanStackSources } from '../../native-catalog' -import { stackedBarDefinition } from './tanstack' -import type { CrimeanWarRow } from '@charts-poc/demo-data/crimean-war' +import { createExampleChart } from './tanstack' +import type { CrimeanWarRow } from '@tanstack/charts-data/crimean-war' import type { ChartPoint } from '@tanstack/charts' import type { ConformanceInput } from '../../types' @@ -77,5 +77,5 @@ describe('stacked Crimean War bars', () => { }) function render(input: ConformanceInput) { - return createChartRuntime().render(stackedBarDefinition(input), input) + return createChartRuntime().render(createExampleChart(input), input) } diff --git a/benchmarks/conformance/cases/bar-vertical-sorted/example.tsx b/benchmarks/conformance/cases/bar-vertical-sorted/example.tsx index a4c56668..709b4725 100644 --- a/benchmarks/conformance/cases/bar-vertical-sorted/example.tsx +++ b/benchmarks/conformance/cases/bar-vertical-sorted/example.tsx @@ -1,4 +1,4 @@ -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import { barY, defineChart } from '@tanstack/charts' import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip } from '@tanstack/charts/tooltip' @@ -9,44 +9,46 @@ const percent = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1, }) -const chart = defineChart(({ width }) => ({ - marks: [ - barY(alphabet, { - x: 'letter', - y: 'frequency', - fill: '#2563eb', - inset: 1, +export const createExampleChart = () => + defineChart( + ({ width }) => ({ + marks: [ + barY(alphabet, { + x: 'letter', + y: 'frequency', + fill: '#2563eb', + inset: 1, + }), + ], + x: { + scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), + axis: { tickLabels: { rotate: width < 560 ? -32 : 0 } }, + }, + y: { + scale: scaleLinear, + grid: true, + axis: { + ticks: { + count: 5, + format: (value: number) => percent.format(value), + }, + label: 'Frequency', + }, + }, }), - ], - x: { - scale: () => scaleBand().paddingInner(0.1).paddingOuter(0.05), - axis: { tickLabels: { rotate: width < 560 ? -32 : 0 } }, - }, - y: { - scale: scaleLinear, - grid: true, - axis: { - ticks: { - count: 5, - format: (value: number) => percent.format(value), + { + keyboard: true, + tooltip: { + use: tooltip, + format: ({ datum }) => + `${datum.letter} · ${percent.format(datum.frequency)} frequency`, }, - label: 'Frequency', }, - }, -})) + ) export const exampleAriaLabel = 'Sorted vertical bars' -export const definition = defineChart(chart, { - keyboard: true, - tooltip: { - use: tooltip, - format: ({ datum }) => - `${datum.letter} · ${percent.format(datum.frequency)} frequency`, - }, -}) - -export const createExampleChart = () => definition +export const definition = createExampleChart() export default function AlphabetFrequencyChart() { return ( diff --git a/benchmarks/conformance/cases/bar-vertical-sorted/plot.ts b/benchmarks/conformance/cases/bar-vertical-sorted/plot.ts index 231f9f2f..2cafa978 100644 --- a/benchmarks/conformance/cases/bar-vertical-sorted/plot.ts +++ b/benchmarks/conformance/cases/bar-vertical-sorted/plot.ts @@ -1,4 +1,4 @@ -import { alphabet } from '@charts-poc/demo-data/alphabet' +import { alphabet } from '@tanstack/charts-data/alphabet' import * as Plot from '@observablehq/plot' import type { ConformanceMount } from '../../types' import { mountObservablePlot } from '../../shared/mount' diff --git a/benchmarks/conformance/cases/facets-anscombe/example.tsx b/benchmarks/conformance/cases/facets-anscombe/example.tsx index 633819af..d5f05d4a 100644 --- a/benchmarks/conformance/cases/facets-anscombe/example.tsx +++ b/benchmarks/conformance/cases/facets-anscombe/example.tsx @@ -1,61 +1,52 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { anscombe } from '@charts-poc/demo-data/anscombe' +import { anscombe } from '@tanstack/charts-data/anscombe' import { defineChart, dot, facet } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -export const definition = (input: ExampleOptions) => - defineChart({ - marks: [ - facet(anscombe, { - by: 'series', - columns: 4, - gap: input.preview === true ? 4 : 12, - label: input.preview === true ? false : (series) => String(series), - chart: (facetRows) => ({ - marks: [ - dot(facetRows, { - x: 'x', - y: 'y', - r: 3.5, - fill: '#2563eb', - }), - ], - x: { - scale: scaleLinear().domain([3, 20]), - grid: input.preview !== true, - axis: input.preview === true ? false : { ticks: { count: 5 } }, - }, - y: { - scale: scaleLinear().domain([2, 14]), - grid: input.preview !== true, - axis: input.preview === true ? false : { ticks: { count: 4 } }, - }, +export const createExampleChart = (input: ChartOptions) => + defineChart( + { + marks: [ + facet(anscombe, { + by: 'series', + columns: 4, + gap: input.preview === true ? 4 : 12, + label: input.preview === true ? false : (series) => String(series), + chart: (facetRows) => ({ + marks: [ + dot(facetRows, { + x: 'x', + y: 'y', + r: 3.5, + fill: '#2563eb', + }), + ], + x: { + scale: scaleLinear().domain([3, 20]), + grid: input.preview !== true, + axis: input.preview === true ? false : { ticks: { count: 5 } }, + }, + y: { + scale: scaleLinear().domain([2, 14]), + grid: input.preview !== true, + axis: input.preview === true ? false : { ticks: { count: 4 } }, + }, + }), }), - }), - ], - margin: 0, - }) -export interface ExampleOptions { - width: number - height: number - revision: number + ], + margin: 0, + }, + { keyboard: true, tooltip: exampleTooltip }, + ) +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = "Anscombe's quartet small multiples" -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/facets-anscombe/plot.ts b/benchmarks/conformance/cases/facets-anscombe/plot.ts index 0b6cf7ed..e9ab3a73 100644 --- a/benchmarks/conformance/cases/facets-anscombe/plot.ts +++ b/benchmarks/conformance/cases/facets-anscombe/plot.ts @@ -1,4 +1,4 @@ -import { anscombe } from '@charts-poc/demo-data/anscombe' +import { anscombe } from '@tanstack/charts-data/anscombe' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/heatmap-labeled/example.tsx b/benchmarks/conformance/cases/heatmap-labeled/example.tsx index 44c4f6d1..d994d4d1 100644 --- a/benchmarks/conformance/cases/heatmap-labeled/example.tsx +++ b/benchmarks/conformance/cases/heatmap-labeled/example.tsx @@ -1,7 +1,7 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import { cell, colorGradientLegend, defineChart, text } from '@tanstack/charts' import { scaleBand, scaleLinear } from 'd3-scale' @@ -10,7 +10,7 @@ const previewEpisodes = simpsons.filter( (row) => row.season <= 4 && row.number_in_season <= 7, ) -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const episodes = input.preview ? previewEpisodes : simpsons const episodeDomain = [ ...new Set(episodes.map((row) => row.number_in_season)), @@ -21,83 +21,77 @@ export const definition = (input: ExampleOptions) => { const ratedEpisodes = episodes.filter((row) => row.imdb_rating !== null) const unratedEpisodes = episodes.filter((row) => row.imdb_rating === null) - return defineChart({ - marks: [ - cell(ratedEpisodes, { - x: 'number_in_season', - y: 'season', - color: 'imdb_rating', - inset: 1, - }), - cell(unratedEpisodes, { - x: 'number_in_season', - y: 'season', - fill: '#d1d5db', - inset: 1, - }), - text(episodes, { - x: 'number_in_season', - y: 'season', - text: (row) => - row.imdb_rating === null ? '–' : row.imdb_rating.toFixed(1), - fill: (row) => - row.imdb_rating !== null && - (row.imdb_rating < 5.5 || row.imdb_rating > 8.6) - ? '#f8fafc' - : '#0f172a', - fontSize: 10, - fontWeight: 600, - }), - ], - x: { - scale: scaleBand() - .domain(episodeDomain) - .paddingInner(0.04) - .paddingOuter(0.02), - axis: { label: 'Episode' }, - }, - y: { - scale: scaleBand() - .domain(seasonDomain) - .paddingInner(0.04) - .paddingOuter(0.02), - axis: { label: 'Season' }, + return defineChart( + { + marks: [ + cell(ratedEpisodes, { + x: 'number_in_season', + y: 'season', + color: 'imdb_rating', + inset: 1, + }), + cell(unratedEpisodes, { + x: 'number_in_season', + y: 'season', + fill: '#d1d5db', + inset: 1, + }), + text(episodes, { + x: 'number_in_season', + y: 'season', + text: (row) => + row.imdb_rating === null ? '–' : row.imdb_rating.toFixed(1), + fill: (row) => + row.imdb_rating !== null && + (row.imdb_rating < 5.5 || row.imdb_rating > 8.6) + ? '#f8fafc' + : '#0f172a', + fontSize: 10, + fontWeight: 600, + }), + ], + x: { + scale: scaleBand() + .domain(episodeDomain) + .paddingInner(0.04) + .paddingOuter(0.02), + axis: { label: 'Episode' }, + }, + y: { + scale: scaleBand() + .domain(seasonDomain) + .paddingInner(0.04) + .paddingOuter(0.02), + axis: { label: 'Season' }, + }, + color: { + scale: () => scaleLinear().range(ratingColors), + legend: colorGradientLegend({ label: 'IMDb rating', steps: 6 }), + }, }, - color: { - scale: () => scaleLinear().range(ratingColors), - legend: colorGradientLegend({ label: 'IMDb rating', steps: 6 }), + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.title} · Season ${datum.season}, episode ${datum.number_in_season} · ${ + datum.imdb_rating === null + ? 'No IMDb rating' + : `${datum.imdb_rating.toFixed(1)} IMDb` + }`, + }, + }, }, - }) + ) } -export interface ExampleOptions { - width: number - height: number - revision: number +export interface ChartOptions { preview?: boolean } export const exampleAriaLabel = 'The Simpsons episode ratings' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.title} · Season ${datum.season}, episode ${datum.number_in_season} · ${ - datum.imdb_rating === null - ? 'No IMDb rating' - : `${datum.imdb_rating.toFixed(1)} IMDb` - }`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, - revision: 0, preview: false, }) diff --git a/benchmarks/conformance/cases/heatmap-labeled/plot.ts b/benchmarks/conformance/cases/heatmap-labeled/plot.ts index 8417b578..6f85b305 100644 --- a/benchmarks/conformance/cases/heatmap-labeled/plot.ts +++ b/benchmarks/conformance/cases/heatmap-labeled/plot.ts @@ -1,4 +1,4 @@ -import { simpsons } from '@charts-poc/demo-data/simpsons' +import { simpsons } from '@tanstack/charts-data/simpsons' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/histogram/example.tsx b/benchmarks/conformance/cases/histogram/example.tsx index 3ab642a7..badabaf1 100644 --- a/benchmarks/conformance/cases/histogram/example.tsx +++ b/benchmarks/conformance/cases/histogram/example.tsx @@ -1,10 +1,10 @@ import { Chart } from '@tanstack/charts/react/tooltip' import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip' -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import { binX, defineChart, rect } from '@tanstack/charts' import { scaleLinear } from 'd3-scale' -import type { CarsRow } from '@charts-poc/demo-data/cars' +import type { CarsRow } from '@tanstack/charts-data/cars' type CarWithEconomy = CarsRow & { 'economy (mpg)': number } @@ -12,60 +12,54 @@ const completeCars = cars.filter( (row): row is CarWithEconomy => row['economy (mpg)'] !== null, ) const boundaries = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50] -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const bins = binX(completeCars.slice(input.revision * 8), { value: 'economy (mpg)', thresholds: boundaries, outputs: { count: { reduce: 'count' } }, }) - return defineChart({ - marks: [ - rect(bins, { - x1: 'x1', - x2: 'x2', - y1: () => 0, - y2: 'count', - fill: '#2563eb', - inset: 1, - }), - ], - x: { - scale: scaleLinear, - grid: true, - axis: { label: 'Fuel economy (mpg)' }, + return defineChart( + { + marks: [ + rect(bins, { + x1: 'x1', + x2: 'x2', + y1: () => 0, + y2: 'count', + fill: '#2563eb', + inset: 1, + }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: 'Fuel economy (mpg)' }, + }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Count' } }, }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Count' } }, - }) + { + keyboard: true, + tooltip: { + use: exampleTooltip, + ...{ + format: ({ datum }) => + `${datum.x1.toLocaleString('en-US')}–${datum.x2.toLocaleString( + 'en-US', + )} · ${datum.count.toLocaleString('en-US')} observations`, + }, + }, + }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Histogram of fuel economy' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: { - use: exampleTooltip, - ...{ - format: ({ datum }) => - `${datum.x1.toLocaleString('en-US')}–${datum.x2.toLocaleString( - 'en-US', - )} · ${datum.count.toLocaleString('en-US')} observations`, - }, - }, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/histogram/plot.ts b/benchmarks/conformance/cases/histogram/plot.ts index 06dd1048..c33c2ea6 100644 --- a/benchmarks/conformance/cases/histogram/plot.ts +++ b/benchmarks/conformance/cases/histogram/plot.ts @@ -1,4 +1,4 @@ -import { cars } from '@charts-poc/demo-data/cars' +import { cars } from '@tanstack/charts-data/cars' import * as Plot from '@observablehq/plot' import { mountObservablePlot } from '../../shared/mount' import type { ConformanceMount } from '../../types' diff --git a/benchmarks/conformance/cases/scatter-bubble/example.tsx b/benchmarks/conformance/cases/scatter-bubble/example.tsx index 71e8ad7d..db1bc47f 100644 --- a/benchmarks/conformance/cases/scatter-bubble/example.tsx +++ b/benchmarks/conformance/cases/scatter-bubble/example.tsx @@ -7,55 +7,50 @@ import { bubbleRows } from './model' const groupRange = ['#2563eb', '#f97316', '#10b981'] -export const definition = (input: ExampleOptions) => { +export const createExampleChart = (input: ChartOptions) => { const rows = bubbleRows(input.revision) - return defineChart({ - marks: [ - dot(rows, { - key: (row) => - `${row.species}:${row.island}:${row.culmen_length_mm}:${row.culmen_depth_mm}:${row.flipper_length_mm}:${row.body_mass_g}:${row.sex}`, - x: 'culmen_length_mm', - y: 'culmen_depth_mm', - color: 'species', - r: 'body_mass_g', - rScale: { - scale: () => scaleSqrt().range([3, 11]), - }, - fillOpacity: 0.78, - stroke: 'currentColor', - strokeOpacity: 0.28, - strokeWidth: 0.75, - }), - ], - x: { scale: scaleLinear, grid: true, axis: { label: 'Bill length (mm)' } }, - y: { scale: scaleLinear, grid: true, axis: { label: 'Bill depth (mm)' } }, - color: { - range: groupRange, - legend: colorLegend({ label: 'Species' }), + return defineChart( + { + marks: [ + dot(rows, { + key: (row) => + `${row.species}:${row.island}:${row.culmen_length_mm}:${row.culmen_depth_mm}:${row.flipper_length_mm}:${row.body_mass_g}:${row.sex}`, + x: 'culmen_length_mm', + y: 'culmen_depth_mm', + color: 'species', + r: 'body_mass_g', + rScale: { + scale: () => scaleSqrt().range([3, 11]), + }, + fillOpacity: 0.78, + stroke: 'currentColor', + strokeOpacity: 0.28, + strokeWidth: 0.75, + }), + ], + x: { + scale: scaleLinear, + grid: true, + axis: { label: 'Bill length (mm)' }, + }, + y: { scale: scaleLinear, grid: true, axis: { label: 'Bill depth (mm)' } }, + color: { + range: groupRange, + legend: colorLegend({ label: 'Species' }), + }, }, - }) + { keyboard: true, tooltip: exampleTooltip }, + ) } -export interface ExampleOptions { - width: number - height: number +export interface ChartOptions { revision: number - preview?: boolean } export const exampleAriaLabel = 'Bubble scatterplot' -export const createExampleChart = (options: ExampleOptions) => - defineChart(definition(options), { - keyboard: true, - tooltip: exampleTooltip, - }) - export const chart = createExampleChart({ - width: 640, - height: 480, revision: 0, - preview: false, }) export default function Example() { diff --git a/benchmarks/conformance/cases/scatter-bubble/model.ts b/benchmarks/conformance/cases/scatter-bubble/model.ts index 36cb39a0..b414e633 100644 --- a/benchmarks/conformance/cases/scatter-bubble/model.ts +++ b/benchmarks/conformance/cases/scatter-bubble/model.ts @@ -1,5 +1,5 @@ -import { penguins } from '@charts-poc/demo-data/penguins' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { penguins } from '@tanstack/charts-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export type BubblePenguin = PenguinsRow & { culmen_length_mm: number diff --git a/benchmarks/conformance/catalog-loader.test.ts b/benchmarks/conformance/catalog-loader.test.ts index 89bca21c..fea9f3f4 100644 --- a/benchmarks/conformance/catalog-loader.test.ts +++ b/benchmarks/conformance/catalog-loader.test.ts @@ -147,7 +147,7 @@ describe('loadCatalogSourceClosure', () => { './cases/example/tanstack.ts': async () => "import { rows } from './data'\nexport { rows }\n", './cases/example/data.ts': async () => - "import { aapl } from '@charts-poc/demo-data/aapl'\nimport type { AaplRow } from '@charts-poc/demo-data/aapl'\nexport const rows: readonly AaplRow[] = aapl\n", + "import { aapl } from '@tanstack/charts-data/aapl'\nimport type { AaplRow } from '@tanstack/charts-data/aapl'\nexport const rows: readonly AaplRow[] = aapl\n", } const closure = await loadCatalogSourceClosure( @@ -159,7 +159,7 @@ describe('loadCatalogSourceClosure', () => { expect(closure.datasets[0]).toMatchObject({ id: 'aapl', title: 'Apple daily stock prices', - specifier: '@charts-poc/demo-data/aapl', + specifier: '@tanstack/charts-data/aapl', records: 1_260, fields: ['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], observablePackage: '@observablehq/sample-datasets@1.0.1', @@ -237,13 +237,13 @@ describe('loadCatalogSourceClosure', () => { expect(closure.roles.fixture.files).toBe(1) }) - it('includes reusable shadcn chart primitives and their data', async () => { + it('includes reusable shared chart primitives and their data', async () => { const modules = { './cases/example/tanstack.ts': async () => - "import { example } from '../../shared/shadcn-catalog-tanstack'\nexport { example }\n", - './shared/shadcn-catalog-tanstack.ts': async () => - "import { rows } from './shadcn-catalog-data'\nexport const example = rows\n", - './shared/shadcn-catalog-data.ts': async () => + "import { example } from '../../shared/transforms/chart-primitives'\nexport { example }\n", + './shared/transforms/chart-primitives.ts': async () => + "import { rows } from '../fixtures/chart-data'\nexport const example = rows\n", + './shared/fixtures/chart-data.ts': async () => 'export const rows = [1, 2, 3]\n', } @@ -254,8 +254,8 @@ describe('loadCatalogSourceClosure', () => { expect(closure.files.map(({ kind, path }) => ({ kind, path }))).toEqual([ { kind: 'entry', path: 'tanstack.ts' }, - { kind: 'support', path: 'shared/shadcn-catalog-tanstack.ts' }, - { kind: 'fixture', path: 'shared/shadcn-catalog-data.ts' }, + { kind: 'support', path: 'shared/transforms/chart-primitives.ts' }, + { kind: 'fixture', path: 'shared/fixtures/chart-data.ts' }, ]) }) diff --git a/benchmarks/conformance/catalog-loader.ts b/benchmarks/conformance/catalog-loader.ts index 48da4f89..96f2caa5 100644 --- a/benchmarks/conformance/catalog-loader.ts +++ b/benchmarks/conformance/catalog-loader.ts @@ -1,9 +1,9 @@ -import { demoDatasetForSpecifier } from '@charts-poc/demo-data/metadata' +import { demoDatasetForSpecifier } from '@tanstack/charts-data/metadata' import type { ConformanceImplementationModule, ConformanceRenderer, } from './types' -import type { DemoDatasetMetadata } from '@charts-poc/demo-data/metadata' +import type { DemoDatasetMetadata } from '@tanstack/charts-data/metadata' export type CatalogModuleLoader = () => Promise export type CatalogModuleRegistry = Record diff --git a/benchmarks/conformance/previews/manifest.json b/benchmarks/conformance/previews/manifest.json index 9d507d04..74efb069 100644 --- a/benchmarks/conformance/previews/manifest.json +++ b/benchmarks/conformance/previews/manifest.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "width": 288, "height": 192, - "sourceHash": "c11021e138ff78d85026f99d2da56bf021ab198faa8db0a4844ea6b1028ae87f", + "sourceHash": "ae6e686c3f133511b6215cb1106fd70e45b90392781d5009d17ed24d2b37de79", "assets": [ { "id": "01-line-gaps", diff --git a/benchmarks/conformance/shared/fixtures/country-atlas.ts b/benchmarks/conformance/shared/fixtures/country-atlas.ts index 78cc9c3b..c4d9252e 100644 --- a/benchmarks/conformance/shared/fixtures/country-atlas.ts +++ b/benchmarks/conformance/shared/fixtures/country-atlas.ts @@ -1 +1 @@ -export * from '@charts-poc/demo-data/country-atlas' +export * from '@tanstack/charts-data/country-atlas' diff --git a/benchmarks/conformance/shared/fixtures/geography.test.ts b/benchmarks/conformance/shared/fixtures/geography.test.ts index 2e424863..6e27fff1 100644 --- a/benchmarks/conformance/shared/fixtures/geography.test.ts +++ b/benchmarks/conformance/shared/fixtures/geography.test.ts @@ -1,6 +1,6 @@ -import { beagle } from '@charts-poc/demo-data/beagle' -import { learningPoverty } from '@charts-poc/demo-data/learning-poverty' -import { usCountyUnemployment } from '@charts-poc/demo-data/us-county-unemployment' +import { beagle } from '@tanstack/charts-data/beagle' +import { learningPoverty } from '@tanstack/charts-data/learning-poverty' +import { usCountyUnemployment } from '@tanstack/charts-data/us-county-unemployment' import { describe, expect, it } from 'vitest' import { beagleRoute } from '../../cases/105-route-map/transform' import { @@ -11,7 +11,7 @@ import { detailedWorldLand, worldCountries, worldLand, -} from '@charts-poc/demo-data/country-atlas' +} from '@tanstack/charts-data/country-atlas' import { learningPovertyCountries, learningPovertyPointsByPopulation, diff --git a/benchmarks/conformance/shared/fixtures/simplify-geo.ts b/benchmarks/conformance/shared/fixtures/simplify-geo.ts index 716d8069..eb78c920 100644 --- a/benchmarks/conformance/shared/fixtures/simplify-geo.ts +++ b/benchmarks/conformance/shared/fixtures/simplify-geo.ts @@ -1 +1 @@ -export * from '@charts-poc/demo-data/simplify-geo' +export * from '@tanstack/charts-data/simplify-geo' diff --git a/benchmarks/conformance/shared/shadcn-catalog-data.ts b/benchmarks/conformance/shared/shadcn-catalog-data.ts index 016035c5..6443e35a 100644 --- a/benchmarks/conformance/shared/shadcn-catalog-data.ts +++ b/benchmarks/conformance/shared/shadcn-catalog-data.ts @@ -1 +1 @@ -export * from '@charts-poc/demo-data/shadcn' +export * from '@tanstack/charts-data/shadcn' diff --git a/benchmarks/conformance/shared/shadcn-catalog-tanstack.tsx b/benchmarks/conformance/shared/shadcn-catalog-tanstack.tsx deleted file mode 100644 index b1f162ec..00000000 --- a/benchmarks/conformance/shared/shadcn-catalog-tanstack.tsx +++ /dev/null @@ -1,2152 +0,0 @@ -import { useMemo, useRef, useState } from 'react' -import { - areaY, - barX, - barY, - d3Curve, - defineChart, - dot, - group, - isResponsiveChartDefinition, - lineY, - stack, - text, -} from '@tanstack/charts' -import { - angleGrid, - focusGroupAngle, - pie, - polar, - radialArc, - radialArea, - radialBarAngle, - radialDot, - radialGrid, - radialRule, - radialText, - type PieDatum, -} from '@tanstack/charts/polar' -import { Chart } from '@tanstack/charts/react/core' -import { RendererChart as TooltipChart } from '@tanstack/charts/react/tooltip' -import { tooltip } from '@tanstack/charts/tooltip' -import { scaleBand, scaleLinear, scalePoint } from 'd3-scale' -import { - curveLinear, - curveLinearClosed, - curveMonotoneX, - curveNatural, - curveStep, -} from 'd3-shape' -import { - getShadcnCatalogSpec, - shadcnActivities, - shadcnBrowsers, - shadcnColors, - shadcnMonths, - shadcnRadarDefault, - shadcnRadarFilled, - shadcnRadarLines, - shadcnRadarMultiple, - shadcnSeriesRows, - type ShadcnActivityDatum, - type ShadcnBrowserDatum, - type ShadcnCatalogSpec, - type ShadcnMonthDatum, - type ShadcnSeriesDatum, -} from './shadcn-catalog-data' -import { - ShadcnChartCard, - ShadcnTrendFooter, - shadcnChartMount, -} from './shadcn-chart-card' -import { createShadcnSpringRenderer } from './shadcn-motion' -import interactiveAreaData from '@charts-poc/demo-data/shadcn-area-interactive-data' -import { tanstackCase } from './mount' -import type { ChartPoint, ChartTooltipOptions } from '@tanstack/charts' -import type { ChartDefinition, ChartValue } from '@tanstack/charts' -import type { ConformanceInput } from '../types' - -const monthSeries = ['desktop', 'mobile', 'tablet'] as const -const twoSeries = ['desktop', 'mobile'] as const -const browserNames = shadcnBrowsers.map((row) => row.browser) -const activityNames = ['running', 'swimming'] as const -const horizontalVariants = new Set(['horizontal', 'label-custom', 'mixed']) -const interactiveAreaRows = interactiveAreaData as readonly { - date: string - desktop: number - mobile: number -}[] -const interactiveBarRows: readonly ShadcnMonthDatum[] = interactiveAreaRows.map( - (row) => ({ - month: row.date, - desktop: row.desktop, - mobile: row.mobile, - tablet: 0, - }), -) -const interactivePieRows: readonly ShadcnBrowserDatum[] = [ - { browser: 'january', visitors: 186 }, - { browser: 'february', visitors: 305 }, - { browser: 'march', visitors: 237 }, - { browser: 'april', visitors: 173 }, - { browser: 'may', visitors: 209 }, -] -const interactiveTimeRangeOptions = [ - { value: '90d', label: 'Last 3 months' }, - { value: '30d', label: 'Last 30 days' }, - { value: '7d', label: 'Last 7 days' }, -] as const - -type InteractiveTimeRange = '90d' | '30d' | '7d' -type InteractiveSeries = (typeof twoSeries)[number] - -interface ShadcnInteractiveState { - timeRange: InteractiveTimeRange - series: InteractiveSeries - month: string -} - -type ShadcnInteractiveDefinitionFactory< - TDatum, - TXValue extends ChartValue, - TYValue extends ChartValue, -> = (state: ShadcnInteractiveState) => ChartDefinition - -type ShadcnRadialCatalogDatum = - | ShadcnBrowserDatum - | PieDatum<{ id: string; value: number }> - | { id: string; angle: number; radius: number; text: string } - | { browser: string; visitors: number; ring: string } - | { - id: string - ring: string - start: number - end: number - fill: string - } - -export function createShadcnTanStackExample(name: string) { - const spec = getShadcnCatalogSpec(name) - if (spec.family === 'area') { - return createShadcnExample( - spec, - buildAreaDefinition(spec), - spec.variant === 'interactive' - ? ({ timeRange }) => buildInteractiveAreaDefinition(timeRange) - : undefined, - ) - } - if (spec.family === 'bar') { - return createShadcnExample< - ShadcnMonthDatum | ShadcnSeriesDatum | ShadcnBrowserDatum, - string | number, - string | number - >( - spec, - buildBarDefinition(spec), - spec.variant === 'interactive' - ? ({ series }) => buildInteractiveBarDefinition(series) - : undefined, - ) - } - if (spec.family === 'line') { - return createShadcnExample( - spec, - buildLineDefinition(spec), - spec.variant === 'interactive' - ? ({ series }) => buildInteractiveLineDefinition(series) - : undefined, - ) - } - if (spec.family === 'pie') { - return createShadcnExample( - spec, - buildPieDefinition(spec), - spec.variant === 'interactive' - ? ({ month }) => buildInteractivePieDefinition(month) - : undefined, - ) - } - if (spec.family === 'radar') { - return createShadcnExample(spec, buildRadarDefinition(spec)) - } - if (spec.family === 'radial') { - return createShadcnExample< - ShadcnRadialCatalogDatum, - number, - string | number - >(spec, buildRadialDefinition(spec)) - } - return createShadcnExample(spec, buildTooltipDefinition()) -} - -function createShadcnExample< - TDatum, - TXValue extends ChartValue, - TYValue extends ChartValue, ->( - spec: ShadcnCatalogSpec, - definition: ChartDefinition, - interactiveDefinitionFactory?: ShadcnInteractiveDefinitionFactory< - TDatum, - TXValue, - TYValue - >, -) { - const tooltipOptions: ChartTooltipOptions = { - className: 'sc-chart-tooltip', - anchor: - spec.family === 'tooltip' - ? (_points, context) => ({ - x: context.surface.width * 0.271, - y: context.surface.height * 0.554, - }) - : 'group-center', - placement: spec.family === 'tooltip' ? 'bottom-right' : 'auto', - offset: spec.family === 'tooltip' ? 0 : undefined, - sort: 'color-domain', - content: - spec.family === 'tooltip' - ? () => ({ rows: [] }) - : (points) => shadcnTooltipContent(spec, points), - } - const chartOptions = { - svgAnimation: false, - focus: - spec.family === 'radar' - ? focusGroupAngle - : spec.family === 'pie' || spec.family === 'radial' - ? 'nearest' - : 'group-x', - keyboard: spec.family !== 'radial', - tooltip: { use: tooltip, ...tooltipOptions }, - } as const - const applyChartOptions = ( - source: ChartDefinition, - ) => - isResponsiveChartDefinition(source) - ? defineChart(source, chartOptions) - : defineChart(source, chartOptions) - const interactiveDefinition = applyChartOptions(definition) - const catalogCase = tanstackCase( - () => interactiveDefinition, - `${spec.title} implemented with TanStack Charts`, - true, - { guides: spec.family !== 'pie', margin: true }, - ) - - function TanStackView({ input }: { input: ConformanceInput }) { - const seededTooltip = useRef(false) - const [timeRange, setTimeRange] = useState('90d') - const [activeSeries, setActiveSeries] = - useState('desktop') - const [activeMonth, setActiveMonth] = useState('january') - const chartDefinition = useMemo( - () => - interactiveDefinitionFactory - ? applyChartOptions( - interactiveDefinitionFactory({ - timeRange, - series: activeSeries, - month: activeMonth, - }), - ) - : interactiveDefinition, - [timeRange, activeSeries, activeMonth], - ) - const renderer = useMemo( - () => createShadcnSpringRenderer(), - [], - ) - const legend = spec.legend ? : undefined - const interactive = spec.variant === 'interactive' - const footer = - spec.family === 'tooltip' || - interactive || - (spec.family === 'pie' && spec.variant === 'legend') ? undefined : ( - - ) - const headerAction = - (spec.family === 'bar' || spec.family === 'line') && interactive ? ( - - ) : interactive ? ( - spec.family === 'area' ? ( - setTimeRange(value as InteractiveTimeRange)} - /> - ) : ( - ({ - value: row.browser, - label: titleCase(row.browser), - swatch: shadcnColors[index], - }))} - onChange={setActiveMonth} - /> - ) - ) : undefined - - return ( - - {({ width, height }) => - spec.family === 'tooltip' ? ( - { - if (seededTooltip.current) return - const point = scene.points.find( - (candidate) => - (candidate.datum as ShadcnActivityDatum).date === - '2024-07-16', - ) - if (!point) return - seededTooltip.current = true - interaction.setControlledFocus(point, { - source: 'programmatic', - }) - }} - renderTooltipBody={({ points }) => ( - []} - variant={spec.variant} - /> - )} - /> - ) : ( - - ) - } - - ) - } - - return { - definition: interactiveDefinition, - catalogCase, - mount: shadcnChartMount(TanStackView), - } -} - -function shadcnTooltipContent( - spec: ShadcnCatalogSpec, - points: readonly ChartPoint[], -) { - if (spec.family === 'pie' || spec.family === 'radial') { - const point = points.find((candidate) => browserMetric(candidate.datum)) - const metric = point && browserMetric(point.datum) - return metric - ? { - title: titleCase(metric.browser), - rows: [ - { - label: 'Visitors', - value: metric.visitors.toLocaleString('en-US'), - color: point.color, - }, - ], - } - : { rows: [] } - } - - return { - title: String(points[0]?.xValue ?? ''), - rows: points.map((point) => ({ - label: titleCase( - String( - point.group ?? - point.markId.replace( - /-?(bars|lines|areas|slices|values|radar)$/u, - '', - ), - ), - ), - value: Number(point.yValue ?? point.xValue ?? 0).toLocaleString('en-US'), - color: point.color, - })), - } -} - -function browserMetric(datum: unknown) { - if (!datum || typeof datum !== 'object') return undefined - const browser = Reflect.get(datum, 'browser') - const visitors = Reflect.get(datum, 'visitors') - return typeof browser === 'string' && - typeof visitors === 'number' && - Number.isFinite(visitors) - ? { browser, visitors } - : undefined -} - -function buildAreaDefinition(spec: ShadcnCatalogSpec) { - if (spec.variant === 'interactive') return buildInteractiveAreaDefinition() - const multi = - spec.variant === 'axes' || - spec.variant === 'gradient' || - spec.variant === 'icons' || - spec.variant === 'interactive' || - spec.variant === 'legend' || - spec.variant.startsWith('stacked') - const expanded = spec.variant === 'stacked-expand' - const expandedRows = shadcnMonths.flatMap((row, index) => [ - { - month: row.month, - series: 'other', - value: [45, 100, 150, 50, 100, 160][index]!, - }, - { month: row.month, series: 'mobile', value: row.mobile }, - { month: row.month, series: 'desktop', value: row.desktop }, - ]) - const rows = expanded - ? expandedRows - : multi - ? shadcnSeriesRows.filter((row) => row.series !== 'tablet') - : shadcnMonths - const curve = - spec.variant === 'linear' - ? curveLinear - : spec.variant === 'step' - ? curveStep - : curveNatural - const gradients = spec.variant === 'gradient' - - return defineChart({ - marks: [ - multi - ? areaY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ - order: expanded - ? ['other', 'mobile', 'desktop'] - : ['mobile', 'desktop'], - ...(expanded ? { offset: 'normalize' } : {}), - }), - curve: d3Curve(curve), - fill: expanded - ? (row) => - row.series === 'other' - ? `color-mix(in oklch, ${shadcnColors[2]} 10%, transparent)` - : `color-mix(in oklch, ${row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0]} 40%, transparent)` - : gradients - ? (row) => `url(#shadcn-area-${row.series})` - : undefined, - fillOpacity: expanded ? 1 : 0.4, - stroke: expanded - ? (row) => - row.series === 'other' - ? shadcnColors[2] - : row.series === 'mobile' - ? shadcnColors[1] - : shadcnColors[0] - : (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1.5, - }) - : areaY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-area', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - fill: shadcnColors[0], - fillOpacity: 0.4, - stroke: shadcnColors[0], - strokeWidth: 1.5, - }), - ], - x: shadcnPointXAxis(), - y: { - scale: - spec.variant === 'axes' - ? scaleLinear().domain([0, 600]) - : expanded - ? scaleLinear().domain([0, 1]) - : scaleLinear, - grid: true, - axis: - spec.variant === 'axes' - ? { line: false, ticks: { size: 0, values: [0, 300, 600] } } - : { line: false, ticks: false, tickLabels: false }, - }, - color: { - domain: expanded ? ['other', 'mobile', 'desktop'] : monthSeries, - range: expanded - ? [shadcnColors[2], shadcnColors[1], shadcnColors[0]] - : shadcnColors.slice(0, 3), - }, - gradients: gradients - ? twoSeries.map((series, index) => ({ - id: `shadcn-area-${series}`, - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: shadcnColors[index], opacity: 0.08 }, - { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, - ], - })) - : undefined, - margin: - spec.variant === 'axes' - ? { top: 12, right: 12, bottom: 28, left: 40 } - : { top: 5, right: 12, bottom: 35, left: 12 }, - theme: shadcnTheme(), - }) -} - -function buildInteractiveAreaDefinition( - timeRange: InteractiveTimeRange = '90d', -) { - const filteredRows = filterInteractiveAreaRows(timeRange) - const rows: ShadcnSeriesDatum[] = filteredRows.flatMap((row) => [ - { month: row.date, series: 'mobile', value: row.mobile }, - { month: row.date, series: 'desktop', value: row.desktop }, - ]) - return defineChart(({ width }) => ({ - marks: [ - areaY(rows, { - id: 'visitor-areas', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ order: ['mobile', 'desktop'] }), - curve: d3Curve(curveNatural), - fill: (row) => `url(#shadcn-interactive-${row.series})`, - fillOpacity: 1, - stroke: (row) => - row.series === 'mobile' ? shadcnColors[1] : shadcnColors[0], - strokeWidth: 1, - }), - ], - x: { - scale: scalePoint, - axis: { - line: false, - ticks: { - values: interactiveDateTicks(timeRange), - size: 0, - padding: 10, - format: formatMonthDay, - }, - }, - }, - y: { - scale: scaleLinear().domain([0, 1200]), - grid: true, - axis: { - line: false, - ticks: { values: [0, 300, 600, 900, 1200], size: 0 }, - tickLabels: false, - }, - }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - gradients: twoSeries.map((series, index) => ({ - id: `shadcn-interactive-${series}`, - x1: 0, - y1: 1, - x2: 0, - y2: 0, - stops: [ - { offset: 0.05, color: shadcnColors[index], opacity: 0.1 }, - { offset: 0.95, color: shadcnColors[index], opacity: 0.8 }, - ], - })), - margin: { - top: 32, - right: width < 400 ? 14 : 5, - bottom: 35, - left: 5, - }, - theme: shadcnTheme(), - })) -} - -function buildBarDefinition(spec: ShadcnCatalogSpec) { - if (spec.variant === 'interactive') { - return buildInteractiveBarDefinition() - } - if (spec.variant === 'active') { - const rows = shadcnBrowsers.map((row) => - row.browser === 'chrome' - ? { ...row, visitors: 187 } - : row.browser === 'firefox' - ? { ...row, visitors: 275 } - : row, - ) - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'browser', - y: 'visitors', - color: 'browser', - fill: (row) => - row.browser === 'firefox' - ? `color-mix(in srgb, ${shadcnColors[2]} 80%, transparent)` - : shadcnColors[browserNames.indexOf(row.browser)]!, - stroke: (row) => - row.browser === 'firefox' ? shadcnColors[2] : 'none', - strokeWidth: 2, - strokeDasharray: (row) => - row.browser === 'firefox' ? '4 4' : 'none', - radius: 8, - }), - ], - x: shadcnBrowserXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: browserNames, range: shadcnColors }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) - } - if (spec.variant === 'mixed') { - return defineChart({ - marks: [ - barX(shadcnBrowsers, { - id: 'visitor-bars', - x: 'visitors', - y: 'browser', - color: 'browser', - radius: 5, - }), - ], - x: { scale: scaleLinear, axis: false }, - y: shadcnBrowserYAxis(), - color: { domain: browserNames, range: shadcnColors }, - margin: { top: 5, right: 5, bottom: 5, left: 60 }, - theme: shadcnTheme(), - }) - } - if (spec.variant === 'label-custom') { - return defineChart({ - marks: [ - barX(shadcnMonths, { - id: 'visitor-bars', - x: 'desktop', - y: 'month', - fill: shadcnColors[1], - radius: 4, - }), - text(shadcnMonths, { - id: 'month-labels', - x: () => 0, - y: 'month', - text: 'month', - dx: 8, - anchor: 'start', - fill: 'var(--background)', - fontSize: 12, - }), - text(shadcnMonths, { - id: 'visitor-labels', - x: 'desktop', - y: 'month', - text: (row) => row.desktop.toLocaleString('en-US'), - dx: 8, - anchor: 'start', - fill: 'var(--foreground)', - fontSize: 12, - }), - ], - x: { scale: scaleLinear, grid: true, axis: false }, - y: { - scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), - axis: false, - }, - margin: { top: 5, right: 36, bottom: 5, left: 0 }, - theme: shadcnTheme(), - }) - } - if (spec.variant === 'multiple') { - return groupedBarDefinition() - } - if (spec.variant === 'stacked') { - const rows = shadcnSeriesRows.filter((row) => row.series !== 'tablet') - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: stack({ order: twoSeries }), - radius: 4, - }), - ], - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) - } - - const negativeRows = [ - { month: 'January', desktop: 186, mobile: 0, tablet: 0 }, - { month: 'February', desktop: 205, mobile: 0, tablet: 0 }, - { month: 'March', desktop: -207, mobile: 0, tablet: 0 }, - { month: 'April', desktop: 173, mobile: 0, tablet: 0 }, - { month: 'May', desktop: -209, mobile: 0, tablet: 0 }, - { month: 'June', desktop: 214, mobile: 0, tablet: 0 }, - ] - const rows = spec.variant === 'negative' ? negativeRows : shadcnMonths - const horizontal = horizontalVariants.has(spec.variant) - const labels = - spec.variant === 'label' || - spec.variant === 'label-custom' || - spec.variant === 'negative' - const marks = horizontal - ? [ - barX(rows, { - id: 'visitor-bars', - x: 'desktop', - y: 'month', - fill: shadcnColors[0], - radius: 5, - }), - ...(labels - ? [ - text(rows, { - id: 'visitor-labels', - x: 'desktop', - y: 'month', - text: (row) => row.desktop.toLocaleString('en-US'), - dx: -7, - anchor: 'end', - fill: 'var(--background)', - fontSize: 11, - fontWeight: 600, - }), - ] - : []), - ] - : [ - barY(rows, { - id: 'visitor-bars', - x: 'month', - y: 'desktop', - fill: (row) => - spec.variant === 'negative' && row.desktop < 0 - ? shadcnColors[1] - : shadcnColors[0], - radius: spec.variant === 'negative' ? 0 : 8, - }), - ...(labels - ? [ - text(rows, { - id: 'visitor-labels', - x: 'month', - y: 'desktop', - text: (row) => row.desktop.toLocaleString('en-US'), - ...(spec.variant === 'negative' - ? { - text: (row: ShadcnMonthDatum) => row.month, - dy: (row: ShadcnMonthDatum) => - row.desktop < 0 ? 14 : -10, - fill: shadcnColors[0], - fontSize: 12, - } - : { - dy: -12, - fill: 'var(--foreground)', - fontSize: 12, - }), - }), - ] - : []), - ] - - return defineChart({ - marks, - x: horizontal - ? { scale: scaleLinear, axis: false } - : spec.variant === 'negative' - ? { - scale: () => - scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: false, - } - : shadcnXAxis(), - y: horizontal - ? { - scale: () => - scaleBand().paddingInner(0.18).paddingOuter(0.08), - axis: { line: false, ticks: { size: 0 } }, - } - : { scale: scaleLinear, grid: true, axis: false }, - margin: horizontal - ? { top: 5, right: 5, bottom: 5, left: 72 } - : spec.variant === 'negative' - ? { top: 24, right: 5, bottom: 24, left: 5 } - : { top: labels ? 24 : 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) -} - -function buildInteractiveBarDefinition( - activeSeries: InteractiveSeries = 'desktop', -) { - return defineChart({ - marks: [ - barY(interactiveBarRows, { - id: 'daily-bars', - x: 'month', - y: (row) => row[activeSeries], - z: () => activeSeries, - key: 'month', - fill: activeSeries === 'desktop' ? shadcnColors[1] : shadcnColors[0], - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { - values: [ - '2024-04-01', - '2024-04-11', - '2024-04-22', - '2024-05-03', - '2024-05-14', - '2024-05-26', - '2024-06-06', - '2024-06-17', - '2024-06-29', - ], - size: 0, - padding: 10, - format: formatMonthDay, - }, - }, - }, - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 12, bottom: 25, left: 12 }, - theme: shadcnTheme(), - }) -} - -function groupedBarDefinition() { - const rows = shadcnSeriesRows.filter( - (row) => row.series === 'desktop' || row.series === 'mobile', - ) - const groupScale = scaleBand() - .domain(twoSeries) - .paddingInner(0.08) - .paddingOuter(0) - return defineChart({ - marks: [ - barY(rows, { - id: 'visitor-bars', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - layout: group({ scale: groupScale }), - radius: 4, - }), - ], - x: shadcnXAxis(), - y: { scale: scaleLinear, grid: true, axis: false }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { top: 5, right: 5, bottom: 35, left: 5 }, - theme: shadcnTheme(), - }) -} - -function buildLineDefinition(spec: ShadcnCatalogSpec) { - if (spec.variant === 'interactive') return buildInteractiveLineDefinition() - const multiple = spec.variant === 'multiple' - const browserVariant = - spec.variant === 'dots-colors' || spec.variant === 'label-custom' - const rows = multiple - ? shadcnSeriesRows.filter((row) => row.series !== 'tablet') - : browserVariant - ? shadcnBrowsers - : shadcnMonths - const curve = - spec.variant === 'linear' - ? curveLinear - : spec.variant === 'step' - ? curveStep - : multiple - ? curveMonotoneX - : curveNatural - const dots = spec.variant.includes('dots') - const labels = spec.variant.includes('label') - const dotMarks = !dots - ? [] - : browserVariant - ? [ - dot(shadcnBrowsers, { - id: 'visitor-dots', - x: 'browser', - y: 'visitors', - color: 'browser', - r: 5, - }), - ] - : [ - ...(spec.variant === 'dots-custom' - ? [ - text(shadcnMonths, { - id: 'visitor-dot-stems', - x: 'month', - y: 'desktop', - text: () => '│', - fill: shadcnColors[0], - fontSize: 24, - }), - ] - : []), - dot(shadcnMonths, { - id: 'visitor-dots', - x: 'month', - y: 'desktop', - r: spec.variant === 'dots-custom' ? 5 : 4, - fill: - spec.variant === 'dots-custom' - ? 'var(--background)' - : shadcnColors[0], - stroke: shadcnColors[0], - strokeWidth: spec.variant === 'dots-custom' ? 2 : 1, - }), - ] - const labelMarks = !labels - ? [] - : browserVariant - ? [ - text(shadcnBrowsers, { - id: 'visitor-labels', - x: 'browser', - y: 'visitors', - text: (row) => titleCase(row.browser), - dy: -12, - fill: 'var(--foreground)', - fontSize: 12, - }), - ] - : [ - text(shadcnMonths, { - id: 'visitor-labels', - x: 'month', - y: 'desktop', - text: (row) => row.desktop.toLocaleString('en-US'), - dy: -12, - fill: 'var(--foreground)', - fontSize: 12, - }), - ] - return defineChart(({ width }) => ({ - marks: [ - multiple - ? lineY(rows as readonly ShadcnSeriesDatum[], { - id: 'visitor-lines', - x: 'month', - y: 'value', - z: 'series', - color: 'series', - key: (row) => `${row.month}:${row.series}`, - curve: d3Curve(curve), - strokeWidth: 2, - }) - : browserVariant - ? lineY(rows as readonly ShadcnBrowserDatum[], { - id: 'visitor-line', - x: 'browser', - y: 'visitors', - curve: d3Curve(curve), - stroke: shadcnColors[1], - strokeWidth: 2, - }) - : lineY(rows as readonly ShadcnMonthDatum[], { - id: 'visitor-line', - x: 'month', - y: 'desktop', - curve: d3Curve(curve), - stroke: shadcnColors[0], - strokeWidth: 2, - }), - ...dotMarks, - ...labelMarks, - ], - x: browserVariant ? { scale: scalePoint, axis: false } : shadcnPointXAxis(), - y: { - scale: scaleLinear().domain([0, browserVariant ? 300 : 320]), - grid: true, - axis: { - line: false, - ticks: { - values: browserVariant - ? [0, 75, 150, 225, 300] - : [0, 80, 160, 240, 320], - size: 0, - }, - tickLabels: false, - }, - }, - color: { - domain: browserVariant ? browserNames : twoSeries, - range: browserVariant ? shadcnColors : shadcnColors.slice(0, 2), - }, - margin: browserVariant - ? { top: 24, right: 24, bottom: 5, left: 24 } - : { - top: - spec.variant === 'dots-custom' && width < 400 - ? 16 - : labels - ? 24 - : 8, - right: 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) -} - -function buildInteractiveLineDefinition( - activeSeries: InteractiveSeries = 'desktop', -) { - return defineChart(({ width }) => ({ - marks: [ - lineY(interactiveBarRows, { - id: 'daily-line', - x: 'month', - y: (row) => row[activeSeries], - z: () => activeSeries, - key: 'month', - curve: d3Curve(curveMonotoneX), - stroke: activeSeries === 'desktop' ? shadcnColors[0] : shadcnColors[1], - strokeWidth: 2, - }), - ], - x: { - scale: scalePoint, - axis: { - line: false, - ticks: { - values: [ - '2024-04-10', - '2024-04-21', - '2024-05-02', - '2024-05-13', - '2024-05-25', - '2024-06-05', - '2024-06-16', - '2024-06-29', - ], - size: 0, - padding: 10, - format: formatMonthDay, - }, - }, - }, - y: { - scale: scaleLinear().domain([0, 600]), - grid: true, - axis: { - line: false, - ticks: { values: [0, 150, 300, 450, 600], size: 0 }, - tickLabels: false, - }, - }, - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: { - top: 5, - right: width < 400 ? 24 : 12, - bottom: 35, - left: 12, - }, - theme: shadcnTheme(), - })) -} - -function buildPieDefinition(spec: ShadcnCatalogSpec) { - if (spec.variant === 'interactive') return buildInteractivePieDefinition() - if (spec.variant === 'stacked') return buildStackedPieDefinition() - const arcs = pie(shadcnBrowsers, { - value: 'visitors', - startAngle: Math.PI / 2, - endAngle: (-Math.PI * 3) / 2, - }) - const donut = spec.variant.includes('donut') - const active = spec.variant === 'donut-active' - const centerText = spec.variant === 'donut-text' - const labels = spec.variant.includes('label') - const externalLabels = spec.variant === 'label' - const customLabels = spec.variant === 'label-custom' - const labelList = spec.variant === 'label-list' - const separator = spec.variant === 'separator-none' ? 0 : active ? 5 : 1 - const marks = [ - radialArc(arcs, { - id: 'browser-slices', - key: 'browser', - innerRadius: donut ? 60 : undefined, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: separator, - }), - ...(active - ? [ - radialArc(arcs.slice(0, 1), { - id: 'active-browser-slice', - key: 'browser', - innerRadius: 60, - outerRadius: ({ radius }) => radius + 10, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 5, - }), - ] - : []), - ...(externalLabels - ? [ - radialRule(arcs, { - id: 'browser-leaders', - angle: 'angle', - radius1: 1, - radius2: 1, - radius2Offset: 14, - key: 'browser', - stroke: 'var(--border)', - }), - ] - : []), - ...(labels - ? [ - radialText(arcs, { - id: 'browser-labels', - angle: 'angle', - radius: externalLabels || customLabels ? 1 : 0.68, - radiusOffset: externalLabels || customLabels ? 17 : 0, - text: (row) => - labelList - ? titleCase(row.browser) - : row.visitors.toLocaleString('en-US'), - key: 'browser', - anchor: externalLabels || customLabels ? 'outside' : 'middle', - fill: - externalLabels || customLabels - ? 'var(--foreground)' - : 'var(--background)', - fontSize: 12, - fontWeight: labelList ? 400 : undefined, - }), - ] - : []), - ...(centerText - ? [ - radialText([{ id: 'total', angle: 0, radius: 0, text: '1,125' }], { - id: 'visitor-total', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: -5, - fill: 'var(--foreground)', - fontSize: 30, - fontWeight: 700, - }), - radialText([{ id: 'label', angle: 0, radius: 0, text: 'Visitors' }], { - id: 'visitor-label', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: 19, - fill: 'var(--muted-foreground)', - fontSize: 14, - }), - ] - : []), - ] - - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks, - }), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) -} - -function buildStackedPieDefinition() { - const desktopRows = [186, 305, 237, 173, 209].map((visitors, index) => ({ - browser: ['january', 'february', 'march', 'april', 'may'][index]!, - visitors, - })) - const mobileRows = [80, 200, 120, 190, 130].map((visitors, index) => ({ - browser: ['january', 'february', 'march', 'april', 'may'][index]!, - visitors, - })) - const desktopArcs = pie(desktopRows, { - value: 'visitors', - startAngle: Math.PI / 2, - endAngle: (-Math.PI * 3) / 2, - }) - const mobileArcs = pie(mobileRows, { - value: 'visitors', - startAngle: Math.PI / 2, - endAngle: (-Math.PI * 3) / 2, - }) - const months = desktopRows.map((row) => row.browser) - return defineChart({ - marks: [ - polar({ - radiusRatio: 1, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(desktopArcs, { - id: 'desktop-slices', - key: 'browser', - outerRadius: 60, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - radialArc(mobileArcs, { - id: 'mobile-slices', - key: 'browser', - innerRadius: 70, - outerRadius: 90, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - ], - }), - ], - color: { domain: months, range: shadcnColors }, - margin: 0, - }) -} - -function buildInteractivePieDefinition(activeMonth = 'january') { - const arcs = pie(interactivePieRows, { - value: 'visitors', - startAngle: Math.PI / 2, - endAngle: (-Math.PI * 3) / 2, - }) - const activeIndex = Math.max( - 0, - interactivePieRows.findIndex((row) => row.browser === activeMonth), - ) - const activeRow = interactivePieRows[activeIndex]! - const active = arcs.filter((row) => row.browser === activeRow.browser) - const activeColor = shadcnColors[activeIndex]! - return defineChart({ - marks: [ - polar({ - radiusRatio: 0.78, - angle: { scale: scaleLinear().domain([0, Math.PI * 2]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialArc(arcs, { - id: 'month-slices', - key: 'browser', - innerRadius: 60, - color: 'browser', - stroke: 'var(--background)', - strokeWidth: 1, - }), - radialArc(active, { - id: 'active-month', - key: 'browser', - innerRadius: 60, - outerRadius: ({ radius }) => radius + 10, - fill: activeColor, - stroke: 'var(--background)', - strokeWidth: 5, - }), - radialArc(active, { - id: 'active-month-ring', - key: 'browser', - innerRadius: ({ radius }) => radius + 12, - outerRadius: ({ radius }) => radius + 25, - fill: activeColor, - stroke: 'var(--background)', - strokeWidth: 3, - }), - radialText( - [ - { - id: 'total', - angle: 0, - radius: 0, - text: String(activeRow.visitors), - }, - ], - { - id: 'active-total', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: -5, - fill: 'var(--foreground)', - fontSize: 30, - fontWeight: 700, - }, - ), - radialText([{ id: 'label', angle: 0, radius: 0, text: 'Visitors' }], { - id: 'active-label', - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: 20, - fill: 'var(--muted-foreground)', - fontSize: 12, - }), - ], - }), - ], - color: { - domain: interactivePieRows.map((row) => row.browser), - range: shadcnColors, - }, - margin: 0, - }) -} - -function buildRadarDefinition(spec: ShadcnCatalogSpec) { - const circle = spec.variant.includes('circle') - const noGrid = spec.variant === 'grid-none' - const noSpokes = - spec.variant === 'grid-circle-no-lines' || - spec.variant === 'grid-custom' || - spec.variant === 'lines-only' || - noGrid - const multiple = - spec.variant === 'multiple' || - spec.variant === 'legend' || - spec.variant === 'icons' || - spec.variant === 'label-custom' || - spec.variant === 'radius' || - spec.variant === 'lines-only' - const filledGrid = spec.variant.includes('fill') - const rows = - spec.variant === 'lines-only' - ? shadcnRadarLines - : filledGrid - ? shadcnRadarFilled - : spec.variant === 'grid-circle-no-lines' - ? shadcnRadarDefault.map((row) => - row.month === 'April' ? { ...row, desktop: 203 } : row, - ) - : multiple - ? shadcnRadarMultiple - : shadcnRadarDefault - const months = rows.map((row) => row.month) - const radiusMax = spec.variant === 'lines-only' ? 220 : filledGrid ? 300 : 320 - const gridValues = Array.from({ length: 4 }, (_, index) => - Math.round((radiusMax * (index + 1)) / 4), - ) - const customLabels = spec.variant === 'label-custom' - const radiusAxis = spec.variant === 'radius' - const dots = - spec.variant === 'dots' || - spec.variant === 'grid-circle' || - spec.variant === 'grid-circle-no-lines' || - noGrid - const guides = [ - ...(!noGrid - ? [ - radialGrid({ - values: - spec.variant === 'grid-custom' - ? [Math.round(radiusMax * 0.947)] - : radiusAxis - ? [0, 80, 160, 240, 320] - : gridValues, - shape: circle ? 'circle' : 'polygon', - stroke: filledGrid ? 'transparent' : 'var(--border)', - strokeOpacity: filledGrid ? 0 : 1, - ...(filledGrid ? { fill: shadcnColors[0], fillOpacity: 0.2 } : {}), - ...(radiusAxis - ? { - labels: true, - labelAngle: Math.PI / 6, - labelFill: 'var(--foreground)', - labelFontSize: 12, - labelRotate: 30, - labelOffset: 1, - } - : {}), - }), - ] - : []), - ...(!radiusAxis - ? [ - angleGrid({ - values: months, - labels: !customLabels, - labelOffset: 10, - labelFill: 'var(--muted-foreground)', - labelFontSize: 12, - stroke: noSpokes || filledGrid ? 'transparent' : 'var(--border)', - strokeOpacity: filledGrid ? 0 : 1, - }), - ] - : []), - ] - const chartSpec = (radiusRatio: number) => ({ - marks: [ - polar({ - radiusRatio, - angle: { scale: scalePoint().domain(months), wrap: true }, - radius: { scale: scaleLinear().domain([0, radiusMax]) }, - guides, - marks: [ - radialArea(rows, { - id: 'desktop-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - curve: curveLinearClosed, - fill: shadcnColors[0], - fillOpacity: - spec.variant === 'lines-only' ? 0 : filledGrid ? 0.5 : 0.6, - stroke: shadcnColors[0], - strokeOpacity: filledGrid ? 0 : 1, - strokeWidth: spec.variant === 'lines-only' ? 2 : 1, - }), - ...(multiple - ? [ - radialArea(rows, { - id: 'mobile-radar', - className: 'ts-chart__radar', - angle: 'month', - radius: 'mobile', - key: 'month', - z: () => 'mobile', - curve: curveLinearClosed, - fill: shadcnColors[1], - fillOpacity: spec.variant === 'lines-only' ? 0 : 1, - stroke: shadcnColors[1], - strokeWidth: spec.variant === 'lines-only' ? 2 : 1, - }), - ] - : []), - ...(dots - ? [ - radialDot(rows, { - id: 'radar-dots', - angle: 'month', - radius: 'desktop', - key: 'month', - z: () => 'desktop', - r: 4, - fill: shadcnColors[0], - }), - ] - : []), - ...(customLabels - ? [ - radialText(rows, { - id: 'radar-values', - angle: 'month', - radius: () => radiusMax, - key: 'month', - z: () => 'desktop', - text: (row) => `${row.desktop}/${row.mobile ?? 0}`, - anchor: 'outside', - radiusOffset: 15, - dy: -7, - fill: 'var(--foreground)', - fontSize: 12, - fontWeight: 500, - }), - radialText(rows, { - id: 'radar-months', - angle: 'month', - radius: () => radiusMax, - key: 'month', - z: () => 'desktop', - text: 'month', - anchor: 'outside', - radiusOffset: 15, - dy: 10, - fill: 'var(--muted-foreground)', - fontSize: 12, - }), - ] - : []), - ], - }), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) - return customLabels - ? defineChart(({ height }) => chartSpec(height < 220 ? 0.64 : 0.76)) - : defineChart(chartSpec(0.76)) -} - -function buildRadialDefinition(spec: ShadcnCatalogSpec) { - if (spec.variant === 'stacked') return buildStackedRadialDefinition() - if (spec.variant === 'shape') { - return buildSingleRadialDefinition({ - id: 'shape', - visitors: 1_260, - endDegrees: 100, - innerRadius: 65, - outerRadius: 95, - backgroundInnerRadius: 74, - backgroundOuterRadius: 86, - cornerRadius: 0, - total: '1,260', - }) - } - if (spec.variant === 'text') { - return buildSingleRadialDefinition({ - id: 'text', - visitors: 200, - endDegrees: 250, - innerRadius: 80, - outerRadius: 90, - backgroundInnerRadius: 80, - backgroundOuterRadius: 90, - cornerRadius: 10, - total: '200', - }) - } - - const label = spec.variant === 'label' - const grid = spec.variant === 'grid' - const startAngle = rechartsPolarAngle(label ? -90 : 0) - const endAngle = rechartsPolarAngle(label ? 380 : 360) - const backgroundRows = shadcnBrowsers.map((row) => ({ - ...row, - background: 300, - })) - const chartSpec = (radiusFactor: number) => ({ - marks: [ - polar({ - radiusRatio: grid ? 0.8 : 1, - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleBand().domain(browserNames).paddingInner(0.2), - range: [ - 30 * radiusFactor, - (label ? 110 : grid ? 100 : 110) * radiusFactor, - ], - }, - guides: grid - ? [ - radialGrid({ - values: browserNames, - shape: 'circle', - stroke: 'var(--border)', - }), - angleGrid({ - values: Array.from({ length: 12 }, (_, index) => index * 25), - labels: false, - stroke: 'var(--border)', - }), - ] - : [], - marks: [ - ...(!grid - ? [ - radialBarAngle(backgroundRows, { - id: 'radial-backgrounds', - angle: 'background', - radius: 'browser', - key: 'browser', - fill: 'var(--muted)', - }), - ] - : []), - radialBarAngle(shadcnBrowsers, { - id: 'radial-values', - angle: 'visitors', - radius: 'browser', - key: 'browser', - fill: (row) => shadcnColors[browserNames.indexOf(row.browser)]!, - }), - ], - }), - ...(label - ? [ - polar({ - startAngle, - endAngle, - angle: { scale: scaleLinear().domain([0, 300]) }, - radius: { - scale: scaleLinear().domain([0, 110]), - range: [0, 110 * radiusFactor], - }, - marks: [ - radialText( - shadcnBrowsers.map((row, index) => ({ - ...row, - angle: 10, - labelRadius: 38 + index * 16, - })), - { - id: 'radial-labels', - angle: 'angle', - radius: 'labelRadius', - key: 'browser', - text: (row) => titleCase(row.browser), - fill: 'white', - fontSize: 11, - rotate: -25, - }, - ), - ], - }), - ] - : []), - ], - color: { domain: browserNames, range: shadcnColors }, - margin: 0, - }) - return label - ? defineChart(({ height }) => chartSpec(height < 220 ? 0.8 : 1)) - : defineChart(chartSpec(1)) -} - -function buildSingleRadialDefinition(options: { - id: string - visitors: number - endDegrees: number - innerRadius: number - outerRadius: number - backgroundInnerRadius: number - backgroundOuterRadius: number - cornerRadius: number - total: string -}) { - const rows = [ - { browser: 'safari', visitors: options.visitors, ring: 'visitors' }, - ] - const background = pie([{ id: 'background', value: 1 }], { value: 'value' }) - return defineChart({ - marks: [ - polar({ - marks: [ - radialArc(background, { - id: `${options.id}-background`, - key: 'id', - innerRadius: options.backgroundInnerRadius, - outerRadius: options.backgroundOuterRadius, - fill: 'var(--muted)', - }), - ], - }), - polar({ - startAngle: rechartsPolarAngle(0), - endAngle: rechartsPolarAngle(options.endDegrees), - angle: { scale: scaleLinear().domain([0, options.visitors]) }, - radius: { - scale: scaleBand().domain(['visitors']), - range: [options.innerRadius, options.outerRadius], - }, - marks: [ - radialBarAngle(rows, { - id: `${options.id}-value`, - angle: 'visitors', - radius: 'ring', - key: 'browser', - fill: shadcnColors[1], - cornerRadius: options.cornerRadius, - }), - ], - }), - radialCenterLabels(options.total, 36, 0, 24), - ], - margin: 0, - }) -} - -function buildStackedRadialDefinition() { - const rows = [ - { - id: 'mobile', - ring: 'visitors', - start: 0, - end: 570, - fill: shadcnColors[1], - }, - { - id: 'desktop', - ring: 'visitors', - start: 570, - end: 1_260, - fill: shadcnColors[0], - }, - ] - return defineChart({ - marks: [ - polar({ - startAngle: rechartsPolarAngle(0), - endAngle: rechartsPolarAngle(180), - angle: { scale: scaleLinear().domain([0, 1_260]) }, - radius: { - scale: scaleBand().domain(['visitors']), - range: [80, 110], - }, - marks: [ - radialBarAngle(rows, { - id: 'stacked-values', - angle1: 'start', - angle2: 'end', - angle: 'end', - radius: 'ring', - key: 'id', - fill: (row) => row.fill, - cornerRadius: 5, - stroke: 'transparent', - strokeWidth: 2, - }), - ], - }), - radialCenterLabels('1,830', 24, -16, 4), - ], - color: { domain: twoSeries, range: shadcnColors.slice(0, 2) }, - margin: 0, - }) -} - -function radialCenterLabels( - total: string, - fontSize: number, - totalDy: number, - labelDy: number, -) { - return polar({ - angle: { scale: scaleLinear().domain([0, 1]) }, - radius: { scale: scaleLinear().domain([0, 1]) }, - marks: [ - radialText([{ id: 'total', angle: 0, radius: 0, text: total }], { - id: `radial-total-${total}`, - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: totalDy, - fill: 'var(--foreground)', - fontSize, - fontWeight: 700, - }), - radialText([{ id: 'label', angle: 0, radius: 0, text: 'Visitors' }], { - id: `radial-label-${total}`, - angle: 'angle', - radius: 'radius', - key: 'id', - text: 'text', - dy: labelDy, - fill: 'var(--muted-foreground)', - fontSize: 14, - }), - ], - }) -} - -function rechartsPolarAngle(degrees: number) { - return ((90 - degrees) * Math.PI) / 180 -} - -function buildTooltipDefinition() { - return defineChart({ - marks: [ - barY(shadcnActivities, { - id: 'activity-bars', - x: 'date', - y: 'value', - z: 'activity', - color: 'activity', - key: (row) => `${row.date}:${row.activity}`, - layout: stack({ order: activityNames }), - radius: 4, - }), - ], - x: { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: formatWeekday }, - }, - }, - y: { scale: scaleLinear().domain([0, 1_000]), axis: false }, - color: { domain: activityNames, range: shadcnColors.slice(0, 2) }, - margin: { top: 0, right: 7, bottom: 32, left: 7 }, - theme: shadcnTheme(), - }) -} - -function ShadcnLegend({ spec }: { spec: ShadcnCatalogSpec }) { - const labels = - spec.family === 'pie' || spec.family === 'radial' ? browserNames : twoSeries - const items = labels.map((label, index) => ( - - {spec.variant === 'icons' ? ( - - - - ) : ( - - )} - {label.charAt(0).toUpperCase() + label.slice(1)} - - )) - return spec.family === 'pie' && spec.variant === 'legend' ? ( -
{items}
- ) : ( - <>{items} - ) -} - -function ShadcnTooltipBody({ - variant, - points, -}: { - variant: string - points: readonly ChartPoint[] -}) { - const ordered = [...points].sort( - (left, right) => - activityNames.indexOf(left.datum.activity) - - activityNames.indexOf(right.datum.activity), - ) - const noLabel = - variant === 'label-none' || - variant === 'formatter' || - variant === 'icons' || - variant === 'advanced' - const noIndicator = - variant === 'indicator-none' || - variant === 'label-none' || - variant === 'formatter' || - variant === 'icons' - const lineIndicator = variant === 'indicator-line' - const formatted = variant === 'formatter' || variant === 'advanced' - const label = - variant === 'label-formatter' - ? 'July 15, 2024' - : variant === 'label-custom' - ? 'Activities' - : '2024-07-16' - return ( -
- {noLabel ? null : {label}} - {ordered.map((point, index) => ( -
- {variant === 'icons' ? ( - - ) : noIndicator ? null : ( - - )} - {titleCase(point.datum.activity)} - - {point.datum.value} - {formatted ? kcal : null} - -
- ))} - {variant === 'advanced' ? ( -
- Total - - {ordered.reduce((total, point) => total + point.datum.value, 0)} - kcal - -
- ) : null} -
- ) -} - -function ShadcnActivityIcon({ activity }: { activity: string }) { - return ( - - {activity === 'running' ? ( - <> - - - - ) : ( - <> - - - - )} - - ) -} - -function ShadcnSelectControl({ - ariaLabel, - value, - options, - onChange, -}: { - ariaLabel: string - value: string - options: readonly { value: string; label: string; swatch?: string }[] - onChange: (value: string) => void -}) { - const selected = options.find((option) => option.value === value) - return ( - - ) -} - -function ShadcnBarMetrics({ - active, - onChange, -}: { - active: InteractiveSeries - onChange: (series: InteractiveSeries) => void -}) { - const totals = { - desktop: interactiveBarRows.reduce((sum, row) => sum + row.desktop, 0), - mobile: interactiveBarRows.reduce((sum, row) => sum + row.mobile, 0), - } - return ( - <> - {twoSeries.map((series) => ( - - ))} - - ) -} - -function filterInteractiveAreaRows(timeRange: InteractiveTimeRange) { - const days = timeRange === '30d' ? 30 : timeRange === '7d' ? 7 : 90 - const start = new Date('2024-06-30T00:00:00Z') - start.setUTCDate(start.getUTCDate() - days) - const firstDate = start.toISOString().slice(0, 10) - return interactiveAreaRows.filter((row) => row.date >= firstDate) -} - -function interactiveDateTicks(timeRange: InteractiveTimeRange) { - if (timeRange === '7d') { - return ['2024-06-23', '2024-06-25', '2024-06-27', '2024-06-29'] - } - if (timeRange === '30d') { - return [ - '2024-06-01', - '2024-06-08', - '2024-06-15', - '2024-06-22', - '2024-06-29', - ] - } - return [ - '2024-04-10', - '2024-04-21', - '2024-05-02', - '2024-05-13', - '2024-05-25', - '2024-06-05', - '2024-06-16', - '2024-06-29', - ] -} - -function shadcnXAxis() { - return { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { - size: 0, - padding: 10, - format: (value: string) => value.slice(0, 3), - }, - }, - } -} - -function shadcnPointXAxis() { - return { - scale: scalePoint, - axis: { - line: false, - ticks: { - size: 0, - padding: 10, - format: (value: string) => value.slice(0, 3), - }, - }, - } -} - -function shadcnBrowserXAxis() { - return { - scale: () => scaleBand().paddingInner(0.2).paddingOuter(0.1), - axis: { - line: false, - ticks: { - size: 0, - padding: 10, - format: titleCase, - }, - }, - } -} - -function shadcnBrowserYAxis() { - return { - scale: () => scaleBand().paddingInner(0.18).paddingOuter(0.08), - axis: { - line: false, - ticks: { size: 0, padding: 10, format: titleCase }, - }, - } -} - -function shadcnTheme() { - return { - foreground: 'var(--muted-foreground, var(--muted))', - grid: 'var(--border)', - background: 'transparent', - } -} - -function formatWeekday(value: string) { - return new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format( - new Date(value), - ) -} - -function formatMonthDay(value: string) { - return new Intl.DateTimeFormat('en-US', { - month: 'short', - day: 'numeric', - timeZone: 'UTC', - }).format(new Date(value)) -} - -function titleCase(value: string) { - return value.charAt(0).toUpperCase() + value.slice(1) -} diff --git a/benchmarks/conformance/shared/shadcn-interaction.test.ts b/benchmarks/conformance/shared/shadcn-interaction.test.ts index d98d19ee..e87f53a3 100644 --- a/benchmarks/conformance/shared/shadcn-interaction.test.ts +++ b/benchmarks/conformance/shared/shadcn-interaction.test.ts @@ -1,13 +1,10 @@ -import { act } from 'react' +import { act, createElement, type ComponentType } from 'react' +import { createRoot } from 'react-dom/client' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { createShadcnTanStackExample } from './shadcn-catalog-tanstack' - -const input = { - width: 600, - height: 500, - revision: 0, - interactive: true, -} as const +import AreaInteractive from '../cases/137-shadcn-area-interactive/example' +import BarInteractive from '../cases/146-shadcn-bar-interactive/example' +import LineInteractive from '../cases/156-shadcn-line-interactive/example' +import PieInteractive from '../cases/164-shadcn-pie-interactive/example' let matchMediaDescriptor: PropertyDescriptor | undefined @@ -30,10 +27,7 @@ afterEach(() => { describe('shadcn interactive chart shells', () => { it('filters the interactive area chart from its range control', () => { const container = document.createElement('div') - const handle = createShadcnTanStackExample('chart-area-interactive').mount( - container, - input, - ) + const handle = mountExample(container, AreaInteractive) const select = container.querySelector('select') const path = () => container @@ -63,9 +57,10 @@ describe('shadcn interactive chart shells', () => { 'switches the interactive %s chart between desktop and mobile', (family) => { const container = document.createElement('div') - const handle = createShadcnTanStackExample( - `chart-${family}-interactive`, - ).mount(container, input) + const handle = mountExample( + container, + family === 'bar' ? BarInteractive : LineInteractive, + ) const mobile = [...container.querySelectorAll('button')].find((button) => button.textContent?.includes('Mobile'), ) @@ -98,10 +93,7 @@ describe('shadcn interactive chart shells', () => { it('changes the active pie slice, swatch, and center value', () => { const container = document.createElement('div') - const handle = createShadcnTanStackExample('chart-pie-interactive').mount( - container, - input, - ) + const handle = mountExample(container, PieInteractive) const select = container.querySelector('select') expect(select?.options).toHaveLength(5) @@ -130,3 +122,16 @@ describe('shadcn interactive chart shells', () => { handle.destroy() }) }) + +function mountExample( + container: HTMLElement, + Example: ComponentType<{ width?: number; height?: number }>, +) { + const root = createRoot(container) + act(() => root.render(createElement(Example, { width: 600, height: 500 }))) + return { + destroy() { + act(() => root.unmount()) + }, + } +} diff --git a/benchmarks/conformance/shared/shadcn-motion.test.ts b/benchmarks/conformance/shared/shadcn-motion.test.ts index fb649678..5ff56042 100644 --- a/benchmarks/conformance/shared/shadcn-motion.test.ts +++ b/benchmarks/conformance/shared/shadcn-motion.test.ts @@ -1,48 +1,33 @@ import { describe, expect, it } from 'vitest' import { createChartScene, type StaticChartDefinition } from '@tanstack/charts' -import { shadcnDashboardChartDefinition } from '../cases/127-shadcn-dashboard/tanstack' -import { barMultipleDefinition } from '../cases/128-shadcn-bar-multiple/tanstack' -import { pieDonutTextDefinition } from '../cases/129-shadcn-pie-donut-text/tanstack' -import { radarMultipleDefinition } from '../cases/130-shadcn-radar-multiple/tanstack' -import { radialTextDefinition } from '../cases/131-shadcn-radial-text/tanstack' -import { advancedTooltipDefinition } from '../cases/132-shadcn-tooltip-advanced/tanstack' -import { createShadcnTanStackExample } from './shadcn-catalog-tanstack' +import { createExampleChart as createShadcnDashboardChart } from '../cases/127-shadcn-dashboard/example' +import { definition as barMultipleDefinition } from '../cases/128-shadcn-bar-multiple/example' +import { definition as pieDonutTextDefinition } from '../cases/129-shadcn-pie-donut-text/example' +import { definition as radarMultipleDefinition } from '../cases/130-shadcn-radar-multiple/example' +import { definition as radialTextDefinition } from '../cases/131-shadcn-radial-text/example' +import { definition as advancedTooltipDefinition } from '../cases/132-shadcn-tooltip-advanced/example' +import { definition as areaDefaultDefinition } from '../cases/134-shadcn-area-default/example' +import { definition as barDefaultDefinition } from '../cases/144-shadcn-bar-default/example' +import { definition as lineDefaultDefinition } from '../cases/152-shadcn-line-default/example' +import { definition as pieSimpleDefinition } from '../cases/170-shadcn-pie-simple/example' +import { definition as radarDefaultDefinition } from '../cases/172-shadcn-radar-default/example' +import { definition as radarLegendDefinition } from '../cases/182-shadcn-radar-legend/example' +import { definition as radialSimpleDefinition } from '../cases/188-shadcn-radial-simple/example' +import { definition as tooltipDefaultDefinition } from '../cases/190-shadcn-tooltip-default/example' import type { ShadcnMonthDatum } from './shadcn-catalog-data' import { focusGroupAngle } from '@tanstack/charts/polar' -import { - createShadcnSpringRenderer, - shadcnSpringTransition, -} from './shadcn-motion' describe('shadcn chart motion', () => { - it('uses one physical spring preset for the collection', () => { - expect(shadcnSpringTransition).toEqual({ - type: 'spring', - stiffness: 170, - damping: 18, - mass: 1, - }) - expect(createShadcnSpringRenderer().id).toBe('svg:svg-motion') - }) - it('keeps dedicated and generated definitions free of duplicate spring policy', () => { const dedicatedDefinitions = [ - shadcnDashboardChartDefinition([]), + createShadcnDashboardChart([]), barMultipleDefinition, pieDonutTextDefinition, radarMultipleDefinition, radialTextDefinition, advancedTooltipDefinition, ] - const generatedDefinitions = [ - 'chart-area-default', - 'chart-bar-default', - 'chart-line-default', - 'chart-pie-simple', - 'chart-radar-default', - 'chart-radial-simple', - 'chart-tooltip-default', - ].map((name) => createShadcnTanStackExample(name).definition) + const generatedDefinitions = shadcnFamilyDefinitions() for (const definition of [ ...dedicatedDefinitions, @@ -55,28 +40,21 @@ describe('shadcn chart motion', () => { }) it('keeps the native focus marker enabled across generated families', () => { - const definitions = [ - 'chart-area-default', - 'chart-bar-default', - 'chart-line-default', - 'chart-pie-simple', - 'chart-radar-default', - 'chart-radial-simple', - 'chart-tooltip-default', - ].map((name) => createShadcnTanStackExample(name).definition) + const definitions = shadcnFamilyDefinitions() for (const definition of definitions) { expect(definition.focus).not.toBe(false) - expect(definition.focusRing).not.toBe(false) + expect( + 'focusRing' in definition ? definition.focusRing : undefined, + ).not.toBe(false) } expect(definitions[4]?.focus).toBe(focusGroupAngle) - expect(definitions[3]?.focus).toBe('nearest') - expect(definitions[5]?.focus).toBe('nearest') + expect(definitions[3]?.focus).toBe(focusGroupAngle) + expect(definitions[5]?.focus).toBe(focusGroupAngle) }) it('groups generated radar points by semantic angle and series', () => { - const definition = - createShadcnTanStackExample('chart-radar-legend').definition + const definition = radarLegendDefinition expect('chart' in definition).toBe(false) if ('chart' in definition) return const scene = createChartScene( @@ -95,3 +73,15 @@ describe('shadcn chart motion', () => { ) }) }) + +function shadcnFamilyDefinitions() { + return [ + areaDefaultDefinition, + barDefaultDefinition, + lineDefaultDefinition, + pieSimpleDefinition, + radarDefaultDefinition, + radialSimpleDefinition, + tooltipDefaultDefinition, + ] +} diff --git a/benchmarks/conformance/shared/shadcn-motion.ts b/benchmarks/conformance/shared/shadcn-motion.ts deleted file mode 100644 index 34331961..00000000 --- a/benchmarks/conformance/shared/shadcn-motion.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { motion } from '@tanstack/charts/motion' -import type { ChartValue } from '@tanstack/charts' -import type { ChartMotionSpringTransition } from '@tanstack/charts/motion' - -export const shadcnSpringTransition = { - type: 'spring', - stiffness: 170, - damping: 18, - mass: 1, -} as const satisfies ChartMotionSpringTransition - -export function createShadcnSpringRenderer< - TDatum = unknown, - TXValue extends ChartValue = ChartValue, - TYValue extends ChartValue = ChartValue, ->() { - return motion({ - initial: 'always', - transition: shadcnSpringTransition, - }) -} diff --git a/benchmarks/conformance/shared/transforms/learning-poverty.ts b/benchmarks/conformance/shared/transforms/learning-poverty.ts index 7ea6710d..58f34e26 100644 --- a/benchmarks/conformance/shared/transforms/learning-poverty.ts +++ b/benchmarks/conformance/shared/transforms/learning-poverty.ts @@ -1 +1 @@ -export * from '@charts-poc/demo-data/learning-poverty-geography' +export * from '@tanstack/charts-data/learning-poverty-geography' diff --git a/docs/reference/motion.md b/docs/reference/motion.md index 9316efea..76586f3a 100644 --- a/docs/reference/motion.md +++ b/docs/reference/motion.md @@ -17,6 +17,8 @@ const renderer = motion({ ``` ```ts +function motion(options?: ChartMotionOptions): UniversalChartRenderer + function motion< TDatum = unknown, TXValue extends ChartValue = ChartValue, @@ -31,6 +33,10 @@ interface ChartMotionOptions { } ``` +Use `motion(options)` beside a typed definition and let the host infer its +datum and axis values. The explicit generic overload remains available when a +low-level caller must type the renderer before it has a definition. + | Option | Default | Meaning | | ---------------------- | --------------------------------------------- | ------------------------------------------------------------- | | `initial` | `true` | Animate first client paint; `always` also replays adopted SVG | diff --git a/examples/charts-octane/package.json b/examples/charts-octane/package.json index 9e498ea6..2d6f5bde 100644 --- a/examples/charts-octane/package.json +++ b/examples/charts-octane/package.json @@ -8,7 +8,7 @@ "dev": "vite --host --port 5192 --strictPort" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@tanstack/charts": "workspace:*", "d3-array": "3.2.4", "d3-scale": "4.0.2", diff --git a/examples/charts-octane/src/charts.ts b/examples/charts-octane/src/charts.ts index 1be92fa6..84a79fc3 100644 --- a/examples/charts-octane/src/charts.ts +++ b/examples/charts-octane/src/charts.ts @@ -1,5 +1,5 @@ -import { cars } from '@charts-poc/demo-data/cars' -import { industries } from '@charts-poc/demo-data/industries' +import { cars } from '@tanstack/charts-data/cars' +import { industries } from '@tanstack/charts-data/industries' import { areaY, barX, @@ -19,8 +19,8 @@ import { stackOffsetWiggle, stackOrderInsideOut, } from 'd3-shape' -import type { CarsRow } from '@charts-poc/demo-data/cars' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { CarsRow } from '@tanstack/charts-data/cars' +import type { IndustriesRow } from '@tanstack/charts-data/industries' export type IndustryHistoryMode = 'line' | 'stacked' | 'share' | 'stream' export type { IndustriesRow } diff --git a/examples/charts-react/package.json b/examples/charts-react/package.json index 9037834a..372f4b2b 100644 --- a/examples/charts-react/package.json +++ b/examples/charts-react/package.json @@ -10,7 +10,7 @@ "dev": "vite --host --port 5191 --strictPort" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@tanstack/charts": "workspace:*", "d3-array": "3.2.4", "d3-scale": "4.0.2", diff --git a/examples/charts-react/src/charts.ts b/examples/charts-react/src/charts.ts index 38dcfb2e..79c7e04f 100644 --- a/examples/charts-react/src/charts.ts +++ b/examples/charts-react/src/charts.ts @@ -1,7 +1,7 @@ -import { cars } from '@charts-poc/demo-data/cars' -import { downloads } from '@charts-poc/demo-data/downloads' -import { industries } from '@charts-poc/demo-data/industries' -import { penguins } from '@charts-poc/demo-data/penguins' +import { cars } from '@tanstack/charts-data/cars' +import { downloads } from '@tanstack/charts-data/downloads' +import { industries } from '@tanstack/charts-data/industries' +import { penguins } from '@tanstack/charts-data/penguins' import { areaY, barX, @@ -25,9 +25,9 @@ import { stackOffsetWiggle, stackOrderInsideOut, } from 'd3-shape' -import type { CarsRow } from '@charts-poc/demo-data/cars' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' -import type { IndustriesRow } from '@charts-poc/demo-data/industries' +import type { CarsRow } from '@tanstack/charts-data/cars' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' +import type { IndustriesRow } from '@tanstack/charts-data/industries' import type { Bin } from 'd3-array' export type IndustryHistoryMode = 'line' | 'stacked' | 'share' | 'stream' diff --git a/examples/conformance/package.json b/examples/conformance/package.json index 282f653b..dc4675eb 100644 --- a/examples/conformance/package.json +++ b/examples/conformance/package.json @@ -8,7 +8,7 @@ "dev": "vite --host --port 5194 --strictPort" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@observablehq/plot": "0.6.17", "@tanstack/charts": "workspace:*", "d3-array": "3.2.4", diff --git a/examples/conformance/src/source-view.test.ts b/examples/conformance/src/source-view.test.ts index 3ae207aa..b9ebae5a 100644 --- a/examples/conformance/src/source-view.test.ts +++ b/examples/conformance/src/source-view.test.ts @@ -4,7 +4,7 @@ import type { CatalogSourceClosure, CatalogSourceFile, } from '../../../benchmarks/conformance/catalog-loader' -import type { DemoDatasetMetadata } from '@charts-poc/demo-data/metadata' +import type { DemoDatasetMetadata } from '@tanstack/charts-data/metadata' describe('renderCatalogSourceView', () => { it('orders and opens authored source while keeping fixtures collapsed', () => { @@ -80,7 +80,7 @@ describe('renderCatalogSourceView', () => { { path: 'tanstack.ts', source: - "import { aapl } from '@charts-poc/demo-data/aapl'\nvoid aapl\n", + "import { aapl } from '@tanstack/charts-data/aapl'\nvoid aapl\n", kind: 'entry', lines: 2, bytes: 66, @@ -163,7 +163,7 @@ function sourceClosure( const aaplDataset: DemoDatasetMetadata = { id: 'aapl', title: 'Apple daily stock prices', - specifier: '@charts-poc/demo-data/aapl', + specifier: '@tanstack/charts-data/aapl', format: 'CSV', records: 1_260, fields: ['Date', 'Close'], diff --git a/examples/conformance/src/source-view.tsx b/examples/conformance/src/source-view.tsx index 1f6a7cf1..8ad4b05b 100644 --- a/examples/conformance/src/source-view.tsx +++ b/examples/conformance/src/source-view.tsx @@ -4,7 +4,7 @@ import type { CatalogSourceFile, CatalogSourceKind, } from '../../../benchmarks/conformance/catalog-loader' -import type { DemoDatasetMetadata } from '@charts-poc/demo-data/metadata' +import type { DemoDatasetMetadata } from '@tanstack/charts-data/metadata' const sourceKindOrder: Record = { entry: 0, diff --git a/examples/sandbox/package.json b/examples/sandbox/package.json index bb5ef538..dc859a2f 100644 --- a/examples/sandbox/package.json +++ b/examples/sandbox/package.json @@ -9,7 +9,7 @@ "dev:interaction-geometry": "vite --host --port 5183 --strictPort --open /?lab=interaction-geometry" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@tanstack/charts": "workspace:*", "d3-array": "3.2.4", "d3-scale": "4.0.2", diff --git a/examples/sandbox/src/App.tsx b/examples/sandbox/src/App.tsx index 5737cf64..eb85c162 100644 --- a/examples/sandbox/src/App.tsx +++ b/examples/sandbox/src/App.tsx @@ -13,7 +13,7 @@ import { type IndustryStackPoint, type TimeRange, } from './transforms' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' import { createAgreementChart, createCarEconomyChart, diff --git a/examples/sandbox/src/plots.ts b/examples/sandbox/src/plots.ts index 2f27eac7..44954599 100644 --- a/examples/sandbox/src/plots.ts +++ b/examples/sandbox/src/plots.ts @@ -21,8 +21,8 @@ import { scaleUtc, } from 'd3-scale' import { curveCatmullRom, curveMonotoneX } from 'd3-shape' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' -import type { SimpsonsRow } from '@charts-poc/demo-data/simpsons' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' +import type { SimpsonsRow } from '@tanstack/charts-data/simpsons' import type { CarEconomyRow, IndustryStackPoint, diff --git a/examples/sandbox/src/transforms.test.ts b/examples/sandbox/src/transforms.test.ts index 5da1a404..e46f1517 100644 --- a/examples/sandbox/src/transforms.test.ts +++ b/examples/sandbox/src/transforms.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' -import { aapl } from '@charts-poc/demo-data/aapl' -import { survey } from '@charts-poc/demo-data/survey' +import { aapl } from '@tanstack/charts-data/aapl' +import { survey } from '@tanstack/charts-data/survey' import { createDashboardData, surveyResponses } from './transforms' describe('sandbox real-data transforms', () => { diff --git a/examples/sandbox/src/transforms.ts b/examples/sandbox/src/transforms.ts index fad4b398..6e576036 100644 --- a/examples/sandbox/src/transforms.ts +++ b/examples/sandbox/src/transforms.ts @@ -1,18 +1,18 @@ -import { aapl, type AaplRow } from '@charts-poc/demo-data/aapl' -import { cars } from '@charts-poc/demo-data/cars' +import { aapl, type AaplRow } from '@tanstack/charts-data/aapl' +import { cars } from '@tanstack/charts-data/cars' import { industries, type IndustriesRow, -} from '@charts-poc/demo-data/industries' -import { penguins, type PenguinsRow } from '@charts-poc/demo-data/penguins' +} from '@tanstack/charts-data/industries' +import { penguins, type PenguinsRow } from '@tanstack/charts-data/penguins' import { sfTemperatures, type SfTemperaturesRow, -} from '@charts-poc/demo-data/sf-temperatures' -import { simpsons, type SimpsonsRow } from '@charts-poc/demo-data/simpsons' -import { survey, type SurveyRow } from '@charts-poc/demo-data/survey' -import { travelers, type TravelersRow } from '@charts-poc/demo-data/travelers' -import { weather, type WeatherRow } from '@charts-poc/demo-data/weather' +} from '@tanstack/charts-data/sf-temperatures' +import { simpsons, type SimpsonsRow } from '@tanstack/charts-data/simpsons' +import { survey, type SurveyRow } from '@tanstack/charts-data/survey' +import { travelers, type TravelersRow } from '@tanstack/charts-data/travelers' +import { weather, type WeatherRow } from '@tanstack/charts-data/weather' import { mean } from 'd3-array' // Keep the source observations intact; derive only what each chart requires. diff --git a/package.json b/package.json index cda37b7a..0c9f49f2 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "devDependencies": { "@changesets/changelog-github": "0.7.0", "@changesets/cli": "2.31.1", - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@observablehq/plot": "0.6.17", "@observablehq/sample-datasets": "1.0.1", "@plot-poc/host-core": "workspace:*", diff --git a/packages/charts-core/docs/reference/motion.md b/packages/charts-core/docs/reference/motion.md index 9316efea..76586f3a 100644 --- a/packages/charts-core/docs/reference/motion.md +++ b/packages/charts-core/docs/reference/motion.md @@ -17,6 +17,8 @@ const renderer = motion({ ``` ```ts +function motion(options?: ChartMotionOptions): UniversalChartRenderer + function motion< TDatum = unknown, TXValue extends ChartValue = ChartValue, @@ -31,6 +33,10 @@ interface ChartMotionOptions { } ``` +Use `motion(options)` beside a typed definition and let the host infer its +datum and axis values. The explicit generic overload remains available when a +low-level caller must type the renderer before it has a definition. + | Option | Default | Meaning | | ---------------------- | --------------------------------------------- | ------------------------------------------------------------- | | `initial` | `true` | Animate first client paint; `always` also replays adopted SVG | diff --git a/packages/charts-core/src/box.test.ts b/packages/charts-core/src/box.test.ts index bb41d1cf..e957603b 100644 --- a/packages/charts-core/src/box.test.ts +++ b/packages/charts-core/src/box.test.ts @@ -1,6 +1,6 @@ import { scaleBand, scaleLinear } from 'd3-scale' -import { morley } from '@charts-poc/demo-data/morley' -import type { MorleyRow } from '@charts-poc/demo-data/morley' +import { morley } from '@tanstack/charts-data/morley' +import type { MorleyRow } from '@tanstack/charts-data/morley' import { describe, expect, expectTypeOf, it } from 'vitest' import { boxRows, boxX, boxY } from './box' import type { BoxDatum, BoxSummaryDatum } from './box' diff --git a/packages/charts-core/src/dom-types.ts b/packages/charts-core/src/dom-types.ts index e511e3c3..12d8b1f7 100644 --- a/packages/charts-core/src/dom-types.ts +++ b/packages/charts-core/src/dom-types.ts @@ -139,6 +139,27 @@ export interface ChartRenderer< ) => ChartSurface } +/** A definition-agnostic renderer that acquires chart types from its host. */ +export interface UniversalChartRenderer { + readonly id: string + prerender: < + TDatum, + TXValue extends ChartValue = ChartValue, + TYValue extends ChartValue = ChartValue, + >( + scene: ChartScene, + options: RenderChartOptions, + ) => string + mount: < + TDatum, + TXValue extends ChartValue = ChartValue, + TYValue extends ChartValue = ChartValue, + >( + container: HTMLElement, + requestRender: (force?: boolean) => void, + ) => ChartSurface +} + export interface ChartRendererRenderContext< TDatum = unknown, TXValue extends ChartValue = ChartValue, diff --git a/packages/charts-core/src/index.ts b/packages/charts-core/src/index.ts index ef08ee04..b1dddf90 100644 --- a/packages/charts-core/src/index.ts +++ b/packages/charts-core/src/index.ts @@ -249,6 +249,7 @@ export type { ChartRendererHostCommonOptions, ChartRendererHostOptions, ChartRendererRenderContext, + UniversalChartRenderer, ChartSurface, ChartSurfaceRenderOptions, ChartTooltipBodyTarget, diff --git a/packages/charts-core/src/mark-decorative.test.ts b/packages/charts-core/src/mark-decorative.test.ts index 2619cee1..a3e961f0 100644 --- a/packages/charts-core/src/mark-decorative.test.ts +++ b/packages/charts-core/src/mark-decorative.test.ts @@ -10,6 +10,7 @@ import { createChartScene, defineChart } from './scene' import { text } from './text' import { waffleY } from './waffle' import type { + ChartMarkDatum, ChartMarkPointX, ChartMarkPointY, ChartMarkScaleX, @@ -71,6 +72,7 @@ describe('decorative mark', () => { expect(polylines[0]).not.toHaveProperty('interaction') expectTypeOf>().toEqualTypeOf() expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() expectTypeOf>().toEqualTypeOf() expectTypeOf>().toEqualTypeOf() }) diff --git a/packages/charts-core/src/mark-decorative.ts b/packages/charts-core/src/mark-decorative.ts index db8c6b0c..aa899a3b 100644 --- a/packages/charts-core/src/mark-decorative.ts +++ b/packages/charts-core/src/mark-decorative.ts @@ -1,23 +1,11 @@ import { createDecorativeMark } from './mark-decorative-internal' import { stripMarkSceneInteraction } from './mark-scene-filter-internal' -import type { ChartMark, ChartValue } from './types' +import type { ChartMark, DecorativeChartMark } from './types' /** Keeps one mark's scale and painted geometry while removing interaction ownership. */ export function decorative< - TDatum, - TXPointValue extends ChartValue, - TYPointValue extends ChartValue, - TXScaleValue extends ChartValue, - TYScaleValue extends ChartValue, ->( - mark: ChartMark< - TDatum, - TXPointValue, - TYPointValue, - TXScaleValue, - TYScaleValue - >, -): ChartMark { + const TMark extends ChartMark, +>(mark: TMark): DecorativeChartMark { return createDecorativeMark( mark, (scene) => @@ -28,5 +16,5 @@ export function decorative< conditional: 'reject', layoutLabels: 'preserve', }, - ) + ) as unknown as DecorativeChartMark } diff --git a/packages/charts-core/src/motion.ts b/packages/charts-core/src/motion.ts index c55c2eaa..7b9ecfdb 100644 --- a/packages/charts-core/src/motion.ts +++ b/packages/charts-core/src/motion.ts @@ -37,6 +37,7 @@ import type { ChartRenderer, ChartSurface, ChartSurfaceRenderOptions, + UniversalChartRenderer, } from './dom-types' import type { ChartFocusState, @@ -752,15 +753,37 @@ function parseSvgFragment(current: SVGElement, markup: string) { return template.content.firstElementChild?.firstElementChild ?? undefined } +export function motion(options?: ChartMotionOptions): UniversalChartRenderer export function motion< TDatum = unknown, TXValue extends ChartValue = ChartValue, TYValue extends ChartValue = ChartValue, ->(options: ChartMotionOptions = {}): ChartRenderer { - return createMotionSvgChartRenderer( - createSvgMotionDriver(options), - renderChartSvgWithResources, - ) +>(options?: ChartMotionOptions): ChartRenderer +export function motion( + options: ChartMotionOptions = {}, +): UniversalChartRenderer { + const capabilityDriver = createSvgMotionDriver(options) + const renderer: UniversalChartRenderer & { + [chartRendererMotion]: ChartRendererMotionCapability + } = { + id: `svg:${capabilityDriver.id}`, + [chartRendererMotion]: { + createTooltip: capabilityDriver.createTooltip, + }, + prerender: renderChartSvgWithResources, + mount< + TDatum, + TXValue extends ChartValue = ChartValue, + TYValue extends ChartValue = ChartValue, + >(container: HTMLElement, requestRender: (force?: boolean) => void) { + return createMotionSvgChartRenderer( + createSvgMotionDriver(options), + renderChartSvgWithResources, + renderer, + ).mount(container, requestRender) + }, + } + return renderer } function createMotionSvgChartRenderer< @@ -774,6 +797,7 @@ function createMotionSvgChartRenderer< TXValue, TYValue > = renderChartSvgWithResources, + ownerRenderer?: ChartRenderer, ): ChartRenderer { const renderer: ChartRenderer & { [chartRendererMotion]: ChartRendererMotionCapability @@ -909,7 +933,7 @@ function createMotionSvgChartRenderer< return presented.scene } const surface: ChartSurface = { - renderer, + renderer: ownerRenderer ?? renderer, get element() { return svgElement() }, diff --git a/packages/charts-core/src/scene.test.ts b/packages/charts-core/src/scene.test.ts index fffc11ec..695a7475 100644 --- a/packages/charts-core/src/scene.test.ts +++ b/packages/charts-core/src/scene.test.ts @@ -259,6 +259,50 @@ describe('native mark and channel scene', () => { ).toBe(true) }) + it('infers raw static and responsive specs before checking behaviors', () => { + const primary = [{ id: 'a', x: 0, y: 1 }] + const secondary = [{ name: 'b', x: 1, value: 2 }] + const marks = [ + lineY(primary, { x: 'x', y: 'y' }), + lineY(secondary, { x: 'x', y: 'value' }), + ] as const + const tooltipExtension = { + id: 'test-tooltip', + create() {}, + __chartExtensionType: 'tooltip', + __chartTooltipHost: 'dom', + } as const + const staticDefinition = defineChart( + { marks, ...linearAxes([0, 1], [0, 2]) }, + { + keyboard: true, + tooltip: { + use: tooltipExtension, + format: ({ datum }) => ('id' in datum ? datum.id : datum.name), + }, + }, + ) + const responsiveDefinition = defineChart( + () => ({ marks, ...linearAxes([0, 1], [0, 2]) }), + { + keyboard: true, + tooltip: { + use: tooltipExtension, + format: ({ datum }) => ('id' in datum ? datum.id : datum.name), + }, + }, + ) + + type Datum = (typeof primary)[number] | (typeof secondary)[number] + expectTypeOf(staticDefinition).toMatchTypeOf>() + expectTypeOf(responsiveDefinition).toMatchTypeOf>() + expect(responsiveDefinition.chart).toBeTypeOf('function') + expect(responsiveDefinition.keyboard).toBe(true) + expect(responsiveDefinition.tooltip).toMatchObject({ + use: tooltipExtension, + }) + }) + it('collects dense channels and interaction points without argument spreading', () => { const count = 200_000 const values = Array(count).fill(0) diff --git a/packages/charts-core/src/scene.ts b/packages/charts-core/src/scene.ts index 396b3159..9bfad712 100644 --- a/packages/charts-core/src/scene.ts +++ b/packages/charts-core/src/scene.ts @@ -71,7 +71,7 @@ export const defaultChartTheme: ChartTheme = { } type DefinedStaticChart< - TMarks extends readonly ChartMark[], + TMarks extends readonly ChartMark[], TSpec extends ChartSpec, > = Omit< StaticChartDefinition< @@ -107,8 +107,25 @@ type ChartDefinitionWithOptions = Omit< > & TOptions +type DefinedResponsiveChart< + TSpec extends { + marks: readonly ChartMark[] + x?: ChartAxisOptions | null + y?: ChartAxisOptions | null + }, +> = Omit< + ResponsiveChartDefinition< + ChartSpecDatum, + ChartSpecXValue, + ChartSpecYValue + >, + keyof ChartDefinitionOptions +> & { + chart: (context: ChartBuildContext) => CheckedChartSpec +} + export function defineChart< - const TMarks extends readonly ChartMark[], + const TMarks extends readonly ChartMark[], const TSpec extends ChartSpec, >( spec: TSpec & { marks: TMarks } & ChartDefinitionOptions< @@ -119,7 +136,7 @@ export function defineChart< ): DefinedStaticChart export function defineChart< const TSpec extends { - marks: readonly ChartMark[] + marks: readonly ChartMark[] x?: ChartAxisOptions | null y?: ChartAxisOptions | null }, @@ -137,28 +154,67 @@ export function defineChart< ResponsiveChartConfig export function defineChart< const TSpec extends { - marks: readonly ChartMark[] + marks: readonly ChartMark[] x?: ChartAxisOptions | null y?: ChartAxisOptions | null }, >( chart: (context: ChartBuildContext) => CheckedChartSpec, -): Omit< - ResponsiveChartDefinition< +): DefinedResponsiveChart +export function defineChart< + const TMarks extends readonly ChartMark[], + const TSpec extends ChartSpec, + const TOptions extends ChartDefinitionOptions< + ChartMarkDatum, + ChartMarkPointX, + ChartMarkPointY + >, +>( + spec: TSpec & { marks: TMarks } & ChartDefinitionOptions< + ChartMarkDatum, + ChartMarkPointX, + ChartMarkPointY + >, + options: TOptions, +): ChartDefinitionWithOptions, TOptions> +export function defineChart< + const TSpec extends { + marks: readonly ChartMark[] + x?: ChartAxisOptions | null + y?: ChartAxisOptions | null + }, + const TOptions extends ChartDefinitionOptions< ChartSpecDatum, ChartSpecXValue, ChartSpecYValue >, - keyof ChartDefinitionOptions -> & { - chart: (context: ChartBuildContext) => CheckedChartSpec -} +>( + chart: (context: ChartBuildContext) => TSpec, + options: TOptions, +): ChartDefinitionWithOptions, TOptions> +export function defineChart< + const TMarks extends readonly ChartMark[], + const TSpec extends ChartSpec, + const TOptions extends ChartDefinitionOptions< + ChartMarkDatum, + ChartMarkPointX, + ChartMarkPointY + >, +>( + config: { + chart: (context: ChartBuildContext) => TSpec & { marks: TMarks } + }, + options: TOptions, +): ChartDefinitionWithOptions< + DefinedResponsiveChart, + TOptions +> export function defineChart< const TDefinition extends StaticChartDefinition, const TOptions extends ChartDefinitionOptions< - ChartSpecDatum, - ChartSpecXValue, - ChartSpecYValue + ChartDefinitionDatum, + ChartDefinitionXValue, + ChartDefinitionYValue >, >( definition: TDefinition, @@ -176,7 +232,11 @@ export function defineChart< options: TOptions, ): ChartDefinitionWithOptions, NoInfer> export function defineChart(definition?: any, options?: any): any { - if (options) return { ...definition, ...options } + if (options) { + return typeof definition === 'function' + ? { chart: definition, ...options } + : { ...definition, ...options } + } return ( typeof definition === 'function' ? { chart: definition } : definition ) as StaticChartDefinition | ResponsiveChartDefinition diff --git a/packages/charts-core/src/types.ts b/packages/charts-core/src/types.ts index 17059fbf..c9db3040 100644 --- a/packages/charts-core/src/types.ts +++ b/packages/charts-core/src/types.ts @@ -551,21 +551,44 @@ export interface ChartLinearGradient { stops: readonly ChartGradientStop[] } -export type ChartMarkScaleX = - TMark extends ChartMark ? TValue : never +/** A scale-contributing mark that does not own interactive chart points. */ +export type DecorativeChartMark< + TMark extends ChartMark, +> = TMark & { + readonly __decorativeMark: TMark +} + +interface DecorativeChartMarkBrand { + readonly __decorativeMark: ChartMark +} -export type ChartMarkScaleY = - TMark extends ChartMark ? TValue : never +export type ChartMarkScaleX = TMark extends { + readonly __decorativeMark: infer TSource +} + ? ChartMarkScaleX + : TMark extends ChartMark + ? TValue + : never -export type ChartMarkPointX = - TMark extends ChartMark +export type ChartMarkScaleY = TMark extends { + readonly __decorativeMark: infer TSource +} + ? ChartMarkScaleY + : TMark extends ChartMark + ? TValue + : never + +export type ChartMarkPointX = TMark extends DecorativeChartMarkBrand + ? never + : TMark extends ChartMark ? [TDatum] extends [never] ? never : TXValue : never -export type ChartMarkPointY = - TMark extends ChartMark +export type ChartMarkPointY = TMark extends DecorativeChartMarkBrand + ? never + : TMark extends ChartMark ? [TDatum] extends [never] ? never : TYValue @@ -588,7 +611,7 @@ export type ChartAxisValue = ? any : WidenChartValue -type AnyChartMarks = readonly ChartMark[] +type AnyChartMarks = readonly ChartMark[] type IsUnion = TValue extends TWhole ? [TWhole] extends [TValue] @@ -706,7 +729,7 @@ export interface ChartMarkMotionOptions { } interface StoredChartSpec extends ChartSpecBase { - marks: readonly ChartMark[] + marks: readonly ChartMark[] x?: ChartAxisOptions | null y?: ChartAxisOptions | null } @@ -812,7 +835,7 @@ export interface StaticChartDefinition< TTooltipHost extends string = string, > extends StoredChartSpec, StoredChartDefinitionOptions { - marks: readonly ChartMark[] + marks: readonly ChartMark[] readonly __datum?: TDatum readonly __xValue?: TXValue readonly __yValue?: TYValue @@ -888,8 +911,11 @@ export type DomChartDefinition< TYValue extends ChartValue = ChartValue, > = ChartDefinitionForTooltipHost -export type ChartMarkDatum = - TMark extends ChartMark ? TDatum : never +export type ChartMarkDatum = TMark extends DecorativeChartMarkBrand + ? never + : TMark extends ChartMark + ? TDatum + : never export type ChartSpecDatum = '__datum' extends keyof TSpec diff --git a/packages/charts-core/src/view.ts b/packages/charts-core/src/view.ts index 6bdf7bc2..9e26e9f3 100644 --- a/packages/charts-core/src/view.ts +++ b/packages/charts-core/src/view.ts @@ -156,23 +156,28 @@ export interface ViewGridOptions< type ViewDefinition = TView extends ViewGridItem ? TDefinition : never -type DefinitionDatum = TDefinition extends { - readonly __datum?: infer TDatum -} - ? TDatum - : never +type DefinitionDatum = + TDefinition extends ComposableChartDefinition + ? TDatum + : never -type DefinitionXValue = TDefinition extends { - readonly __xValue?: infer TXValue extends ChartValue -} - ? TXValue - : never +type DefinitionXValue = + TDefinition extends ComposableChartDefinition< + any, + infer TXValue extends ChartValue, + any + > + ? TXValue + : never -type DefinitionYValue = TDefinition extends { - readonly __yValue?: infer TYValue extends ChartValue -} - ? TYValue - : never +type DefinitionYValue = + TDefinition extends ComposableChartDefinition< + any, + any, + infer TYValue extends ChartValue + > + ? TYValue + : never type ViewDatum = DefinitionDatum< ViewDefinition diff --git a/packages/charts-demo-data/package.json b/packages/charts-demo-data/package.json index 30005610..56212871 100644 --- a/packages/charts-demo-data/package.json +++ b/packages/charts-demo-data/package.json @@ -1,5 +1,5 @@ { - "name": "@charts-poc/demo-data", + "name": "@tanstack/charts-data", "version": "0.0.0", "private": true, "type": "module", diff --git a/packages/charts-demo-data/raw/observable-plot/README.md b/packages/charts-demo-data/raw/observable-plot/README.md index 2f7dd4d6..a0560441 100644 --- a/packages/charts-demo-data/raw/observable-plot/README.md +++ b/packages/charts-demo-data/raw/observable-plot/README.md @@ -5,5 +5,5 @@ These files are byte-for-byte snapshots from `356f579b1d947ee05a914420eddff0f29cee300a`. The generator records each file's upstream source and SHA-256 in -`@charts-poc/demo-data/metadata`. Observable Plot is MIT licensed; the +`@tanstack/charts-data/metadata`. Observable Plot is MIT licensed; the metadata retains the separate upstream dataset attribution. diff --git a/packages/charts-demo-data/src/learning-poverty-geography.ts b/packages/charts-demo-data/src/learning-poverty-geography.ts index eb89511d..54261752 100644 --- a/packages/charts-demo-data/src/learning-poverty-geography.ts +++ b/packages/charts-demo-data/src/learning-poverty-geography.ts @@ -1,8 +1,8 @@ -import { learningPoverty } from '@charts-poc/demo-data/learning-poverty' +import { learningPoverty } from '@tanstack/charts-data/learning-poverty' import { geoCentroid } from 'd3-geo' import { worldCountries } from './country-atlas' import { simplifyPolygonGeometry } from './simplify-geo' -import type { LearningPovertyRow } from '@charts-poc/demo-data/learning-poverty' +import type { LearningPovertyRow } from '@tanstack/charts-data/learning-poverty' import type { ExtendedFeature, GeoGeometryObjects } from 'd3-geo' import type { CountryFeature, CountryGeometry } from './country-atlas' diff --git a/packages/charts-demo-data/src/metadata.js b/packages/charts-demo-data/src/metadata.js index d09d5d88..53a21cd8 100644 --- a/packages/charts-demo-data/src/metadata.js +++ b/packages/charts-demo-data/src/metadata.js @@ -1,7 +1,7 @@ // Generated by scripts/sync-demo-data.mjs. // Do not edit this file directly. export const demoDatasetMetadata = [ - {id: "aapl", title: "Apple daily stock prices", specifier: "@charts-poc/demo-data/aapl", format: "CSV", records: 1260, fields: [ + {id: "aapl", title: "Apple daily stock prices", specifier: "@tanstack/charts-data/aapl", format: "CSV", records: 1260, fields: [ "Date", "Open", "High", @@ -32,7 +32,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 92399, sha256: "18dc8bf6542da26625d992544a619a5fc210d6dfc799e81ab7fb7f9edbc21f9a", selection: "Complete published snapshot", source: "Yahoo! Finance", sourceUrl: "https://finance.yahoo.com/lookup", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "aapl.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/aapl.csv", license: "ISC distribution; upstream source credited"}, - {id: "alphabet", title: "English letter frequencies", specifier: "@charts-poc/demo-data/alphabet", format: "CSV", records: 26, fields: [ + {id: "alphabet", title: "English letter frequencies", specifier: "@tanstack/charts-data/alphabet", format: "CSV", records: 26, fields: [ "letter", "frequency", ], schema: [ @@ -43,7 +43,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 275, sha256: "d62ce74dad83964bb0c463811933a29df888bff0624febbe7e63594931fa7e9e", selection: "Complete published snapshot", source: "Cryptographical Mathematics by Robert Edward Lewand", sourceUrl: "http://cs.wellesley.edu/~fturbak/codman/letterfreq.html", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "alphabet.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/alphabet.csv", license: "ISC distribution; upstream source credited"}, - {id: "cars", title: "1983 ASA automobile data", specifier: "@charts-poc/demo-data/cars", format: "CSV", records: 406, fields: [ + {id: "cars", title: "1983 ASA automobile data", specifier: "@tanstack/charts-data/cars", format: "CSV", records: 406, fields: [ "name", "economy (mpg)", "cylinders", @@ -80,7 +80,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 17438, sha256: "eaad8395d37ee0f591ea143e8ce4f87d0909fb1daba085834b27c1da841f56af", selection: "Complete published snapshot", source: "1983 ASA Data Exposition", sourceUrl: "http://lib.stat.cmu.edu/datasets/", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "cars.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/cars.csv", license: "ISC distribution; upstream source credited"}, - {id: "citywages", title: "U.S. metropolitan wage inequality", specifier: "@charts-poc/demo-data/citywages", format: "CSV", records: 195, fields: [ + {id: "citywages", title: "U.S. metropolitan wage inequality", specifier: "@tanstack/charts-data/citywages", format: "CSV", records: 195, fields: [ "Metro", "POP_1980", "LPOP_1980", @@ -125,7 +125,7 @@ export const demoDatasetMetadata = [ "null", ]}, ], bytes: 15389, sha256: "9b50329064c16166026a8fee22c1f99f08c5de53697ab24271634b27d7b94a0b", selection: "Complete published snapshot", source: "The New York Times", sourceUrl: "https://www.nytimes.com/2019/12/02/upshot/wealth-poverty-divide-american-cities.html", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "citywages.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/citywages.csv", license: "ISC distribution; upstream source credited"}, - {id: "diamonds", title: "ggplot2 diamonds", specifier: "@charts-poc/demo-data/diamonds", format: "CSV", records: 53940, fields: [ + {id: "diamonds", title: "ggplot2 diamonds", specifier: "@tanstack/charts-data/diamonds", format: "CSV", records: 53940, fields: [ "carat", "cut", "color", @@ -168,7 +168,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 2448483, sha256: "243996d7650e84e190a88d505b44c3a0be1bcfc7b4f32606d60d103a51494b9e", selection: "Complete published snapshot", source: "ggplot2", sourceUrl: "https://github.com/tidyverse/ggplot2/blob/master/data-raw/diamonds.csv", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "diamonds.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/diamonds.csv", license: "ISC distribution; upstream source credited"}, - {id: "flare", title: "Flare package hierarchy", specifier: "@charts-poc/demo-data/flare", format: "CSV", records: 252, fields: [ + {id: "flare", title: "Flare package hierarchy", specifier: "@tanstack/charts-data/flare", format: "CSV", records: 252, fields: [ "name", "size", ], schema: [ @@ -180,7 +180,7 @@ export const demoDatasetMetadata = [ "null", ]}, ], bytes: 7989, sha256: "704349b51b709f2357ea6a4ef01f46e0ccbe0917dc08e4a44c1cbe0b954b8c13", selection: "Complete published snapshot", source: "Flare visualization toolkit", sourceUrl: "https://observablehq.com/@d3/treemap", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "flare.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/flare.csv", license: "ISC distribution; upstream source credited"}, - {id: "industries", title: "U.S. industry unemployment", specifier: "@charts-poc/demo-data/industries", format: "CSV", records: 1708, fields: [ + {id: "industries", title: "U.S. industry unemployment", specifier: "@tanstack/charts-data/industries", format: "CSV", records: 1708, fields: [ "date", "industry", "unemployed", @@ -195,7 +195,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 53919, sha256: "4cfc13b6ebe0f8c231b52895cee5f67670e5a1bad86460a8982716c3d86d835f", selection: "Complete published snapshot", source: "U.S. Bureau of Labor Statistics", sourceUrl: "https://www.bls.gov/", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "industries.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/industries.csv", license: "ISC distribution; upstream source credited"}, - {id: "miserables", title: "Les Misérables character network", specifier: "@charts-poc/demo-data/miserables", format: "JSON", records: 331, fields: [ + {id: "miserables", title: "Les Misérables character network", specifier: "@tanstack/charts-data/miserables", format: "JSON", records: 331, fields: [ "nodes", "links", ], schema: [ @@ -206,7 +206,7 @@ export const demoDatasetMetadata = [ "array", ]}, ], bytes: 18844, sha256: "e84d8083667ccd496313307bd7e7a036da77689b8acf3464fa0211fb0b61a675", selection: "Complete published snapshot", source: "Donald Knuth, Stanford Graph Base", sourceUrl: "https://www-cs-faculty.stanford.edu/~knuth/sgb.html", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "miserables.json", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/miserables.json", license: "ISC distribution; upstream source credited"}, - {id: "olympians", title: "2016 Summer Olympians", specifier: "@charts-poc/demo-data/olympians", format: "CSV", records: 11538, fields: [ + {id: "olympians", title: "2016 Summer Olympians", specifier: "@tanstack/charts-data/olympians", format: "CSV", records: 11538, fields: [ "id", "name", "nationality", @@ -260,7 +260,7 @@ export const demoDatasetMetadata = [ "null", ]}, ], bytes: 841836, sha256: "29ff8d6298da8961d264be2849701614cce6ef939d6e52fb413f2071ec30f7ec", selection: "Complete published snapshot", source: "Matt Riggott / IOC", sourceUrl: "https://www.flother.is/2017/olympic-games-data/", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "olympians.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/olympians.csv", license: "ISC distribution; upstream source credited"}, - {id: "penguins", title: "Palmer penguins", specifier: "@charts-poc/demo-data/penguins", format: "CSV", records: 344, fields: [ + {id: "penguins", title: "Palmer penguins", specifier: "@tanstack/charts-data/penguins", format: "CSV", records: 344, fields: [ "species", "island", "culmen_length_mm", @@ -296,7 +296,7 @@ export const demoDatasetMetadata = [ "null", ]}, ], bytes: 13506, sha256: "dfee817d1c1422363886dfd1897b3bed1a54ff9a3a6b223b5b7900a88e55a24d", selection: "Complete published snapshot", source: "Dr. Kristen Gorman / Palmer Station LTER", sourceUrl: "https://github.com/allisonhorst/palmerpenguins", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "penguins.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/penguins.csv", license: "ISC distribution; upstream source credited"}, - {id: "pizza", title: "Pizza Paradise orders", specifier: "@charts-poc/demo-data/pizza", format: "CSV", records: 29853, fields: [ + {id: "pizza", title: "Pizza Paradise orders", specifier: "@tanstack/charts-data/pizza", format: "CSV", records: 29853, fields: [ "order_date", "day_of_week", "category", @@ -327,7 +327,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 2329284, sha256: "50b49e7118acd32960ab3a97784c9507fb1b040fddffaa35603097acf98405f6", selection: "Complete published snapshot", source: "Observable Pizza Paradise", sourceUrl: "https://observablehq.com/@observablehq/pizza-paradise-data", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "pizza.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/pizza.csv", license: "ISC distribution; upstream source credited"}, - {id: "weather", title: "Seattle weather observations", specifier: "@charts-poc/demo-data/weather", format: "CSV", records: 2922, fields: [ + {id: "weather", title: "Seattle weather observations", specifier: "@tanstack/charts-data/weather", format: "CSV", records: 2922, fields: [ "location", "date", "precipitation", @@ -358,7 +358,7 @@ export const demoDatasetMetadata = [ "string", ]}, ], bytes: 121417, sha256: "27219f1ca8dbd94c9b6f4b9f4f52ab2f1eb33dfdcf719cd9fc6481ed50b74549", selection: "Complete published snapshot", source: "NOAA / Vega", sourceUrl: "https://github.com/vega/vega-datasets/blob/master/scripts/weather.py", observablePackage: "@observablehq/sample-datasets@1.0.1", observableRevision: "732c0148de741469b2bcc03f53d93b0ad0b93f0a", observableFile: "weather.csv", observableUrl: "https://github.com/observablehq/sample-datasets/blob/732c0148de741469b2bcc03f53d93b0ad0b93f0a/weather.csv", license: "ISC distribution; upstream source credited"}, - {id: "westport-house", title: "Westport House second-floor plan", specifier: "@charts-poc/demo-data/westport-house", format: "JSON", records: 121, fields: [ + {id: "westport-house", title: "Westport House second-floor plan", specifier: "@tanstack/charts-data/westport-house", format: "JSON", records: 121, fields: [ "type", "features", ], schema: [ @@ -369,7 +369,7 @@ export const demoDatasetMetadata = [ "array", ]}, ], bytes: 63146, sha256: "066ea951b4affba3ee7c2bf981b8333681ce24e55903ffcddcc39f0475fb39a3", selection: "Complete published snapshot", source: "WRLD indoor maps API", sourceUrl: "https://github.com/wrld3d/wrld-indoor-maps-api", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/westport-house.json", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/westport-house.json", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "anscombe", title: "Anscombe's quartet", specifier: "@charts-poc/demo-data/anscombe", format: "CSV", records: 44, fields: [ + {id: "anscombe", title: "Anscombe's quartet", specifier: "@tanstack/charts-data/anscombe", format: "CSV", records: 44, fields: [ "series", "x", "y", @@ -384,7 +384,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 422, sha256: "136943112c4dbaebddb3f69f72612c0a4c9d4354b74ea54d98f6d16d01be9913", selection: "Complete published snapshot", source: "Anscombe's quartet", sourceUrl: "https://en.wikipedia.org/wiki/Anscombe%27s_quartet", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/anscombe.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/anscombe.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "beagle", title: "HMS Beagle voyage", specifier: "@charts-poc/demo-data/beagle", format: "CSV", records: 303, fields: [ + {id: "beagle", title: "HMS Beagle voyage", specifier: "@tanstack/charts-data/beagle", format: "CSV", records: 303, fields: [ "0", "1", ], schema: [ @@ -395,7 +395,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 4063, sha256: "338919940e130c887f186729eda26ad85b8b272ab83128d5facf40fbb3b309e9", selection: "Complete published snapshot", source: "Charles Darwin's voyage on the HMS Beagle", sourceUrl: "https://observablehq.com/@bmschmidt/data-driven-projections-darwins-world", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/beagle.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/beagle.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "crimean-war", title: "Crimean War monthly mortality", specifier: "@charts-poc/demo-data/crimean-war", format: "CSV", records: 24, fields: [ + {id: "crimean-war", title: "Crimean War monthly mortality", specifier: "@tanstack/charts-data/crimean-war", format: "CSV", records: 24, fields: [ "date", "army", "disease", @@ -418,7 +418,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 676, sha256: "5747ee54b77a9b717dbc9d7f032581c4db67ea97de2f34df89cad093e632c368", selection: "Complete published snapshot", source: "Florence Nightingale", sourceUrl: "https://archive.org/details/b21304110/page/n11/mode/2up", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/crimean-war.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/crimean-war.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "decathlon", title: "Decathlon results", specifier: "@charts-poc/demo-data/decathlon", format: "CSV", records: 50, fields: [ + {id: "decathlon", title: "Decathlon results", specifier: "@tanstack/charts-data/decathlon", format: "CSV", records: 50, fields: [ "Country", "100 Meters", "Long Jump", @@ -441,7 +441,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 1321, sha256: "8c016fb7adcc04f0a9a970cd50a7067b1faa019f7a1df924d4dafcfedfdde951", selection: "Complete published snapshot", source: "JMP Statistical Discovery sample", sourceUrl: "https://github.com/hemanrobinson/preattentive/blob/a58dd4795d0ee063a38a2d7bf33812d969ca6256/src/Data.js#L5598-L5650", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/decathlon.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/decathlon.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "downloads", title: "Observable package downloads", specifier: "@charts-poc/demo-data/downloads", format: "CSV", records: 1566, fields: [ + {id: "downloads", title: "Observable package downloads", specifier: "@tanstack/charts-data/downloads", format: "CSV", records: 1566, fields: [ "date", "downloads", ], schema: [ @@ -452,7 +452,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 20457, sha256: "09953cc843f382738c48dcfeae633dea30579ada163e8fd53b9907fa5f11d6ca", selection: "Complete published snapshot", source: "npm downloads API", sourceUrl: "https://observablehq.com/@mbostock/npm-daily-downloads?name=@observablehq/cars", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/downloads.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/downloads.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "learning-poverty", title: "Learning poverty by country", specifier: "@charts-poc/demo-data/learning-poverty", format: "CSV", records: 100, fields: [ + {id: "learning-poverty", title: "Learning poverty by country", specifier: "@tanstack/charts-data/learning-poverty", format: "CSV", records: 100, fields: [ "Country Name", "Out-of-School (OoS)", "Below Minimum Proficiency (in School)", @@ -487,7 +487,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 4675, sha256: "6c4d1c0aef44a435a3205f8af2a2321d56da01950fb60475bb5086b90ed07e50", selection: "Complete published snapshot", source: "World Bank / Our World in Data", sourceUrl: "https://ourworldindata.org/grapher/share-of-children-who-cannot-read-at-end-of-primary-age", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/learning-poverty.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/learning-poverty.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "driving", title: "U.S. driving and gasoline prices", specifier: "@charts-poc/demo-data/driving", format: "CSV", records: 55, fields: [ + {id: "driving", title: "U.S. driving and gasoline prices", specifier: "@tanstack/charts-data/driving", format: "CSV", records: 55, fields: [ "side", "year", "miles", @@ -506,7 +506,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 1546, sha256: "3aced2fa41f2be51ee43f9da66d964d7c647dac27bcc37158d09098efad4ba4e", selection: "Complete published snapshot", source: "The New York Times", sourceUrl: "https://archive.nytimes.com/www.nytimes.com/imagepages/2010/05/02/business/02metrics.html", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/driving.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/driving.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "morley", title: "Michelson speed-of-light experiments", specifier: "@charts-poc/demo-data/morley", format: "CSV", records: 100, fields: [ + {id: "morley", title: "Michelson speed-of-light experiments", specifier: "@tanstack/charts-data/morley", format: "CSV", records: 100, fields: [ "Expt", "Run", "Speed", @@ -521,7 +521,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 874, sha256: "a9c06023c0f277f09b6ad541e0f81acc4e21b09f3d5c35919547c3934dae5968", selection: "Complete published snapshot", source: "R datasets / Michelson–Morley experiment", sourceUrl: "https://github.com/vincentarelbundock/Rdatasets/blob/master/csv/datasets/morley.csv", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/morley.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/morley.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "sf-temperatures", title: "San Francisco daily temperatures", specifier: "@charts-poc/demo-data/sf-temperatures", format: "CSV", records: 732, fields: [ + {id: "sf-temperatures", title: "San Francisco daily temperatures", specifier: "@tanstack/charts-data/sf-temperatures", format: "CSV", records: 732, fields: [ "date", "high", "low", @@ -536,7 +536,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 15106, sha256: "1e90d4f9b2094bb32a4fd3f9d777478d0b5cb16f609c95e9be6eb2c245061cb4", selection: "Complete published snapshot", source: "National Climatic Data Center", sourceUrl: "https://www.ncdc.noaa.gov/", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/sf-temperatures.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/sf-temperatures.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "simpsons", title: "The Simpsons episode ratings", specifier: "@charts-poc/demo-data/simpsons", format: "CSV", records: 600, fields: [ + {id: "simpsons", title: "The Simpsons episode ratings", specifier: "@tanstack/charts-data/simpsons", format: "CSV", records: 600, fields: [ "id", "title", "original_air_date", @@ -597,7 +597,7 @@ export const demoDatasetMetadata = [ "null", ]}, ], bytes: 119729, sha256: "7cc6ecdcb70637a6d5e8df8933537f338178a96f61dd92e905f1b6b6044ebd31", selection: "Complete published snapshot", source: "IMDb / Todd W. Schneider", sourceUrl: "https://data.world/data-society/the-simpsons-by-the-data", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/simpsons.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/simpsons.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "survey", title: "Likert survey responses", specifier: "@charts-poc/demo-data/survey", format: "CSV", records: 500, fields: [ + {id: "survey", title: "Likert survey responses", specifier: "@tanstack/charts-data/survey", format: "CSV", records: 500, fields: [ "Question", "ID", "Response", @@ -612,7 +612,7 @@ export const demoDatasetMetadata = [ "string", ]}, ], bytes: 8217, sha256: "de6879d712488bf64cc7d215c12de59b5c9e08d574471493ae8d476510c2969c", selection: "Complete published snapshot", source: "Eitan Lees", sourceUrl: "https://talk.observablehq.com/t/diverging-stacked-bar-chart-in-plot/6028", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/survey.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/survey.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "travelers", title: "U.S. airport traveler throughput", specifier: "@charts-poc/demo-data/travelers", format: "CSV", records: 300, fields: [ + {id: "travelers", title: "U.S. airport traveler throughput", specifier: "@tanstack/charts-data/travelers", format: "CSV", records: 300, fields: [ "date", "current", "previous", @@ -627,7 +627,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 7836, sha256: "a5d9ba37fe6d67dc82195c571bc3f3a04ca07c83ddf57e127e1886f4d04d8ce8", selection: "Complete published snapshot", source: "U.S. Transportation Security Administration", sourceUrl: "https://www.tsa.gov/coronavirus/passenger-throughput", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/travelers.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/travelers.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "us-county-unemployment", title: "U.S. county unemployment", specifier: "@charts-poc/demo-data/us-county-unemployment", format: "CSV", records: 3219, fields: [ + {id: "us-county-unemployment", title: "U.S. county unemployment", specifier: "@tanstack/charts-data/us-county-unemployment", format: "CSV", records: 3219, fields: [ "id", "state", "county", @@ -646,7 +646,7 @@ export const demoDatasetMetadata = [ "number", ]}, ], bytes: 109819, sha256: "dd3cc76e5e21f8caceee84da7e36450d28a59a1535f928f93efbc9b752059452", selection: "Complete published snapshot", source: "U.S. Bureau of Labor Statistics", sourceUrl: "https://www.bls.gov/lau/tables.htm", observablePackage: "observablehq/plot@356f579b1d94", observableRevision: "356f579b1d947ee05a914420eddff0f29cee300a", observableFile: "test/data/us-county-unemployment.csv", observableUrl: "https://github.com/observablehq/plot/blob/356f579b1d947ee05a914420eddff0f29cee300a/test/data/us-county-unemployment.csv", license: "Observable Plot repository ISC; upstream source credited"}, - {id: "wind", title: "Gridded surface wind", specifier: "@charts-poc/demo-data/wind", format: "CSV", records: 4800, fields: [ + {id: "wind", title: "Gridded surface wind", specifier: "@tanstack/charts-data/wind", format: "CSV", records: 4800, fields: [ "longitude", "latitude", "u", diff --git a/packages/charts-fixtures/package.json b/packages/charts-fixtures/package.json index 0ee4eded..70fc26a5 100644 --- a/packages/charts-fixtures/package.json +++ b/packages/charts-fixtures/package.json @@ -11,7 +11,7 @@ "./styles.css": "./src/styles.css" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@tanstack/charts": "workspace:*", "d3-array": "3.2.4", "d3-scale": "4.0.2", diff --git a/packages/charts-fixtures/src/index.test.ts b/packages/charts-fixtures/src/index.test.ts index 5848c363..c5549e7a 100644 --- a/packages/charts-fixtures/src/index.test.ts +++ b/packages/charts-fixtures/src/index.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' -import { cars } from '@charts-poc/demo-data/cars' -import { downloads } from '@charts-poc/demo-data/downloads' +import { cars } from '@tanstack/charts-data/cars' +import { downloads } from '@tanstack/charts-data/downloads' import { carRankingData, downloadData, diff --git a/packages/charts-fixtures/src/index.ts b/packages/charts-fixtures/src/index.ts index 5bc63036..43ee7d53 100644 --- a/packages/charts-fixtures/src/index.ts +++ b/packages/charts-fixtures/src/index.ts @@ -9,13 +9,13 @@ import { ruleY, rect, } from '@tanstack/charts' -import { cars } from '@charts-poc/demo-data/cars' -import { downloads } from '@charts-poc/demo-data/downloads' +import { cars } from '@tanstack/charts-data/cars' +import { downloads } from '@tanstack/charts-data/downloads' import { bin as d3Bin } from 'd3-array' import { scaleBand, scaleLinear, scaleOrdinal, scaleUtc } from 'd3-scale' import { curveMonotoneX } from 'd3-shape' -import type { CarsRow } from '@charts-poc/demo-data/cars' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' +import type { CarsRow } from '@tanstack/charts-data/cars' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' import type { Bin } from 'd3-array' export type HorsepowerBin = Bin diff --git a/packages/fixtures/package.json b/packages/fixtures/package.json index 82b39d19..8c4e4871 100644 --- a/packages/fixtures/package.json +++ b/packages/fixtures/package.json @@ -9,7 +9,7 @@ "./styles.css": "./src/styles.css" }, "dependencies": { - "@charts-poc/demo-data": "workspace:*", + "@tanstack/charts-data": "workspace:*", "@observablehq/plot": "0.6.17", "@plot-poc/observable": "workspace:*" } diff --git a/packages/fixtures/src/data.test.ts b/packages/fixtures/src/data.test.ts index 413c4749..7ae4b3b1 100644 --- a/packages/fixtures/src/data.test.ts +++ b/packages/fixtures/src/data.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' -import { downloads } from '@charts-poc/demo-data/downloads' -import { penguins } from '@charts-poc/demo-data/penguins' +import { downloads } from '@tanstack/charts-data/downloads' +import { penguins } from '@tanstack/charts-data/penguins' import { downloadData, penguinData } from './data' describe('shared Observable Plot fixtures', () => { diff --git a/packages/fixtures/src/data.ts b/packages/fixtures/src/data.ts index 8be10dd6..b4c02e46 100644 --- a/packages/fixtures/src/data.ts +++ b/packages/fixtures/src/data.ts @@ -1,7 +1,7 @@ -import { downloads } from '@charts-poc/demo-data/downloads' -import { penguins } from '@charts-poc/demo-data/penguins' -import type { DownloadsRow } from '@charts-poc/demo-data/downloads' -import type { PenguinsRow } from '@charts-poc/demo-data/penguins' +import { downloads } from '@tanstack/charts-data/downloads' +import { penguins } from '@tanstack/charts-data/penguins' +import type { DownloadsRow } from '@tanstack/charts-data/downloads' +import type { PenguinsRow } from '@tanstack/charts-data/penguins' export interface PenguinBodyMassRow extends PenguinsRow { readonly body_mass_g: number diff --git a/packages/react-charts/src/Chart.test.tsx b/packages/react-charts/src/Chart.test.tsx index 4743a7f0..af740f84 100644 --- a/packages/react-charts/src/Chart.test.tsx +++ b/packages/react-charts/src/Chart.test.tsx @@ -11,9 +11,13 @@ import type { import { renderChartSvgWithResources } from '@tanstack/charts/svg/resources' import { tooltip } from '@tanstack/charts/tooltip' import { portal as tooltipPortal } from '@tanstack/charts/tooltip/portal' +import { motion } from '@tanstack/charts/motion' import { scaleLinear } from 'd3-scale' import { Chart } from './Chart' -import { Chart as TooltipChart } from './tooltip' +import { + Chart as TooltipChart, + RendererChart as TooltipRendererChart, +} from './tooltip' const data = [ { id: 'jan', month: 1, value: 8 }, @@ -171,6 +175,13 @@ if (false) { }} /> ) + const inferredMotionRenderer = ( + + ) const widened = ( ) - void [inferredCallback, inferredStaticCallback, widened] + void [ + inferredCallback, + inferredStaticCallback, + inferredMotionRenderer, + widened, + ] } describe('React adapter', () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a184774b..54fb9f9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: '@changesets/cli': specifier: 2.31.1 version: 2.31.1(@types/node@25.9.5) - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:packages/charts-demo-data '@observablehq/plot': @@ -284,7 +284,7 @@ importers: examples/charts-octane: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../../packages/charts-demo-data '@tanstack/charts': @@ -318,7 +318,7 @@ importers: examples/charts-react: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../../packages/charts-demo-data '@tanstack/charts': @@ -410,7 +410,7 @@ importers: examples/conformance: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../../packages/charts-demo-data '@observablehq/plot': @@ -506,7 +506,7 @@ importers: examples/sandbox: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../../packages/charts-demo-data '@tanstack/charts': @@ -741,7 +741,7 @@ importers: packages/charts-fixtures: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../charts-demo-data '@tanstack/charts': @@ -786,7 +786,7 @@ importers: packages/fixtures: dependencies: - '@charts-poc/demo-data': + '@tanstack/charts-data': specifier: workspace:* version: link:../charts-demo-data '@observablehq/plot': diff --git a/scripts/catalog-definition-shapes.test.mjs b/scripts/catalog-definition-shapes.test.mjs index 6892e67d..349f9103 100644 --- a/scripts/catalog-definition-shapes.test.mjs +++ b/scripts/catalog-definition-shapes.test.mjs @@ -29,23 +29,7 @@ const responsiveDefinitions = [ 'bar-vertical-sorted/example.tsx', ] -const indirectDefinitions = [ - '130-shadcn-radar-multiple/example.tsx', - '172-shadcn-radar-default/example.tsx', - '173-shadcn-radar-dots/example.tsx', - '174-shadcn-radar-grid-circle-fill/example.tsx', - '175-shadcn-radar-grid-circle-no-lines/example.tsx', - '176-shadcn-radar-grid-circle/example.tsx', - '177-shadcn-radar-grid-custom/example.tsx', - '178-shadcn-radar-grid-fill/example.tsx', - '179-shadcn-radar-grid-none/example.tsx', - '180-shadcn-radar-icons/example.tsx', - '182-shadcn-radar-legend/example.tsx', - '183-shadcn-radar-lines-only/example.tsx', - '184-shadcn-radar-radius/example.tsx', - '185-shadcn-radial-grid/example.tsx', - '188-shadcn-radial-simple/example.tsx', -] +const indirectDefinitions = [] describe('catalog definition shapes', () => { it('uses static definitions unless the chart reads build context', async () => { @@ -84,10 +68,10 @@ describe('catalog definition shapes', () => { ) expect(classification.parameterless).toEqual([]) - expect(classification.static).toBe(160) + expect(classification.static).toBe(175) expect(classification.responsive.sort()).toEqual(responsiveDefinitions) expect(classification.indirect.sort()).toEqual(indirectDefinitions) - expect(classification.staticFiles).toHaveLength(155) + expect(classification.staticFiles).toHaveLength(170) expect( new Set([ ...classification.staticFiles, @@ -159,8 +143,29 @@ function classifyDefinitions(relativePath, source, classification) { const definition = unwrapParentheses(node.arguments[0]) if (ts.isObjectLiteralExpression(definition)) { - classification.static += 1 - hasStaticDefinition = true + const chartProperty = definition.properties.find( + (property) => + ts.isPropertyAssignment(property) && + property.name.getText(sourceFile) === 'chart', + ) + const chart = + chartProperty && ts.isPropertyAssignment(chartProperty) + ? unwrapParentheses(chartProperty.initializer) + : undefined + if (chart && ts.isArrowFunction(chart)) { + if (chart.parameters.length === 0) { + const { line } = sourceFile.getLineAndCharacterOfPosition( + chart.getStart(sourceFile), + ) + classification.parameterless.push(`${relativePath}:${line + 1}`) + } else { + classification.responsive.push(relativePath) + hasResponsiveDefinition = true + } + } else { + classification.static += 1 + hasStaticDefinition = true + } } else if (ts.isArrowFunction(definition)) { if (definition.parameters.length === 0) { const { line } = sourceFile.getLineAndCharacterOfPosition( diff --git a/scripts/check-catalog-examples.mjs b/scripts/check-catalog-examples.mjs index ba8ebc95..93296796 100644 --- a/scripts/check-catalog-examples.mjs +++ b/scripts/check-catalog-examples.mjs @@ -8,9 +8,10 @@ const casesRoot = path.join(root, 'benchmarks', 'conformance', 'cases') const demoDataRoot = path.join(root, 'packages', 'charts-demo-data', 'src') const sourceExtensions = ['.ts', '.tsx', '.js', '.jsx', '.json', '.css'] const browserModuleExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs'] -const demoDataPrefixes = ['@charts-poc/demo-data/', '@tanstack/charts-data/'] +const demoDataPrefixes = ['@tanstack/charts-data/'] const forbiddenPublicNames = - /\b(?:Conformance|tanstackCase|tanstackMount|reactMount|catalogPreviewDefinition)\b/ + /\b(?:Conformance|ExampleOptions|tanstackCase|tanstackMount|reactMount|catalogPreviewDefinition)\b/ +const privatePackageName = '@charts-poc/' const directories = (await fs.readdir(casesRoot, { withFileTypes: true })) .filter((entry) => entry.isDirectory()) @@ -57,6 +58,11 @@ for (const directory of directories) { `${directory}/${relativePath}: contains conformance-only code`, ) } + if (source.includes(privatePackageName)) { + failures.push( + `${directory}/${relativePath}: exposes a private workspace package`, + ) + } if ( sourcePath === examplePath && !hasDefaultComponentExport(source, sourcePath) @@ -70,6 +76,11 @@ for (const directory of directories) { `${directory}: put the chart definition before the component shell`, ) } + if (sourcePath === examplePath) { + for (const problem of catalogScaffoldingProblems(source, sourcePath)) { + failures.push(`${directory}: ${problem}`) + } + } for (const specifier of importSpecifiers(source, sourcePath)) { const demoDataPrefix = demoDataPrefixes.find((prefix) => @@ -151,6 +162,83 @@ function definitionFollowsComponent(source) { ) } +function catalogScaffoldingProblems(source, sourcePath) { + const file = ts.createSourceFile( + sourcePath, + source, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TSX, + ) + const problems = [] + const localFactories = new Set() + let exampleFactory + for (const statement of file.statements) { + if (ts.isFunctionDeclaration(statement) && statement.name) { + localFactories.add(statement.name.text) + if (statement.name.text === 'createExampleChart') { + exampleFactory = statement + } + } + if (!ts.isVariableStatement(statement)) continue + for (const declaration of statement.declarationList.declarations) { + if (!ts.isIdentifier(declaration.name)) continue + localFactories.add(declaration.name.text) + if (declaration.name.text === 'createExampleChart') { + exampleFactory = declaration + if ( + declaration.initializer && + ts.isIdentifier(declaration.initializer) + ) { + problems.push( + 'createExampleChart must contain the authored definition', + ) + } + } + } + } + + let exampleFactoryHasDefinition = false + const visit = (node, insideExampleFactory = false) => { + const nextInside = insideExampleFactory || node === exampleFactory + if (isDefineChartCall(node)) { + if (nextInside) exampleFactoryHasDefinition = true + const chart = node.arguments[0] + if (chart && isDefineChartCall(chart)) { + problems.push('remove nested defineChart wrappers') + } + if ( + chart && + ts.isCallExpression(chart) && + ts.isIdentifier(chart.expression) && + localFactories.has(chart.expression.text) + ) { + problems.push( + `inline the local ${chart.expression.text} chart-definition wrapper`, + ) + } + } + ts.forEachChild(node, (child) => visit(child, nextInside)) + } + visit(file) + + if (exampleFactory && !exampleFactoryHasDefinition) { + problems.push('createExampleChart must contain defineChart') + } + if (/\.\.\.\s*\{\s*\}/u.test(source)) { + problems.push('remove empty object spreads') + } + return [...new Set(problems)] +} + +function isDefineChartCall(node) { + return ( + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + node.expression.text === 'defineChart' + ) +} + function checkUnusedPublicSource(sourcePaths, output) { const config = ts.readConfigFile( path.join(root, 'tsconfig.json'), diff --git a/scripts/clean-catalog-examples.mjs b/scripts/clean-catalog-examples.mjs index 0f2cb464..68c8bb39 100644 --- a/scripts/clean-catalog-examples.mjs +++ b/scripts/clean-catalog-examples.mjs @@ -2,6 +2,7 @@ import { promises as fs } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { format } from 'prettier' +import ts from 'typescript' import { removeUnusedTypeScript } from './typescript-source.mjs' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') @@ -12,17 +13,585 @@ const directories = (await fs.readdir(casesRoot, { withFileTypes: true })) .sort() let changed = 0 +let collapsed = 0 for (const directory of directories) { const examplePath = path.join(casesRoot, directory, 'example.tsx') const source = await fs.readFile(examplePath, 'utf8') - const cleaned = await format(removeUnusedTypeScript(source, examplePath), { - parser: 'typescript', - semi: false, - singleQuote: true, - }) + const collapsedWrapper = collapseDefinitionWrapper(source, examplePath) + const normalized = { + ...collapsedWrapper, + source: renameIdentifier( + pruneUnusedExampleOptions( + splitBehaviorOptions( + flattenNestedDefineCharts(collapsedWrapper.source, examplePath), + examplePath, + ), + examplePath, + ), + examplePath, + 'ExampleOptions', + 'ChartOptions', + ), + } + if (normalized.source === source) continue + const cleaned = await format( + removeUnusedTypeScript(normalized.source, examplePath), + { + parser: 'typescript', + semi: false, + singleQuote: true, + }, + ) + if (normalized.renamedFrom) { + collapsed += 1 + await renameCaseReferences(directory, normalized.renamedFrom) + } if (cleaned === source) continue await fs.writeFile(examplePath, cleaned, 'utf8') changed += 1 } -console.log(`Cleaned ${changed} of ${directories.length} catalog examples.`) +function pruneUnusedExampleOptions(source, filePath) { + const file = ts.createSourceFile( + filePath, + source, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TSX, + ) + const declaration = file.statements.find( + (statement) => + ts.isInterfaceDeclaration(statement) && + ['ExampleOptions', 'ChartOptions'].includes(statement.name.text), + ) + if (!declaration) return source + const optionsTypeName = declaration.name.text + const factory = functionLikeDeclaration(file, 'createExampleChart') + const factoryUsesOptions = factory?.functionLike.parameters.some( + (parameter) => isOptionsType(parameter.type, optionsTypeName), + ) + + const parameterNames = new Set() + const usedProperties = new Set() + const visitParameters = (node) => { + if (ts.isParameter(node) && isOptionsType(node.type, optionsTypeName)) { + if (ts.isIdentifier(node.name)) { + parameterNames.add(node.name.text) + } else if (ts.isObjectBindingPattern(node.name)) { + for (const element of node.name.elements) { + const name = element.propertyName ?? element.name + if (ts.isIdentifier(name)) usedProperties.add(name.text) + } + } + } + ts.forEachChild(node, visitParameters) + } + visitParameters(file) + + const visitUses = (node) => { + if ( + ts.isPropertyAccessExpression(node) && + ts.isIdentifier(node.expression) && + parameterNames.has(node.expression.text) + ) { + usedProperties.add(node.name.text) + } + ts.forEachChild(node, visitUses) + } + visitUses(file) + + const declaredProperties = new Set( + declaration.members.flatMap((member) => { + if (!ts.isPropertySignature(member) || !member.name) return [] + const name = propertyNameText(member.name) + return name ? [name] : [] + }), + ) + const unusedProperties = new Set( + [...declaredProperties].filter((name) => !usedProperties.has(name)), + ) + if (unusedProperties.size === 0 && declaration.members.length > 0) { + return source + } + + const edits = [] + const removesOptions = unusedProperties.size === declaration.members.length + if (removesOptions) { + edits.push({ + start: declaration.getFullStart(), + end: declaration.end, + }) + if (factoryUsesOptions) { + const parameter = factory.functionLike.parameters.find((candidate) => + isOptionsType(candidate.type, optionsTypeName), + ) + if (parameter) { + edits.push({ start: parameter.getStart(file), end: parameter.end }) + } + } + } + if (!removesOptions) { + for (const member of declaration.members) { + if (!ts.isPropertySignature(member) || !member.name) continue + const name = propertyNameText(member.name) + if (name && unusedProperties.has(name)) { + edits.push(removalEdit(member, declaration.members, source, file)) + } + } + } + + const visitCalls = (node) => { + if ( + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + factoryUsesOptions && + node.expression.text === 'createExampleChart' && + node.arguments[0] && + ts.isObjectLiteralExpression(node.arguments[0]) + ) { + const object = node.arguments[0] + if (removesOptions) { + edits.push({ start: object.getStart(file), end: object.end }) + return + } + for (const property of object.properties) { + if (!ts.isPropertyAssignment(property) || !property.name) continue + const name = propertyNameText(property.name) + if (name && unusedProperties.has(name)) { + edits.push(removalEdit(property, object.properties, source, file)) + } + } + } + ts.forEachChild(node, visitCalls) + } + visitCalls(file) + + let result = source + for (const edit of edits.sort((left, right) => right.start - left.start)) { + result = result.slice(0, edit.start) + result.slice(edit.end) + } + return result +} + +function isOptionsType(node, typeName) { + return ( + node && + ts.isTypeReferenceNode(node) && + ts.isIdentifier(node.typeName) && + node.typeName.text === typeName + ) +} + +function propertyNameText(node) { + if (ts.isIdentifier(node) || ts.isStringLiteral(node)) return node.text + return undefined +} + +function removalEdit(node, siblings, source, file) { + const index = siblings.indexOf(node) + const next = siblings[index + 1] + if (next) { + return { start: node.getFullStart(), end: next.getFullStart() } + } + const previous = siblings[index - 1] + if (previous) { + const between = source.slice(previous.end, node.getFullStart()) + const comma = between.lastIndexOf(',') + if (comma !== -1) { + return { + start: previous.end + comma, + end: node.end, + } + } + } + return { start: node.getFullStart(), end: node.end } +} + +console.log( + `Cleaned ${changed} of ${directories.length} catalog examples; collapsed ${collapsed} generated definition wrappers.`, +) + +function collapseDefinitionWrapper(source, filePath) { + const file = ts.createSourceFile( + filePath, + source, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TSX, + ) + const wrapper = functionLikeDeclaration(file, 'createExampleChart') + const wrapperFunction = wrapper?.functionLike + const outerCall = + wrapperFunction && isFactoryFunction(wrapperFunction) + ? returnedExpression(wrapperFunction) + : undefined + if ( + !wrapper || + !wrapperFunction || + !isFactoryFunction(wrapperFunction) || + !outerCall || + !isDefineChartCall(outerCall) + ) { + return { source } + } + + const delegatedCall = outerCall.arguments[0] + const behaviorOptions = outerCall.arguments[1] + if ( + outerCall.arguments.length !== 2 || + !delegatedCall || + !ts.isCallExpression(delegatedCall) || + !ts.isIdentifier(delegatedCall.expression) || + !behaviorOptions || + !ts.isObjectLiteralExpression(behaviorOptions) + ) { + return { source } + } + + const targetName = delegatedCall.expression.text + const target = functionLikeDeclaration(file, targetName) + const targetFunction = target?.functionLike + if (!target || !targetFunction) { + return { source } + } + + const resultExpression = returnedExpression(targetFunction) + if (!resultExpression) return { source } + + const replacement = definitionWithBehavior( + source, + resultExpression, + behaviorOptions, + ) + const wrapperBody = inlinedFactoryBody( + source, + file, + wrapperFunction, + outerCall, + targetFunction, + delegatedCall.arguments, + resultExpression, + replacement, + ) + if (!wrapperBody) return { source } + const edits = [ + { + start: wrapperFunction.body.getStart(file), + end: wrapperFunction.body.end, + text: wrapperBody, + }, + { + start: target.statement.getStart(file), + end: target.statement.end, + text: '', + }, + ].sort((left, right) => right.start - left.start) + + let result = source + for (const edit of edits) { + result = result.slice(0, edit.start) + edit.text + result.slice(edit.end) + } + return { source: result, renamedFrom: targetName } +} + +function isFactoryFunction(node) { + return ( + ts.isArrowFunction(node) || + ts.isFunctionExpression(node) || + ts.isFunctionDeclaration(node) + ) +} + +function functionLikeDeclaration(file, name) { + const variable = variableDeclaration(file, name) + const initializer = variable?.declaration.initializer + if ( + variable && + initializer && + (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) + ) { + return { functionLike: initializer, statement: variable.statement } + } + for (const statement of file.statements) { + if ( + ts.isFunctionDeclaration(statement) && + statement.name?.text === name && + statement.body + ) { + return { functionLike: statement, statement } + } + } + return undefined +} + +function inlinedFactoryBody( + source, + file, + wrapper, + outerCall, + factory, + argumentsList, + resultExpression, + replacement, +) { + if (factory.parameters.length !== argumentsList.length) return undefined + const prefix = statementsBeforeReturn(source, file, wrapper, outerCall) + const bindings = [] + for (let index = 0; index < factory.parameters.length; index += 1) { + const parameter = factory.parameters[index] + const argument = argumentsList[index] + if (!parameter || !argument || !ts.isIdentifier(parameter.name)) { + return undefined + } + if (ts.isIdentifier(argument) && argument.text === parameter.name.text) { + continue + } + const value = parameter.initializer + ? `${sourceText(source, argument)} ?? ${sourceText(source, parameter.initializer)}` + : sourceText(source, argument) + bindings.push(`const ${parameter.name.text} = ${value}`) + } + + let body + if (ts.isBlock(factory.body)) { + body = source.slice(factory.body.getStart(file) + 1, factory.body.end - 1) + const expressionStart = + resultExpression.getStart(file) - (factory.body.getStart(file) + 1) + const expressionEnd = + resultExpression.end - (factory.body.getStart(file) + 1) + body = + body.slice(0, expressionStart) + replacement + body.slice(expressionEnd) + } else { + body = `return ${replacement}` + } + return `{\n${prefix}\n${bindings.join('\n')}\n${body}\n}` +} + +function statementsBeforeReturn(source, file, factory, expression) { + if (!ts.isBlock(factory.body)) return '' + const returnStatement = factory.body.statements.find( + (statement) => + ts.isReturnStatement(statement) && statement.expression === expression, + ) + if (!returnStatement) return '' + return source.slice( + factory.body.getStart(file) + 1, + returnStatement.getStart(file), + ) +} + +function variableDeclaration(file, name) { + for (const statement of file.statements) { + if (!ts.isVariableStatement(statement)) continue + for (const declaration of statement.declarationList.declarations) { + if (ts.isIdentifier(declaration.name) && declaration.name.text === name) { + return { declaration, statement } + } + } + } + return undefined +} + +function returnedExpression(factory) { + if (!ts.isBlock(factory.body)) return factory.body + for (const statement of factory.body.statements) { + if (ts.isReturnStatement(statement) && statement.expression) { + return statement.expression + } + } + return undefined +} + +function isDefineChartCall(node) { + return ( + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + node.expression.text === 'defineChart' + ) +} + +function definitionWithBehavior(source, expression, behaviorOptions) { + const behaviorText = sourceText(source, behaviorOptions) + if (!isDefineChartCall(expression)) { + return `defineChart(${sourceText(source, expression)}, ${behaviorText})` + } + + if (expression.arguments.length !== 1) { + throw new Error('Expected the delegated definition to have one argument.') + } + return `defineChart(${sourceText(source, expression.arguments[0])}, ${behaviorText})` +} + +function sourceText(source, node) { + return source.slice(node.getStart(), node.end) +} + +function flattenNestedDefineCharts(source, filePath) { + let result = source + for (let pass = 0; pass < 4; pass += 1) { + const file = ts.createSourceFile( + filePath, + result, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TSX, + ) + const edits = [] + const visit = (node) => { + if ( + isDefineChartCall(node) && + node.arguments.length === 2 && + isDefineChartCall(node.arguments[0]) && + node.arguments[0].arguments.length === 1 + ) { + edits.push({ + start: node.getStart(file), + end: node.end, + text: `defineChart(${sourceText(result, node.arguments[0].arguments[0])}, ${sourceText(result, node.arguments[1])})`, + }) + return + } + ts.forEachChild(node, visit) + } + visit(file) + if (edits.length === 0) return result + for (const edit of edits.sort((left, right) => right.start - left.start)) { + result = result.slice(0, edit.start) + edit.text + result.slice(edit.end) + } + } + return result +} + +function splitBehaviorOptions(source, filePath) { + const file = ts.createSourceFile( + filePath, + source, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TSX, + ) + const factory = functionLikeDeclaration(file, 'createExampleChart') + const definition = factory + ? returnedExpression(factory.functionLike) + : undefined + + if ( + definition && + isDefineChartCall(definition) && + (definition.arguments.length === 1 || definition.arguments.length === 2) && + ts.isObjectLiteralExpression(definition.arguments[0]) + ) { + const config = definition.arguments[0] + const chartProperty = config.properties.find( + (property) => + ts.isPropertyAssignment(property) && + property.name && + ts.isIdentifier(property.name) && + property.name.text === 'chart', + ) + const behavior = definition.arguments[1] + if ( + chartProperty && + ts.isPropertyAssignment(chartProperty) && + (!behavior || ts.isObjectLiteralExpression(behavior)) + ) { + const options = config.properties.filter( + (property) => property !== chartProperty, + ) + if (behavior && ts.isObjectLiteralExpression(behavior)) { + options.push(...behavior.properties) + } + const replacement = + options.length === 0 + ? `defineChart(${sourceText(source, chartProperty.initializer)})` + : `defineChart(${sourceText(source, chartProperty.initializer)}, {${options.map((property) => sourceText(source, property)).join(',\n')}})` + return ( + source.slice(0, definition.getStart(file)) + + replacement + + source.slice(definition.end) + ) + } + } + + if ( + !definition || + !isDefineChartCall(definition) || + definition.arguments.length !== 1 || + !ts.isObjectLiteralExpression(definition.arguments[0]) + ) { + return source + } + + const chart = definition.arguments[0] + const behaviorNames = new Set(['keyboard', 'tooltip']) + const behaviorProperties = chart.properties.filter( + (property) => + property.name && + ts.isIdentifier(property.name) && + behaviorNames.has(property.name.text), + ) + if (behaviorProperties.length !== behaviorNames.size) return source + const chartProperties = chart.properties.filter( + (property) => !behaviorProperties.includes(property), + ) + const propertyText = (property) => sourceText(source, property) + const replacement = `defineChart({${chartProperties.map(propertyText).join(',\n')}}, {${behaviorProperties.map(propertyText).join(',\n')}})` + return ( + source.slice(0, definition.getStart(file)) + + replacement + + source.slice(definition.end) + ) +} + +async function renameCaseReferences(directory, from) { + if (from === 'createExampleChart') return + const caseRoot = path.join(casesRoot, directory) + const entries = await fs.readdir(caseRoot, { withFileTypes: true }) + for (const entry of entries) { + if ( + !entry.isFile() || + entry.name === 'example.tsx' || + !/\.(?:ts|tsx)$/u.test(entry.name) + ) { + continue + } + const filePath = path.join(caseRoot, entry.name) + const source = await fs.readFile(filePath, 'utf8') + const renamed = renameIdentifier( + source, + filePath, + from, + 'createExampleChart', + ) + if (renamed === source) continue + const formatted = await format(renamed, { + parser: 'typescript', + semi: false, + singleQuote: true, + }) + await fs.writeFile(filePath, formatted, 'utf8') + } +} + +function renameIdentifier(source, filePath, from, to) { + const file = ts.createSourceFile( + filePath, + source, + ts.ScriptTarget.Latest, + true, + filePath.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS, + ) + const edits = [] + const visit = (node) => { + if (ts.isIdentifier(node) && node.text === from) { + edits.push({ start: node.getStart(file), end: node.end }) + } + ts.forEachChild(node, visit) + } + visit(file) + let result = source + for (const edit of edits.sort((left, right) => right.start - left.start)) { + result = result.slice(0, edit.start) + to + result.slice(edit.end) + } + return result +} diff --git a/scripts/compare-plot-catalog.mjs b/scripts/compare-plot-catalog.mjs index 0fde38a1..71f7955a 100644 --- a/scripts/compare-plot-catalog.mjs +++ b/scripts/compare-plot-catalog.mjs @@ -1189,7 +1189,7 @@ async function buildImplementations(cases, typeAudit) { legalComments: 'none', logLevel: 'silent', write: false, - external: ['@charts-poc/demo-data/*'], + external: ['@tanstack/charts-data/*'], }) const contents = measurementResult.outputFiles[0]?.contents if (!contents) { diff --git a/scripts/demo-data.test.mjs b/scripts/demo-data.test.mjs index b68e1ef2..eeda15be 100644 --- a/scripts/demo-data.test.mjs +++ b/scripts/demo-data.test.mjs @@ -4,7 +4,7 @@ import { readFile } from 'node:fs/promises' import { resolve } from 'node:path' import { build } from 'esbuild' import { describe, expect, it } from 'vitest' -import { demoDatasetMetadata } from '@charts-poc/demo-data/metadata' +import { demoDatasetMetadata } from '@tanstack/charts-data/metadata' import { autoTypeValue, parseCsvRows, @@ -63,7 +63,7 @@ describe('demo data', () => { expect(dataset.schema.map(({ name }) => name)).toEqual(dataset.fields) expect(dataset.sha256).toMatch(/^[a-f0-9]{64}$/u) expect(dataset.observableRevision).toMatch(/^[a-f0-9]{40}$/u) - expect(dataset.specifier).toBe(`@charts-poc/demo-data/${dataset.id}`) + expect(dataset.specifier).toBe(`@tanstack/charts-data/${dataset.id}`) } }) @@ -72,7 +72,7 @@ describe('demo data', () => { absWorkingDir: workspace, stdin: { contents: - "import { alphabet } from '@charts-poc/demo-data/alphabet'; console.log(alphabet.length)", + "import { alphabet } from '@tanstack/charts-data/alphabet'; console.log(alphabet.length)", resolveDir: workspace, }, bundle: true, @@ -100,7 +100,7 @@ describe('demo data', () => { absWorkingDir: workspace, stdin: { contents: - "import { olympians } from '@charts-poc/demo-data/olympians'; console.log(olympians.length)", + "import { olympians } from '@tanstack/charts-data/olympians'; console.log(olympians.length)", resolveDir: workspace, }, bundle: true, diff --git a/scripts/generate-shadcn-cases.mjs b/scripts/generate-shadcn-cases.mjs index 8cbeffdd..8266feb2 100644 --- a/scripts/generate-shadcn-cases.mjs +++ b/scripts/generate-shadcn-cases.mjs @@ -1,11 +1,7 @@ -import { mkdir, readFile, writeFile } from 'node:fs/promises' +import { access, mkdir, readFile, writeFile } from 'node:fs/promises' import path from 'node:path' import { format } from 'prettier' -import { getShadcnCatalogSpec } from '@charts-poc/demo-data/shadcn' -import { - shadcnExampleSource, - shadcnExampleStyles, -} from './shadcn-example-source.mjs' +import { getShadcnCatalogSpec } from '@tanstack/charts-data/shadcn' const root = path.resolve(import.meta.dirname, '..') const catalogPath = path.join( @@ -57,7 +53,6 @@ const ConformanceExample = ({ input }: { input: ConformanceInput }) => export * from './example' export const shadcnDefinition = definition -${legacyDefinitionAlias(entry.name)} export const mount = shadcnChartMount(ConformanceExample) export const catalogCase = tanstackExampleMount( () => definition, @@ -68,32 +63,14 @@ export const catalogCase = tanstackExampleMount( { parser: 'typescript', semi: false, singleQuote: true }, ), ) - await writeFile( - path.join(directory, 'example.tsx'), - await shadcnExampleSource(getShadcnCatalogSpec(entry.name)), - ) - await writeFile( - path.join(directory, 'styles.css'), - await shadcnExampleStyles(), - ) + await access(path.join(directory, 'example.tsx')) + await access(path.join(directory, 'styles.css')) await writeFile( path.join(directory, 'recharts.ts'), `import { createShadcnRechartsExample } from '../../shared/shadcn-catalog-recharts'\n\nconst example = createShadcnRechartsExample('${entry.name}')\n\nexport const mount = example.mount\n`, ) } -function legacyDefinitionAlias(name) { - const aliases = { - 'chart-bar-multiple': 'barMultipleDefinition', - 'chart-pie-donut-text': 'pieDonutTextDefinition', - 'chart-radar-multiple': 'radarMultipleDefinition', - 'chart-radial-text': 'radialTextDefinition', - 'chart-tooltip-advanced': 'advancedTooltipDefinition', - } - const alias = aliases[name] - return alias ? `export const ${alias} = definition` : '' -} - await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`) await syncDefinitionCoverage() console.log(`Synchronized ${generatedCount} generated shadcn chart cases.`) diff --git a/scripts/public-callback-contract.mjs b/scripts/public-callback-contract.mjs index 875ee1a2..5855a6a3 100644 --- a/scripts/public-callback-contract.mjs +++ b/scripts/public-callback-contract.mjs @@ -71,6 +71,10 @@ const callbackInventory = { 'measureText onFocusChange onFocusGroupChange onRender onSelect onTooltipBodyChange', ], ['@tanstack/charts:src/dom-types.ts:ChartRenderer', 'mount.requestRender'], + [ + '@tanstack/charts:src/dom-types.ts:UniversalChartRenderer', + 'mount.requestRender', + ], [ '@tanstack/charts:src/dom-types.ts:ChartSurface', 'subscribePresentationPoints.listener', @@ -368,6 +372,7 @@ const callbackInventory = { ], ['@tanstack/charts:src/types.ts:ResponsiveChartConfig', 'chart'], ['@tanstack/charts:src/types.ts:ResponsiveChartDefinition', 'chart'], + ['@tanstack/charts:src/scene.ts:DefinedResponsiveChart', 'chart'], ['@tanstack/charts:src/types.ts:InitializedMark', 'render resolveLayout'], [ '@tanstack/charts:src/types.ts:InitializedMarkBase', @@ -606,6 +611,10 @@ const callbackInventory = { ], ['@tanstack/charts:src/dom-types.ts:ChartHost', 'destroy getScene update'], ['@tanstack/charts:src/dom-types.ts:ChartRenderer', 'mount prerender'], + [ + '@tanstack/charts:src/dom-types.ts:UniversalChartRenderer', + 'mount prerender', + ], [ '@tanstack/charts:src/dom-types.ts:ChartRendererHost', 'destroy getScene update', diff --git a/scripts/shadcn-example-source.mjs b/scripts/shadcn-example-source.mjs deleted file mode 100644 index 559d8de8..00000000 --- a/scripts/shadcn-example-source.mjs +++ /dev/null @@ -1,858 +0,0 @@ -import { readFile } from 'node:fs/promises' -import path from 'node:path' -import ts from 'typescript' -import { format } from 'prettier' -import { removeUnusedTypeScript } from './typescript-source.mjs' - -const root = path.resolve(import.meta.dirname, '..') -const implementationPath = path.join( - root, - 'benchmarks/conformance/shared/shadcn-catalog-tanstack.tsx', -) -const cardPath = path.join( - root, - 'benchmarks/conformance/shared/shadcn-chart-card.tsx', -) -const implementationSource = await readFile(implementationPath, 'utf8') -const implementationFile = ts.createSourceFile( - implementationPath, - implementationSource, - ts.ScriptTarget.Latest, - true, - ts.ScriptKind.TSX, -) -const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }) - -const functions = new Map() -const variables = new Map() -for (const statement of implementationFile.statements) { - if (ts.isFunctionDeclaration(statement) && statement.name) { - functions.set(statement.name.text, statement) - } - if ( - ts.isVariableStatement(statement) && - statement.declarationList.declarations.length === 1 - ) { - const declaration = statement.declarationList.declarations[0] - if (ts.isIdentifier(declaration.name)) { - variables.set(declaration.name.text, statement) - } - } -} - -const horizontalVariants = new Set(['horizontal', 'label-custom', 'mixed']) - -export async function shadcnExampleSource(spec) { - const definitionSource = definitionFor(spec) - const componentSource = componentFor(spec) - const body = `${definitionSource}\n\n${componentSource}` - .replaceAll(/\.\.\.\[\],?/gu, '') - .replaceAll(/\.\.\.\{\},?/gu, '') - const imports = importsFor(body) - const formatted = await format( - `${imports}\nimport './styles.css'\n\n${body}`, - { parser: 'typescript', semi: false, singleQuote: true }, - ) - const cleaned = await cleanupGeneratedSource(formatted) - return format( - removeUnusedTypeScript( - cleaned, - path.join( - root, - 'benchmarks/conformance/cases', - `generated-${spec.name}`, - 'example.tsx', - ), - ), - { parser: 'typescript', semi: false, singleQuote: true }, - ) -} - -async function cleanupGeneratedSource(source) { - let file = ts.createSourceFile( - 'example.tsx', - source, - ts.ScriptTarget.Latest, - true, - ts.ScriptKind.TSX, - ) - for (let pass = 0; pass < 3; pass += 1) { - const result = ts.transform(file, [ - (context) => { - const visit = (node) => { - const visited = ts.visitEachChild(node, visit, context) - if (ts.isArrayLiteralExpression(visited)) { - return ts.factory.updateArrayLiteralExpression( - visited, - visited.elements.flatMap((element) => - ts.isSpreadElement(element) && - ts.isArrayLiteralExpression(element.expression) - ? [...element.expression.elements] - : [element], - ), - ) - } - return visited - } - return (node) => ts.visitNode(node, visit) - }, - ]) - file = result.transformed[0] - result.dispose() - } - return format(printer.printFile(file), { - parser: 'typescript', - semi: false, - singleQuote: true, - }) -} - -export async function shadcnExampleStyles() { - const cardSource = await readFile(cardPath, 'utf8') - const match = cardSource.match( - /export const shadcnChartCardStyles = `([\s\S]*?)`\s*$/u, - ) - if (!match) throw new Error('Could not read the shadcn chart-card styles.') - return format(`${match[1].trim()}\n`, { parser: 'css', singleQuote: true }) -} - -function definitionFor(spec) { - const interactive = spec.variant === 'interactive' - const rootName = interactive - ? { - area: 'buildInteractiveAreaDefinition', - bar: 'buildInteractiveBarDefinition', - line: 'buildInteractiveLineDefinition', - pie: 'buildInteractivePieDefinition', - }[spec.family] - : { - area: 'buildAreaDefinition', - bar: 'buildBarDefinition', - line: 'buildLineDefinition', - pie: 'buildPieDefinition', - radar: 'buildRadarDefinition', - radial: 'buildRadialDefinition', - tooltip: 'buildTooltipDefinition', - }[spec.family] - if (!rootName) throw new Error(`Unsupported shadcn example ${spec.name}`) - - const functionNames = new Set([rootName]) - if (!interactive && spec.family === 'area') { - functionNames.add('shadcnPointXAxis').add('shadcnTheme') - } - if (!interactive && spec.family === 'bar') { - if (spec.variant === 'multiple') functionNames.add('groupedBarDefinition') - functionNames - .add('shadcnXAxis') - .add('shadcnBrowserXAxis') - .add('shadcnBrowserYAxis') - .add('shadcnTheme') - .add('titleCase') - } - if (!interactive && spec.family === 'line') { - functionNames.add('shadcnPointXAxis').add('shadcnTheme').add('titleCase') - } - if (!interactive && spec.family === 'pie') { - if (spec.variant === 'stacked') - functionNames.add('buildStackedPieDefinition') - functionNames.add('titleCase') - } - if (spec.family === 'radial') { - functionNames - .add('buildSingleRadialDefinition') - .add('buildStackedRadialDefinition') - .add('radialCenterLabels') - .add('rechartsPolarAngle') - .add('titleCase') - } - if (interactive && spec.family === 'area') { - functionNames - .add('filterInteractiveAreaRows') - .add('interactiveDateTicks') - .add('formatMonthDay') - .add('shadcnTheme') - } - if (interactive && (spec.family === 'bar' || spec.family === 'line')) { - functionNames.add('formatMonthDay').add('shadcnTheme') - } - if (spec.family === 'tooltip') { - functionNames.add('formatWeekday').add('shadcnTheme').add('titleCase') - } else { - functionNames - .add('shadcnTooltipContent') - .add('browserMetric') - .add('titleCase') - } - if (spec.family === 'tooltip') { - functionNames.add('ShadcnTooltipBody').add('ShadcnActivityIcon') - } - - const variableNames = new Set([ - 'monthSeries', - 'twoSeries', - 'browserNames', - 'activityNames', - 'horizontalVariants', - 'interactiveAreaRows', - 'interactiveBarRows', - 'interactivePieRows', - ]) - const printedFunctions = [...functionNames] - .map((name) => { - const declaration = functions.get(name) - if (!declaration) throw new Error(`Missing shadcn helper ${name}`) - return printSpecializedFunction(declaration, spec, name === rootName) - }) - .join('\n\n') - const selectedVariables = new Set() - let variableSearchSource = printedFunctions - for (let pass = 0; pass < variableNames.size; pass += 1) { - for (const name of variableNames) { - if ( - selectedVariables.has(name) || - !new RegExp(`\\b${name}\\b`, 'u').test(variableSearchSource) - ) { - continue - } - selectedVariables.add(name) - variableSearchSource += `\n${printer.printNode( - ts.EmitHint.Unspecified, - variables.get(name), - implementationFile, - )}` - } - } - const usedVariables = [...selectedVariables] - .sort( - (left, right) => - variables.get(left).getStart(implementationFile) - - variables.get(right).getStart(implementationFile), - ) - .map((name) => - printer.printNode( - ts.EmitHint.Unspecified, - variables.get(name), - implementationFile, - ), - ) - .join('\n') - - const state = interactiveState(spec) - const focus = - spec.family === 'pie' || spec.family === 'radar' || spec.family === 'radial' - ? 'focusGroupAngle' - : "'group-x'" - const tooltipContent = - spec.family === 'tooltip' - ? '() => ({ rows: [] })' - : '(points) => shadcnTooltipContent(points)' - const createCall = state - ? `createDefinition(${state.parameter})` - : 'createDefinition()' - const createSignature = state - ? `(${state.parameter}: ${state.type} = ${state.defaultValue})` - : '()' - - return `${typeAliasesFor(spec)}${usedVariables}\n\n${printedFunctions}\n\nexport function createExampleChart${createSignature} { - return defineChart(${createCall}, { - svgAnimation: false, - focus: ${focus}, - keyboard: ${spec.family !== 'radial'}, - tooltip: { - use: tooltip, - className: 'sc-chart-tooltip', - anchor: ${spec.family === 'tooltip' ? '(_points, context) => ({ x: context.surface.width * 0.271, y: context.surface.height * 0.554 })' : "'group-center'"}, - placement: ${spec.family === 'tooltip' ? "'bottom-right'" : "'auto'"}, - offset: ${spec.family === 'tooltip' ? '0' : 'undefined'}, - sort: 'color-domain', - content: ${tooltipContent}, - }, - }) -} - -export const definition = createExampleChart() - -type ExampleDefinition = ReturnType -type ExampleDatum = ExampleDefinition extends DomChartDefinition ? TDatum : never -type ExampleXValue = ExampleDefinition extends DomChartDefinition ? TXValue : never -type ExampleYValue = ExampleDefinition extends DomChartDefinition ? TYValue : never` -} - -function printSpecializedFunction(declaration, spec, isRoot) { - let transformed = declaration - for (let index = 0; index < 3; index += 1) { - transformed = transformFunction(transformed, spec) - } - transformed = removeSpecParameter(transformed) - transformed = removeUnusedFunctionConstants(transformed) - let source = printer.printNode( - ts.EmitHint.Unspecified, - transformed, - implementationFile, - ) - if (isRoot) { - source = source.replace( - /^function\s+[A-Za-z_$][\w$]*/u, - 'function createDefinition', - ) - } - if (spec.family === 'bar' && spec.variant === 'negative') { - source = source.replace( - /\n\s*text:\s*\(row\)\s*=>\s*row\.desktop\.toLocaleString\(["']en-US["']\),/u, - '', - ) - } - for (const name of ['dotMarks', 'labelMarks']) { - const emptyDeclaration = new RegExp( - `\\n?\\s*const\\s+${name}\\s*=\\s*\\[\\];?`, - 'u', - ) - if (!emptyDeclaration.test(source)) continue - source = source - .replace(emptyDeclaration, '') - .replace(new RegExp(`\\.\\.\\.${name},?`, 'gu'), '') - } - source = source.replaceAll(/,?\s*\.\.\.\[\]/gu, '') - return source -} - -function transformFunction(declaration, spec) { - const constants = collectPrimitiveConstants(declaration, spec) - const result = ts.transform(declaration, [ - (context) => { - const visit = (node) => { - if ( - ts.isPropertyAccessExpression(node) && - ts.isIdentifier(node.expression) && - node.expression.text === 'spec' - ) { - return literal(spec[node.name.text]) - } - const visited = ts.visitEachChild(node, visit, context) - if (ts.isIfStatement(visited)) { - const value = evaluate(visited.expression, constants) - if (typeof value === 'boolean') { - const selected = value - ? visited.thenStatement - : visited.elseStatement - if (!selected) return ts.factory.createEmptyStatement() - return ts.isBlock(selected) ? [...selected.statements] : selected - } - } - if (ts.isConditionalExpression(visited)) { - const value = evaluate(visited.condition, constants) - if (typeof value === 'boolean') { - return value ? visited.whenTrue : visited.whenFalse - } - } - if (ts.isBinaryExpression(visited)) { - const value = evaluate(visited, constants) - if (typeof value === 'boolean') return literal(value) - } - if (ts.isArrayLiteralExpression(visited)) { - return ts.factory.updateArrayLiteralExpression( - visited, - visited.elements.flatMap((element) => - ts.isSpreadElement(element) && - ts.isArrayLiteralExpression(element.expression) - ? [...element.expression.elements] - : [element], - ), - ) - } - if (ts.isObjectLiteralExpression(visited)) { - const flattened = visited.properties.flatMap((property) => - ts.isSpreadAssignment(property) && - ts.isObjectLiteralExpression(property.expression) - ? [...property.expression.properties] - : [property], - ) - const lastPropertyIndex = new Map() - flattened.forEach((property, index) => { - if ( - (ts.isPropertyAssignment(property) || - ts.isShorthandPropertyAssignment(property)) && - (ts.isIdentifier(property.name) || - ts.isStringLiteral(property.name)) - ) { - lastPropertyIndex.set(property.name.text, index) - } - }) - return ts.factory.updateObjectLiteralExpression( - visited, - flattened.filter((property, index) => { - if ( - (ts.isPropertyAssignment(property) || - ts.isShorthandPropertyAssignment(property)) && - (ts.isIdentifier(property.name) || - ts.isStringLiteral(property.name)) - ) { - return lastPropertyIndex.get(property.name.text) === index - } - return true - }), - ) - } - if (ts.isBlock(visited)) { - const statements = [] - for (const statement of visited.statements) { - if (ts.isEmptyStatement(statement)) continue - statements.push(statement) - if ( - ts.isReturnStatement(statement) || - ts.isThrowStatement(statement) - ) - break - } - return ts.factory.updateBlock(visited, statements) - } - return visited - } - return (node) => ts.visitNode(node, visit) - }, - ]) - const transformed = result.transformed[0] - result.dispose() - return transformed -} - -function removeSpecParameter(declaration) { - return ts.factory.updateFunctionDeclaration( - declaration, - declaration.modifiers, - declaration.asteriskToken, - declaration.name, - declaration.typeParameters, - declaration.parameters.filter( - (parameter) => - !(ts.isIdentifier(parameter.name) && parameter.name.text === 'spec'), - ), - declaration.type, - declaration.body, - ) -} - -function removeUnusedFunctionConstants(declaration) { - if (!declaration.body) return declaration - let statements = [...declaration.body.statements] - for (let pass = 0; pass < 4; pass += 1) { - const used = identifierNames( - statements - .map((statement) => - printer.printNode( - ts.EmitHint.Unspecified, - statement, - implementationFile, - ), - ) - .join('\n'), - { excludeDeclarations: true }, - ) - statements = statements.filter((statement) => { - if ( - !ts.isVariableStatement(statement) || - statement.declarationList.declarations.length !== 1 - ) { - return true - } - const item = statement.declarationList.declarations[0] - return !ts.isIdentifier(item.name) || used.has(item.name.text) - }) - } - return ts.factory.updateFunctionDeclaration( - declaration, - declaration.modifiers, - declaration.asteriskToken, - declaration.name, - declaration.typeParameters, - declaration.parameters, - declaration.type, - ts.factory.updateBlock(declaration.body, statements), - ) -} - -function collectPrimitiveConstants(declaration, spec) { - const constants = new Map() - const body = declaration.body - if (!body) return constants - for (let pass = 0; pass < 4; pass += 1) { - for (const statement of body.statements) { - if (!ts.isVariableStatement(statement)) continue - for (const item of statement.declarationList.declarations) { - if (!ts.isIdentifier(item.name) || !item.initializer) continue - const value = evaluate(item.initializer, constants, spec) - if ( - typeof value === 'boolean' || - typeof value === 'string' || - typeof value === 'number' - ) { - constants.set(item.name.text, value) - } - } - } - } - return constants -} - -function evaluate(node, constants, spec) { - if (ts.isParenthesizedExpression(node)) { - return evaluate(node.expression, constants, spec) - } - if (ts.isStringLiteral(node) || ts.isNumericLiteral(node)) return node.text - if (node.kind === ts.SyntaxKind.TrueKeyword) return true - if (node.kind === ts.SyntaxKind.FalseKeyword) return false - if (ts.isIdentifier(node)) return constants.get(node.text) - if ( - ts.isPropertyAccessExpression(node) && - ts.isIdentifier(node.expression) && - node.expression.text === 'spec' - ) { - return spec?.[node.name.text] - } - if ( - ts.isPrefixUnaryExpression(node) && - node.operator === ts.SyntaxKind.ExclamationToken - ) { - const value = evaluate(node.operand, constants, spec) - return typeof value === 'boolean' ? !value : undefined - } - if (ts.isBinaryExpression(node)) { - const left = evaluate(node.left, constants, spec) - const right = evaluate(node.right, constants, spec) - if ( - left !== undefined && - right !== undefined && - node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken - ) - return left === right - if ( - left !== undefined && - right !== undefined && - node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken - ) - return left !== right - if (node.operatorToken.kind === ts.SyntaxKind.BarBarToken) { - return typeof left === 'boolean' && typeof right === 'boolean' - ? left || right - : undefined - } - if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) { - return typeof left === 'boolean' && typeof right === 'boolean' - ? left && right - : undefined - } - } - if ( - ts.isCallExpression(node) && - ts.isPropertyAccessExpression(node.expression) && - node.arguments.length === 1 - ) { - const receiver = evaluate(node.expression.expression, constants, spec) - const argument = evaluate(node.arguments[0], constants, spec) - if (typeof receiver === 'string' && typeof argument === 'string') { - if (node.expression.name.text === 'includes') - return receiver.includes(argument) - if (node.expression.name.text === 'startsWith') - return receiver.startsWith(argument) - } - if ( - ts.isIdentifier(node.expression.expression) && - node.expression.expression.text === 'horizontalVariants' && - node.expression.name.text === 'has' && - typeof argument === 'string' - ) { - return horizontalVariants.has(argument) - } - } - return undefined -} - -function literal(value) { - if (typeof value === 'string') return ts.factory.createStringLiteral(value) - if (typeof value === 'number') return ts.factory.createNumericLiteral(value) - if (typeof value === 'boolean') - return value ? ts.factory.createTrue() : ts.factory.createFalse() - return ts.factory.createIdentifier('undefined') -} - -function typeAliasesFor(spec) { - if (spec.variant !== 'interactive') return '' - if (spec.family === 'area') { - return "type InteractiveTimeRange = '90d' | '30d' | '7d'\n\n" - } - if (spec.family === 'bar' || spec.family === 'line') { - return "type InteractiveSeries = 'desktop' | 'mobile'\n\n" - } - return '' -} - -function interactiveState(spec) { - if (spec.variant !== 'interactive') return undefined - if (spec.family === 'area') { - return { - parameter: 'timeRange', - type: 'InteractiveTimeRange', - defaultValue: "'90d'", - } - } - if (spec.family === 'bar' || spec.family === 'line') { - return { - parameter: 'activeSeries', - type: 'InteractiveSeries', - defaultValue: "'desktop'", - } - } - return { parameter: 'activeMonth', type: 'string', defaultValue: "'january'" } -} - -function importsFor(source) { - const usedIdentifiers = identifierNames(source) - const groups = new Map() - const imports = { - react: ['useMemo', 'useRef', 'useState'], - '@tanstack/charts': [ - 'areaY', - 'barX', - 'barY', - 'd3Curve', - 'defineChart', - 'dot', - 'group', - 'lineY', - 'stack', - 'text', - 'type ChartPoint', - 'type ChartValue', - 'type DomChartDefinition', - ], - '@tanstack/charts/polar': [ - 'angleGrid', - 'focusGroupAngle', - 'pie', - 'polar', - 'radialArc', - 'radialArea', - 'radialBarAngle', - 'radialDot', - 'radialGrid', - 'radialRule', - 'radialText', - ], - '@tanstack/charts/react/tooltip': ['RendererChart'], - '@tanstack/charts/tooltip': ['tooltip'], - '@tanstack/charts/motion': ['motion'], - 'd3-scale': ['scaleBand', 'scaleLinear', 'scalePoint'], - 'd3-shape': [ - 'curveLinear', - 'curveLinearClosed', - 'curveMonotoneX', - 'curveNatural', - 'curveStep', - ], - '@charts-poc/demo-data/shadcn': [ - 'shadcnActivities', - 'shadcnBrowsers', - 'shadcnColors', - 'shadcnMonths', - 'shadcnRadarDefault', - 'shadcnRadarFilled', - 'shadcnRadarLines', - 'shadcnRadarMultiple', - 'shadcnSeriesRows', - 'type ShadcnActivityDatum', - 'type ShadcnBrowserDatum', - 'type ShadcnMonthDatum', - 'type ShadcnSeriesDatum', - ], - } - for (const [module, names] of Object.entries(imports)) { - const used = names.filter((entry) => { - const name = entry.replace(/^type\s+/u, '') - return usedIdentifiers.has(name) - }) - if (used.length > 0) groups.set(module, used) - } - if (/\binteractiveAreaData\b/u.test(source)) { - groups.set('@charts-poc/demo-data/shadcn-area-interactive-data', [ - 'default:interactiveAreaData', - ]) - } - return [...groups] - .map(([module, names]) => { - const defaultImport = names.find((name) => name.startsWith('default:')) - const named = names.filter((name) => !name.startsWith('default:')) - if (defaultImport) - return `import ${defaultImport.slice(8)} from '${module}'` - return `import { ${named.join(', ')} } from '${module}'` - }) - .join('\n') -} - -function identifierNames(source, options = {}) { - const file = ts.createSourceFile( - 'generated.tsx', - source, - ts.ScriptTarget.Latest, - true, - ts.ScriptKind.TSX, - ) - const names = new Set() - const visit = (node) => { - if (ts.isIdentifier(node)) { - const parent = node.parent - const declarationName = - (ts.isVariableDeclaration(parent) || - ts.isParameter(parent) || - ts.isFunctionDeclaration(parent)) && - parent.name === node - const propertyName = - (ts.isPropertyAssignment(parent) || - ts.isMethodDeclaration(parent) || - ts.isPropertyAccessExpression(parent)) && - parent.name === node - if ((!options.excludeDeclarations || !declarationName) && !propertyName) { - names.add(node.text) - } - } - ts.forEachChild(node, visit) - } - visit(file) - return names -} - -function componentFor(spec) { - const interactive = spec.variant === 'interactive' - const state = interactiveState(spec) - const stateSetup = !state - ? '' - : spec.family === 'area' - ? "const [timeRange, setTimeRange] = useState('90d')" - : spec.family === 'bar' || spec.family === 'line' - ? "const [activeSeries, setActiveSeries] = useState('desktop')" - : "const [activeMonth, setActiveMonth] = useState('january')" - const stateValue = state?.parameter - const chartDefinition = state - ? `useMemo(() => createExampleChart(${stateValue}), [${stateValue}])` - : 'definition' - const headerAction = !interactive - ? 'null' - : spec.family === 'area' - ? ` setTimeRange(value as InteractiveTimeRange)} options={[{ value: '90d', label: 'Last 3 months' }, { value: '30d', label: 'Last 30 days' }, { value: '7d', label: 'Last 7 days' }]} />` - : spec.family === 'bar' || spec.family === 'line' - ? '' - : ` ({ value: row.browser, label: titleCase(row.browser), swatch: shadcnColors[index] }))} />` - const square = spec.square - const variant = interactive ? `interactive-${spec.family}` : 'default' - const footer = - spec.family === 'tooltip' || - interactive || - (spec.family === 'pie' && spec.variant === 'legend') - ? 'null' - : `` - const legend = spec.legend ? '' : 'null' - const chartProps = - spec.family === 'tooltip' - ? `onRender={({ scene, interaction }) => { - if (seededTooltip.current) return - const point = scene.points.find((candidate) => (candidate.datum as ShadcnActivityDatum).date === '2024-07-16') - if (!point) return - seededTooltip.current = true - interaction.setControlledFocus(point, { source: 'programmatic' }) - }} - renderTooltipBody={({ points }) => []} variant=${JSON.stringify(spec.variant)} />}` - : '' - const tooltipRef = - spec.family === 'tooltip' ? 'const seededTooltip = useRef(false)' : '' - const helperSource = componentHelpers(spec) - - return `export interface ExampleProps { width?: number; height?: number } - -export default function Example({ width = 640, height = 600 }: ExampleProps) { - ${stateSetup} - ${tooltipRef} - const chartDefinition = ${chartDefinition} - const renderer = useMemo(() => motion({ initial: 'always', transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 } }), []) - const contentWidth = Math.max(1, width - 50) - const chartWidth = ${square ? `Math.min(${interactive && spec.family === 'pie' ? 300 : 250}, contentWidth)` : 'contentWidth'} - const chartHeight = ${ - square - ? 'chartWidth' - : interactive && ['area', 'bar', 'line'].includes(spec.family) - ? '250' - : spec.legend - ? '(contentWidth * 9) / 16 - 27' - : '(contentWidth * 9) / 16' - } - const headerAction = ${headerAction} - const legend = ${legend} - const footer = ${footer} - - return ( -
-
-
-

${escapeJsx(spec.title)}

${escapeJsx(spec.description)}

- {headerAction ?
{headerAction}
: null} -
-
-
- -
- {legend ?
{legend}
: null} -
- {footer ?
{footer}
: null} -
-
- ) -} - -${helperSource}` -} - -function componentHelpers(spec) { - const helpers = [] - if (spec.legend) { - const labels = - spec.family === 'pie' || spec.family === 'radial' - ? "['chrome', 'safari', 'firefox', 'edge', 'other']" - : "['desktop', 'mobile']" - helpers.push(`function Legend() { - return <>{${labels}.map((label, index) => ${spec.variant === 'icons' ? '' : ''}{titleCase(label)})} -}`) - } - if ( - spec.family !== 'tooltip' && - spec.variant !== 'interactive' && - !(spec.family === 'pie' && spec.variant === 'legend') - ) { - helpers.push(`function TrendFooter({ note }: { note: string }) { - return <>
Trending up by 5.2% this month
{note}
-}`) - } - if ( - spec.variant === 'interactive' && - (spec.family === 'area' || spec.family === 'pie') - ) { - helpers.push(`function SelectControl({ value, options, onChange }: { value: string; options: readonly { value: string; label: string; swatch?: string }[]; onChange: (value: string) => void }) { - const selected = options.find((option) => option.value === value) - return -}`) - } - if ( - spec.variant === 'interactive' && - (spec.family === 'bar' || spec.family === 'line') - ) { - helpers.push(`function BarMetrics({ active, onChange }: { active: InteractiveSeries; onChange: (series: InteractiveSeries) => void }) { - const totals = { desktop: interactiveBarRows.reduce((sum, row) => sum + row.desktop, 0), mobile: interactiveBarRows.reduce((sum, row) => sum + row.mobile, 0) } - return <>{twoSeries.map((series) => )} -}`) - } - return helpers.join('\n\n') -} - -function escapeJsx(value) { - return value - .replaceAll('&', '&') - .replaceAll('<', '<') - .replaceAll('>', '>') -} diff --git a/scripts/sync-demo-data.mjs b/scripts/sync-demo-data.mjs index eba0e30e..84089048 100644 --- a/scripts/sync-demo-data.mjs +++ b/scripts/sync-demo-data.mjs @@ -294,7 +294,7 @@ for (const dataset of datasets) { metadata.push({ id: dataset.id, title: dataset.title, - specifier: `@charts-poc/demo-data/${dataset.id}`, + specifier: `@tanstack/charts-data/${dataset.id}`, format: dataset.file.endsWith('.csv') ? 'CSV' : 'JSON', records, fields, From b9310e5c833f59b54807b401c2de292faab8189f Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Sat, 15 Aug 2026 00:13:53 -0600 Subject: [PATCH 2/3] Update bundle benchmark baseline --- benchmarks/comparison/bundle-baseline.json | 128 ++++++++++----------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/benchmarks/comparison/bundle-baseline.json b/benchmarks/comparison/bundle-baseline.json index 25ca8b2b..bdbb4946 100644 --- a/benchmarks/comparison/bundle-baseline.json +++ b/benchmarks/comparison/bundle-baseline.json @@ -1,8 +1,8 @@ { "schemaVersion": 4, - "generatedAt": "2026-08-14T05:55:21.257Z", + "generatedAt": "2026-08-15T06:11:41.238Z", "packageVersions": { - "tanstack": "0.12.0", + "tanstack": "0.13.0", "chartjs": "4.5.1", "echarts": "6.1.0", "recharts": "3.10.1", @@ -11,8 +11,8 @@ "sources": { "tanstack": { "kind": "workspace", - "revision": "56567ec51902d8af0d0d730f3a31206999cc8438", - "inputDigest": "sha256:6755913ae5f9c34a2bbb1ccb7cd2144274bc37d74051c091fc279ac3d1d7a4cd" + "revision": "91e2eef1772dc06118ce5aa1e0b388d12bf91918", + "inputDigest": "sha256:d3480809cd111f9acf9bbaf58be2b4f42bc56c4a748fcc151d49025a2c444e88" }, "chartjs": { "kind": "package", @@ -45,88 +45,88 @@ }, "bundles": { "tanstack-line-basic": { - "minifiedBytes": 105944, - "gzipBytes": 38533, - "brotliBytes": 34109, - "incrementalGzipBytes": 38533, - "incrementalBrotliBytes": 34109 + "minifiedBytes": 105980, + "gzipBytes": 38537, + "brotliBytes": 34114, + "incrementalGzipBytes": 38537, + "incrementalBrotliBytes": 34114 }, "tanstack-line-interactive": { - "minifiedBytes": 111385, - "gzipBytes": 40302, - "brotliBytes": 35551, - "incrementalGzipBytes": 40302, - "incrementalBrotliBytes": 35551 + "minifiedBytes": 111421, + "gzipBytes": 40306, + "brotliBytes": 35539, + "incrementalGzipBytes": 40306, + "incrementalBrotliBytes": 35539 }, "tanstack-line-advanced": { - "minifiedBytes": 118575, - "gzipBytes": 42629, - "brotliBytes": 37541, - "incrementalGzipBytes": 42629, - "incrementalBrotliBytes": 37541 + "minifiedBytes": 118611, + "gzipBytes": 42632, + "brotliBytes": 37568, + "incrementalGzipBytes": 42632, + "incrementalBrotliBytes": 37568 }, "tanstack-bar-basic": { - "minifiedBytes": 114612, - "gzipBytes": 41793, - "brotliBytes": 36837, - "incrementalGzipBytes": 41793, - "incrementalBrotliBytes": 36837 + "minifiedBytes": 114648, + "gzipBytes": 41796, + "brotliBytes": 36865, + "incrementalGzipBytes": 41796, + "incrementalBrotliBytes": 36865 }, "tanstack-bar-interactive": { - "minifiedBytes": 118904, - "gzipBytes": 43127, - "brotliBytes": 37954, - "incrementalGzipBytes": 43127, - "incrementalBrotliBytes": 37954 + "minifiedBytes": 118940, + "gzipBytes": 43130, + "brotliBytes": 37969, + "incrementalGzipBytes": 43130, + "incrementalBrotliBytes": 37969 }, "tanstack-bar-advanced": { - "minifiedBytes": 119243, - "gzipBytes": 43268, - "brotliBytes": 38025, - "incrementalGzipBytes": 43268, - "incrementalBrotliBytes": 38025 + "minifiedBytes": 119279, + "gzipBytes": 43273, + "brotliBytes": 38033, + "incrementalGzipBytes": 43273, + "incrementalBrotliBytes": 38033 }, "tanstack-area-basic": { - "minifiedBytes": 111028, - "gzipBytes": 40457, - "brotliBytes": 35802, - "incrementalGzipBytes": 40457, - "incrementalBrotliBytes": 35802 + "minifiedBytes": 111064, + "gzipBytes": 40462, + "brotliBytes": 35868, + "incrementalGzipBytes": 40462, + "incrementalBrotliBytes": 35868 }, "tanstack-area-interactive": { - "minifiedBytes": 116469, - "gzipBytes": 42189, - "brotliBytes": 37272, - "incrementalGzipBytes": 42189, - "incrementalBrotliBytes": 37272 + "minifiedBytes": 116505, + "gzipBytes": 42194, + "brotliBytes": 37277, + "incrementalGzipBytes": 42194, + "incrementalBrotliBytes": 37277 }, "tanstack-area-advanced": { - "minifiedBytes": 123841, - "gzipBytes": 44639, - "brotliBytes": 39311, - "incrementalGzipBytes": 44639, - "incrementalBrotliBytes": 39311 + "minifiedBytes": 123877, + "gzipBytes": 44638, + "brotliBytes": 39304, + "incrementalGzipBytes": 44638, + "incrementalBrotliBytes": 39304 }, "tanstack-scatter-basic": { - "minifiedBytes": 106983, - "gzipBytes": 38919, - "brotliBytes": 34369, - "incrementalGzipBytes": 38919, - "incrementalBrotliBytes": 34369 + "minifiedBytes": 107019, + "gzipBytes": 38925, + "brotliBytes": 34417, + "incrementalGzipBytes": 38925, + "incrementalBrotliBytes": 34417 }, "tanstack-scatter-interactive": { - "minifiedBytes": 112424, - "gzipBytes": 40678, - "brotliBytes": 35859, - "incrementalGzipBytes": 40678, - "incrementalBrotliBytes": 35859 + "minifiedBytes": 112460, + "gzipBytes": 40681, + "brotliBytes": 35819, + "incrementalGzipBytes": 40681, + "incrementalBrotliBytes": 35819 }, "tanstack-scatter-advanced": { - "minifiedBytes": 112440, - "gzipBytes": 40683, - "brotliBytes": 35866, - "incrementalGzipBytes": 40683, - "incrementalBrotliBytes": 35866 + "minifiedBytes": 112476, + "gzipBytes": 40686, + "brotliBytes": 35826, + "incrementalGzipBytes": 40686, + "incrementalBrotliBytes": 35826 }, "chartjs-line-basic": { "minifiedBytes": 137909, From 78d89bb6a0848f239c1e7ea30d15245226d0df37 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Sat, 15 Aug 2026 00:23:56 -0600 Subject: [PATCH 3/3] Refresh bundle and docs baselines --- benchmarks/bundle-size/README.md | 2 +- .../bundle-size/universal-baseline.json | 32 +++++++++---------- docs/comparison.md | 6 ++-- packages/charts-core/docs/comparison.md | 6 ++-- scripts/measure-bundles.mjs | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/benchmarks/bundle-size/README.md b/benchmarks/bundle-size/README.md index 74df5685..bb9c0e54 100644 --- a/benchmarks/bundle-size/README.md +++ b/benchmarks/bundle-size/README.md @@ -42,7 +42,7 @@ of the default scene and host contracts. Default static SVG consumes scene clips and gradients. Their reviewed shared-path cost is recorded in the locked entries and the corresponding complete-consumer budgets. Rolling path planning remains confined to the opt-in motion renderer, whose complete SVG budget is -18.2 KiB gzip. +20.75 KiB gzip. Every public transform family has an isolated budget and retained-input allowlist. Numeric and 2D bins may retain `d3-array`, and row stacks may retain diff --git a/benchmarks/bundle-size/universal-baseline.json b/benchmarks/bundle-size/universal-baseline.json index 02d2cd6b..aa9bc680 100644 --- a/benchmarks/bundle-size/universal-baseline.json +++ b/benchmarks/bundle-size/universal-baseline.json @@ -3,16 +3,16 @@ "policy": "Exact minified and gzip output for entries that optional features must not affect. Review every change before updating.", "bundles": { "D3-scale line scene": { - "bytes": 47115, - "gzip": 17898 + "bytes": 47151, + "gzip": 17902 }, "D3-scale line + static SVG": { - "bytes": 51848, - "gzip": 19616 + "bytes": 51884, + "gzip": 19619 }, "Representative marks": { - "bytes": 71536, - "gzip": 26220 + "bytes": 71572, + "gzip": 26228 }, "TanStack DOM host": { "bytes": 70878, @@ -23,24 +23,24 @@ "gzip": 25621 }, "React line consumer": { - "bytes": 96231, - "gzip": 34868 + "bytes": 96267, + "gzip": 34866 }, "Compact-scale line scene": { - "bytes": 29572, - "gzip": 10769 + "bytes": 29608, + "gzip": 10773 }, "React compact-scale line consumer": { - "bytes": 78732, - "gzip": 27803 + "bytes": 78768, + "gzip": 27799 }, "Custom-scale line scene": { - "bytes": 27756, - "gzip": 10032 + "bytes": 27792, + "gzip": 10035 }, "D3 linear-scale line scene": { - "bytes": 47047, - "gzip": 17863 + "bytes": 47083, + "gzip": 17866 } } } diff --git a/docs/comparison.md b/docs/comparison.md index cf9a4427..8535e734 100644 --- a/docs/comparison.md +++ b/docs/comparison.md @@ -12,14 +12,14 @@ turning untested behavior into a checkmark. | Library | Package | Measured source | | -------------------------------------------------------------------------------------- | -------------------- | ------------------- | -| [TanStack Charts](./overview.md) | `@tanstack/charts` | workspace `56567ec` | +| [TanStack Charts](./overview.md) | `@tanstack/charts` | workspace `91e2eef` | | [Chart.js](https://www.chartjs.org/docs/latest/) | `chart.js` | npm `4.5.1` | | [Apache ECharts](https://echarts.apache.org/handbook/en/best-practices/canvas-vs-svg/) | `echarts` | npm `6.1.0` | | [Recharts](https://recharts.github.io/en-US/) | `recharts` | npm `3.10.1` | | [Observable Plot](https://observablehq.com/plot/features/plots) | `@observablehq/plot` | npm `0.6.17` | The competitor versions are exact package pins, not latest versions inferred -at page render time. The measured TanStack workspace revision is `56567ec`. +at page render time. The measured TanStack workspace revision is `91e2eef`. ## Capability matrix @@ -90,7 +90,7 @@ output model. ## Bundle snapshot -Baseline date: `2026-08-14`. +Baseline date: `2026-08-15`. Controlled ranges cover 12 independently built, minified browser consumers: line, bar, area, and scatter at basic, interactive, and advanced tiers. Only diff --git a/packages/charts-core/docs/comparison.md b/packages/charts-core/docs/comparison.md index cf9a4427..8535e734 100644 --- a/packages/charts-core/docs/comparison.md +++ b/packages/charts-core/docs/comparison.md @@ -12,14 +12,14 @@ turning untested behavior into a checkmark. | Library | Package | Measured source | | -------------------------------------------------------------------------------------- | -------------------- | ------------------- | -| [TanStack Charts](./overview.md) | `@tanstack/charts` | workspace `56567ec` | +| [TanStack Charts](./overview.md) | `@tanstack/charts` | workspace `91e2eef` | | [Chart.js](https://www.chartjs.org/docs/latest/) | `chart.js` | npm `4.5.1` | | [Apache ECharts](https://echarts.apache.org/handbook/en/best-practices/canvas-vs-svg/) | `echarts` | npm `6.1.0` | | [Recharts](https://recharts.github.io/en-US/) | `recharts` | npm `3.10.1` | | [Observable Plot](https://observablehq.com/plot/features/plots) | `@observablehq/plot` | npm `0.6.17` | The competitor versions are exact package pins, not latest versions inferred -at page render time. The measured TanStack workspace revision is `56567ec`. +at page render time. The measured TanStack workspace revision is `91e2eef`. ## Capability matrix @@ -90,7 +90,7 @@ output model. ## Bundle snapshot -Baseline date: `2026-08-14`. +Baseline date: `2026-08-15`. Controlled ranges cover 12 independently built, minified browser consumers: line, bar, area, and scatter at basic, interactive, and advanced tiers. Only diff --git a/scripts/measure-bundles.mjs b/scripts/measure-bundles.mjs index 8921fbde..f9e2e220 100644 --- a/scripts/measure-bundles.mjs +++ b/scripts/measure-bundles.mjs @@ -1688,7 +1688,7 @@ const entries = [ budgeted( 'Motion SVG renderer', 'benchmarks/entries/charts-motion-svg-renderer.ts', - 20.7, + 20.75, { rendererBoundary: 'svg', inputBoundary: {