@misoto22/folio 0.0.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/bin/folio-design.mjs +277 -0
- package/bin/migrate-legacy.mjs +81 -0
- package/dist/agent/Accordion.md +65 -0
- package/dist/agent/Actions.md +49 -0
- package/dist/agent/Alert.md +65 -0
- package/dist/agent/AppShell.md +69 -0
- package/dist/agent/ArchitectureFigure.md +72 -0
- package/dist/agent/AreaChart.md +94 -0
- package/dist/agent/Article.md +65 -0
- package/dist/agent/AspectRatio.md +58 -0
- package/dist/agent/Avatar.md +53 -0
- package/dist/agent/Badge.md +62 -0
- package/dist/agent/BarChart.md +93 -0
- package/dist/agent/BarList.md +67 -0
- package/dist/agent/BigNumber.md +70 -0
- package/dist/agent/BoxPlot.md +82 -0
- package/dist/agent/Breadcrumb.md +55 -0
- package/dist/agent/BulletChart.md +71 -0
- package/dist/agent/Button.md +81 -0
- package/dist/agent/Calendar.md +77 -0
- package/dist/agent/CalendarHeatmap.md +75 -0
- package/dist/agent/Card.md +72 -0
- package/dist/agent/Checkbox.md +57 -0
- package/dist/agent/Code.md +51 -0
- package/dist/agent/CodeBlock.md +77 -0
- package/dist/agent/Collapsible.md +68 -0
- package/dist/agent/Collection.md +169 -0
- package/dist/agent/ColorPicker.md +76 -0
- package/dist/agent/Combobox.md +77 -0
- package/dist/agent/Command.md +122 -0
- package/dist/agent/ComposedChart.md +82 -0
- package/dist/agent/Contact.md +90 -0
- package/dist/agent/Content.md +70 -0
- package/dist/agent/ContextMenu.md +93 -0
- package/dist/agent/Conversation.md +247 -0
- package/dist/agent/DataflowFigure.md +49 -0
- package/dist/agent/DatePicker.md +104 -0
- package/dist/agent/DescriptionList.md +69 -0
- package/dist/agent/Diagram.md +71 -0
- package/dist/agent/DiagramCanvas.md +71 -0
- package/dist/agent/DiagramExportMenu.md +65 -0
- package/dist/agent/DiagramInspector.md +73 -0
- package/dist/agent/DiagramLegend.md +56 -0
- package/dist/agent/DiagramMinimap.md +69 -0
- package/dist/agent/DiagramToolbar.md +70 -0
- package/dist/agent/Dialog.md +76 -0
- package/dist/agent/DropdownMenu.md +110 -0
- package/dist/agent/EmptyState.md +63 -0
- package/dist/agent/ErrorState.md +67 -0
- package/dist/agent/Evidence.md +165 -0
- package/dist/agent/Facet.md +107 -0
- package/dist/agent/Field.md +79 -0
- package/dist/agent/FigureBand.md +49 -0
- package/dist/agent/FloatingIconButton.md +61 -0
- package/dist/agent/FunnelChart.md +75 -0
- package/dist/agent/Heading.md +65 -0
- package/dist/agent/Heatmap.md +78 -0
- package/dist/agent/Histogram.md +88 -0
- package/dist/agent/Input.md +52 -0
- package/dist/agent/Kbd.md +48 -0
- package/dist/agent/LifecycleFigure.md +50 -0
- package/dist/agent/LineChart.md +85 -0
- package/dist/agent/LinkArrow.md +49 -0
- package/dist/agent/Markdown.md +69 -0
- package/dist/agent/Media.md +261 -0
- package/dist/agent/Metric.md +70 -0
- package/dist/agent/Metrics.md +114 -0
- package/dist/agent/Music.md +86 -0
- package/dist/agent/NativeSelect.md +62 -0
- package/dist/agent/NavItem.md +56 -0
- package/dist/agent/NumberField.md +73 -0
- package/dist/agent/PageHeader.md +69 -0
- package/dist/agent/Pagination.md +70 -0
- package/dist/agent/PieChart.md +80 -0
- package/dist/agent/Popover.md +80 -0
- package/dist/agent/Portfolio.md +93 -0
- package/dist/agent/PortfolioIndex.md +34 -0
- package/dist/agent/Progress.md +58 -0
- package/dist/agent/RadarChart.md +79 -0
- package/dist/agent/RadialChart.md +81 -0
- package/dist/agent/RadioGroup.md +66 -0
- package/dist/agent/Reading.md +233 -0
- package/dist/agent/Recovery.md +72 -0
- package/dist/agent/SankeyChart.md +85 -0
- package/dist/agent/ScatterChart.md +80 -0
- package/dist/agent/ScrollArea.md +62 -0
- package/dist/agent/SearchPalette.md +51 -0
- package/dist/agent/SearchableMenu.md +69 -0
- package/dist/agent/Select.md +102 -0
- package/dist/agent/Separator.md +60 -0
- package/dist/agent/SequenceFigure.md +51 -0
- package/dist/agent/Sheet.md +82 -0
- package/dist/agent/Sidebar.md +194 -0
- package/dist/agent/SiteNavigation.md +62 -0
- package/dist/agent/SiteShell.md +67 -0
- package/dist/agent/Skeleton.md +96 -0
- package/dist/agent/Slider.md +67 -0
- package/dist/agent/Sparkline.md +68 -0
- package/dist/agent/Spinner.md +62 -0
- package/dist/agent/StatusDot.md +56 -0
- package/dist/agent/StatusPill.md +55 -0
- package/dist/agent/Steps.md +68 -0
- package/dist/agent/Switch.md +50 -0
- package/dist/agent/Table.md +111 -0
- package/dist/agent/Tabs.md +71 -0
- package/dist/agent/Tag.md +67 -0
- package/dist/agent/Text.md +66 -0
- package/dist/agent/Textarea.md +46 -0
- package/dist/agent/Timeline.md +114 -0
- package/dist/agent/Timestamp.md +65 -0
- package/dist/agent/Toast.md +51 -0
- package/dist/agent/ToggleGroup.md +67 -0
- package/dist/agent/Toolbar.md +72 -0
- package/dist/agent/Tooltip.md +74 -0
- package/dist/agent/TreemapChart.md +76 -0
- package/dist/agent/WaterfallChart.md +86 -0
- package/dist/agent/WorkflowFigure.md +51 -0
- package/dist/agent/catalog.json +8006 -0
- package/dist/agent/index.md +182 -0
- package/dist/article.css +407 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +198 -0
- package/dist/charts/AreaChart/AreaChart.js +479 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +190 -0
- package/dist/charts/BarChart/BarChart.js +599 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +65 -0
- package/dist/charts/BarList/BarList.js +79 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +72 -0
- package/dist/charts/BigNumber/BigNumber.js +51 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +497 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +197 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.d.ts +106 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js +103 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +178 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +106 -0
- package/dist/charts/FunnelChart/FunnelChart.js +137 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +101 -0
- package/dist/charts/Heatmap/Heatmap.js +125 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +188 -0
- package/dist/charts/Histogram/Histogram.js +382 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +174 -0
- package/dist/charts/LineChart/LineChart.js +485 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +140 -0
- package/dist/charts/PieChart/PieChart.js +317 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +135 -0
- package/dist/charts/RadarChart/RadarChart.js +303 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +142 -0
- package/dist/charts/RadialChart/RadialChart.js +279 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +149 -0
- package/dist/charts/SankeyChart/SankeyChart.js +509 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +149 -0
- package/dist/charts/ScatterChart/ScatterChart.js +275 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +95 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +98 -0
- package/dist/charts/TreemapChart/TreemapChart.js +127 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +321 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +43 -0
- package/dist/charts/index.js +130 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +149 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +24 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +94 -0
- package/dist/charts/lib/export.js +62 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +81 -0
- package/dist/charts/lib/figure.js +62 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +144 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +43 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +58 -0
- package/dist/components/AppShell/AppShell.js +126 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Article/Article.d.ts +58 -0
- package/dist/components/Article/Article.js +34 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +38 -0
- package/dist/components/Avatar/Avatar.js +44 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +37 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +46 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +95 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +54 -0
- package/dist/components/Calendar/Calendar.js +369 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +55 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +26 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +145 -0
- package/dist/components/CodeBlock/CodeBlock.js +114 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +45 -0
- package/dist/components/Collapsible/Collapsible.js +60 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +77 -0
- package/dist/components/Combobox/Combobox.js +170 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +125 -0
- package/dist/components/Command/Command.js +204 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +63 -0
- package/dist/components/ContextMenu/ContextMenu.js +109 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +130 -0
- package/dist/components/DatePicker/DatePicker.js +257 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +86 -0
- package/dist/components/Diagram/Diagram.js +211 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +63 -0
- package/dist/components/Dialog/Dialog.js +90 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +87 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +120 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +55 -0
- package/dist/components/EmptyState/EmptyState.js +32 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +55 -0
- package/dist/components/ErrorState/ErrorState.js +41 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +111 -0
- package/dist/components/Field/Field.js +95 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +31 -0
- package/dist/components/FigureBand/FigureBand.js +51 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +34 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +27 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/Metric/Metric.d.ts +61 -0
- package/dist/components/Metric/Metric.js +51 -0
- package/dist/components/Metric/Metric.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +33 -0
- package/dist/components/NativeSelect/NativeSelect.js +44 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +92 -0
- package/dist/components/PageHeader/PageHeader.js +37 -0
- package/dist/components/PageHeader/PageHeader.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +67 -0
- package/dist/components/Pagination/Pagination.js +112 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +43 -0
- package/dist/components/Progress/Progress.js +57 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +49 -0
- package/dist/components/RadioGroup/RadioGroup.js +53 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +46 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +68 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +101 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +87 -0
- package/dist/components/Select/Select.js +130 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +48 -0
- package/dist/components/Separator/Separator.js +43 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +43 -0
- package/dist/components/Sheet/Sheet.js +79 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.d.ts +357 -0
- package/dist/components/Sidebar/Sidebar.js +447 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +74 -0
- package/dist/components/Slider/Slider.js +143 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +58 -0
- package/dist/components/Spinner/Spinner.js +49 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +30 -0
- package/dist/components/StatusPill/StatusPill.js +37 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +25 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +137 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +37 -0
- package/dist/components/Tabs/Tabs.js +205 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +87 -0
- package/dist/components/Tag/Tag.js +62 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +32 -0
- package/dist/components/Toast/Toast.js +64 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +46 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +88 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
- package/dist/diagrams/index.d.ts +17 -0
- package/dist/diagrams/index.js +29 -0
- package/dist/diagrams/index.js.map +1 -0
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +138 -0
- package/dist/diagrams/lib/frame.js +131 -0
- package/dist/diagrams/lib/frame.js.map +1 -0
- package/dist/diagrams/lib/geometry.d.ts +114 -0
- package/dist/diagrams/lib/geometry.js +113 -0
- package/dist/diagrams/lib/geometry.js.map +1 -0
- package/dist/diagrams/lib/legend.d.ts +32 -0
- package/dist/diagrams/lib/legend.js +84 -0
- package/dist/diagrams/lib/legend.js.map +1 -0
- package/dist/diagrams/lib/marks.d.ts +207 -0
- package/dist/diagrams/lib/marks.js +480 -0
- package/dist/diagrams/lib/marks.js.map +1 -0
- package/dist/diagrams/lib/route.d.ts +106 -0
- package/dist/diagrams/lib/route.js +201 -0
- package/dist/diagrams/lib/route.js.map +1 -0
- package/dist/diagrams/lib/wires.d.ts +59 -0
- package/dist/diagrams/lib/wires.js +94 -0
- package/dist/diagrams/lib/wires.js.map +1 -0
- package/dist/diagrams/spec.d.ts +405 -0
- package/dist/diagrams/spec.js +1 -0
- package/dist/diagrams/spec.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +300 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/control.d.ts +32 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +48 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/slot-content.d.ts +8 -0
- package/dist/lib/slot-content.js +17 -0
- package/dist/lib/slot-content.js.map +1 -0
- package/dist/lib/step-rail.d.ts +45 -0
- package/dist/lib/step-rail.js +47 -0
- package/dist/lib/step-rail.js.map +1 -0
- package/dist/lib/svg-export.d.ts +138 -0
- package/dist/lib/svg-export.js +198 -0
- package/dist/lib/svg-export.js.map +1 -0
- package/dist/lib/useClipboardCopy.d.ts +30 -0
- package/dist/lib/useClipboardCopy.js +37 -0
- package/dist/lib/useClipboardCopy.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +49 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +193 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +514 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +652 -0
- package/dist/tokens.d.ts +198 -0
- package/dist/tokens.js +1020 -0
- package/dist/tokens.json +1019 -0
- package/dist/website/Actions/Actions.d.ts +34 -0
- package/dist/website/Actions/Actions.js +29 -0
- package/dist/website/Actions/Actions.js.map +1 -0
- package/dist/website/Collection/Collection.d.ts +128 -0
- package/dist/website/Collection/Collection.js +162 -0
- package/dist/website/Collection/Collection.js.map +1 -0
- package/dist/website/Contact/Contact.d.ts +87 -0
- package/dist/website/Contact/Contact.js +94 -0
- package/dist/website/Contact/Contact.js.map +1 -0
- package/dist/website/Content/CodePanel.d.ts +27 -0
- package/dist/website/Content/CodePanel.js +30 -0
- package/dist/website/Content/CodePanel.js.map +1 -0
- package/dist/website/Content/Content.d.ts +29 -0
- package/dist/website/Content/Content.js +38 -0
- package/dist/website/Content/Content.js.map +1 -0
- package/dist/website/Conversation/Conversation.d.ts +193 -0
- package/dist/website/Conversation/Conversation.js +252 -0
- package/dist/website/Conversation/Conversation.js.map +1 -0
- package/dist/website/Evidence/Evidence.d.ts +116 -0
- package/dist/website/Evidence/Evidence.js +142 -0
- package/dist/website/Evidence/Evidence.js.map +1 -0
- package/dist/website/Media/Media.d.ts +173 -0
- package/dist/website/Media/Media.js +225 -0
- package/dist/website/Media/Media.js.map +1 -0
- package/dist/website/Media/MediaLightbox.d.ts +18 -0
- package/dist/website/Media/MediaLightbox.js +38 -0
- package/dist/website/Media/MediaLightbox.js.map +1 -0
- package/dist/website/Metrics/Metrics.d.ts +74 -0
- package/dist/website/Metrics/Metrics.js +96 -0
- package/dist/website/Metrics/Metrics.js.map +1 -0
- package/dist/website/Music/Music.d.ts +60 -0
- package/dist/website/Music/Music.js +80 -0
- package/dist/website/Music/Music.js.map +1 -0
- package/dist/website/Portfolio/FrameLayout.d.ts +9 -0
- package/dist/website/Portfolio/FrameLayout.js +42 -0
- package/dist/website/Portfolio/FrameLayout.js.map +1 -0
- package/dist/website/Portfolio/Portfolio.d.ts +49 -0
- package/dist/website/Portfolio/Portfolio.js +66 -0
- package/dist/website/Portfolio/Portfolio.js.map +1 -0
- package/dist/website/Portfolio/QuestionCard.d.ts +22 -0
- package/dist/website/Portfolio/QuestionCard.js +33 -0
- package/dist/website/Portfolio/QuestionCard.js.map +1 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.d.ts +21 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js +31 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js.map +1 -0
- package/dist/website/Reading/Reading.d.ts +203 -0
- package/dist/website/Reading/Reading.js +357 -0
- package/dist/website/Reading/Reading.js.map +1 -0
- package/dist/website/Recovery/Recovery.d.ts +39 -0
- package/dist/website/Recovery/Recovery.js +96 -0
- package/dist/website/Recovery/Recovery.js.map +1 -0
- package/dist/website/SearchPalette/SearchPalette.d.ts +59 -0
- package/dist/website/SearchPalette/SearchPalette.js +120 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -0
- package/dist/website/SiteNavigation/SiteNavigation.d.ts +46 -0
- package/dist/website/SiteNavigation/SiteNavigation.js +101 -0
- package/dist/website/SiteNavigation/SiteNavigation.js.map +1 -0
- package/dist/website/SiteShell/SiteShell.d.ts +45 -0
- package/dist/website/SiteShell/SiteShell.js +46 -0
- package/dist/website/SiteShell/SiteShell.js.map +1 -0
- package/dist/website/Timeline/Timeline.d.ts +80 -0
- package/dist/website/Timeline/Timeline.js +99 -0
- package/dist/website/Timeline/Timeline.js.map +1 -0
- package/dist/website/index.d.ts +27 -0
- package/dist/website/index.js +21 -0
- package/dist/website/index.js.map +1 -0
- package/dist/website-actions.css +6 -0
- package/dist/website-base.css +46 -0
- package/dist/website-collection.css +89 -0
- package/dist/website-contact.css +29 -0
- package/dist/website-content.css +17 -0
- package/dist/website-controls.css +91 -0
- package/dist/website-conversation.css +115 -0
- package/dist/website-evidence.css +56 -0
- package/dist/website-media.css +227 -0
- package/dist/website-metrics.css +15 -0
- package/dist/website-music.css +27 -0
- package/dist/website-portfolio.css +94 -0
- package/dist/website-reading.css +159 -0
- package/dist/website-recovery.css +28 -0
- package/dist/website-search.css +26 -0
- package/dist/website-shell.css +89 -0
- package/dist/website-timeline.css +43 -0
- package/dist/website.css +25 -0
- package/llms.txt +35 -0
- package/package.json +163 -5
- package/skills/folio-design/SKILL.md +228 -0
- package/skills/folio-design/evals/claims.json +95 -0
- package/skills/folio-design/evals/evals.json +84 -0
- package/skills/folio-design/rules/a11y.md +167 -0
- package/skills/folio-design/rules/composition.md +108 -0
- package/skills/folio-design/rules/forms.md +135 -0
- package/skills/folio-design/rules/naming.md +155 -0
- package/skills/folio-design/rules/tokens.md +133 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useId,
|
|
7
|
+
useMemo
|
|
8
|
+
} from "react";
|
|
9
|
+
import {
|
|
10
|
+
Funnel as RechartsFunnel,
|
|
11
|
+
FunnelChart as RechartsFunnelChart,
|
|
12
|
+
LabelList
|
|
13
|
+
} from "recharts";
|
|
14
|
+
import { ChartContainer, colorStops, cssName } from "../lib/chart.js";
|
|
15
|
+
import { ChartFigure } from "../lib/figure.js";
|
|
16
|
+
import {} from "../lib/empty.js";
|
|
17
|
+
import { ChartTooltip, ChartTooltipContent } from "../lib/tooltip.js";
|
|
18
|
+
import { ColorStops } from "../lib/paint.js";
|
|
19
|
+
const FunnelChartContext = createContext(null);
|
|
20
|
+
function useFunnelChart() {
|
|
21
|
+
const context = useContext(FunnelChartContext);
|
|
22
|
+
if (!context) throw new Error("A funnel chart part must be rendered inside <FunnelChart>");
|
|
23
|
+
return context;
|
|
24
|
+
}
|
|
25
|
+
function FunnelChart({
|
|
26
|
+
config,
|
|
27
|
+
data,
|
|
28
|
+
dataKey,
|
|
29
|
+
nameKey,
|
|
30
|
+
title,
|
|
31
|
+
showTitle,
|
|
32
|
+
description,
|
|
33
|
+
children,
|
|
34
|
+
className,
|
|
35
|
+
chartProps,
|
|
36
|
+
hideDataTable = false,
|
|
37
|
+
empty
|
|
38
|
+
}) {
|
|
39
|
+
const chartId = useId().replace(/:/g, "");
|
|
40
|
+
const context = useMemo(
|
|
41
|
+
() => ({ config, nameKey, dataKey, data }),
|
|
42
|
+
[config, data, dataKey, nameKey]
|
|
43
|
+
);
|
|
44
|
+
return /* @__PURE__ */ jsx(FunnelChartContext.Provider, { value: context, children: /* @__PURE__ */ jsx(
|
|
45
|
+
ChartFigure,
|
|
46
|
+
{
|
|
47
|
+
title,
|
|
48
|
+
showTitle,
|
|
49
|
+
description,
|
|
50
|
+
className,
|
|
51
|
+
table: hideDataTable ? false : { rows: data, rowKey: nameKey, columns: [{ key: dataKey, label: "Value" }] },
|
|
52
|
+
isEmpty: data.length === 0,
|
|
53
|
+
empty,
|
|
54
|
+
children: /* @__PURE__ */ jsx(ChartContainer, { config, children: /* @__PURE__ */ jsx(RechartsFunnelChart, { id: chartId, accessibilityLayer: true, ...chartProps, children }) })
|
|
55
|
+
}
|
|
56
|
+
) });
|
|
57
|
+
}
|
|
58
|
+
function Funnel({
|
|
59
|
+
variant = "stepped",
|
|
60
|
+
orientation = "vertical",
|
|
61
|
+
gap = 2,
|
|
62
|
+
children,
|
|
63
|
+
funnelProps
|
|
64
|
+
}) {
|
|
65
|
+
const { config, data, dataKey, nameKey } = useFunnelChart();
|
|
66
|
+
const chartId = useId().replace(/:/g, "");
|
|
67
|
+
const painted = data.map((row, index) => {
|
|
68
|
+
const name = String(row[nameKey]);
|
|
69
|
+
const slot = variant === "ramp" ? `var(--series-${index % 8 + 1})` : void 0;
|
|
70
|
+
return {
|
|
71
|
+
...row,
|
|
72
|
+
fill: slot ?? (name in config ? `url(#${chartId}-stage-${cssName(name)})` : "var(--series-1)")
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
RechartsFunnel,
|
|
78
|
+
{
|
|
79
|
+
dataKey,
|
|
80
|
+
nameKey,
|
|
81
|
+
data: painted,
|
|
82
|
+
isAnimationActive: false,
|
|
83
|
+
stroke: "var(--chart-surface)",
|
|
84
|
+
strokeWidth: gap,
|
|
85
|
+
orientation,
|
|
86
|
+
...funnelProps,
|
|
87
|
+
children
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
/* @__PURE__ */ jsx("defs", { children: Object.entries(config).map(([key, series]) => /* @__PURE__ */ jsx(
|
|
91
|
+
"linearGradient",
|
|
92
|
+
{
|
|
93
|
+
id: `${chartId}-stage-${cssName(key)}`,
|
|
94
|
+
x1: "0",
|
|
95
|
+
y1: "0",
|
|
96
|
+
x2: "1",
|
|
97
|
+
y2: "0",
|
|
98
|
+
children: /* @__PURE__ */ jsx(ColorStops, { dataKey: cssName(key), stops: colorStops(series) })
|
|
99
|
+
},
|
|
100
|
+
key
|
|
101
|
+
)) })
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
function Label({ dataKey, position = "right", labelListProps }) {
|
|
105
|
+
const { nameKey } = useFunnelChart();
|
|
106
|
+
return /* @__PURE__ */ jsx(
|
|
107
|
+
LabelList,
|
|
108
|
+
{
|
|
109
|
+
dataKey: dataKey ?? nameKey,
|
|
110
|
+
position,
|
|
111
|
+
stroke: "none",
|
|
112
|
+
fontSize: 12,
|
|
113
|
+
className: "fill-(--ink)",
|
|
114
|
+
...labelListProps
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
function Tooltip({ variant, roundness, defaultIndex }) {
|
|
119
|
+
const { nameKey } = useFunnelChart();
|
|
120
|
+
return /* @__PURE__ */ jsx(
|
|
121
|
+
ChartTooltip,
|
|
122
|
+
{
|
|
123
|
+
defaultIndex,
|
|
124
|
+
cursor: false,
|
|
125
|
+
content: /* @__PURE__ */ jsx(ChartTooltipContent, { nameKey, hideLabel: true, roundness, variant })
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
FunnelChart.Funnel = Funnel;
|
|
130
|
+
FunnelChart.Label = Label;
|
|
131
|
+
FunnelChart.Tooltip = Tooltip;
|
|
132
|
+
var FunnelChart_default = FunnelChart;
|
|
133
|
+
export {
|
|
134
|
+
FunnelChart,
|
|
135
|
+
FunnelChart_default as default
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=FunnelChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/FunnelChart/FunnelChart.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useContext,\n useId,\n useMemo,\n type ComponentProps,\n type ReactNode,\n} from 'react'\nimport {\n Funnel as RechartsFunnel,\n FunnelChart as RechartsFunnelChart,\n LabelList,\n} from 'recharts'\nimport { ChartContainer, colorStops, cssName, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { type ChartEmptyProps } from '../lib/empty'\nimport { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport { ColorStops } from '../lib/paint'\nimport type { ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\n/**\n * How each stage is painted.\n *\n * `stepped` is the honest default: every stage keeps the same fill and the\n * TAPER carries the drop. A ramp that also darkens each stage encodes the same\n * fact twice and invites the reader to compare two things that are one.\n */\nexport type FunnelVariant = 'stepped' | 'ramp'\n\ninterface FunnelChartContextValue {\n config: ChartConfig\n nameKey: string\n dataKey: string\n data: Record<string, unknown>[]\n}\n\nconst FunnelChartContext = createContext<FunnelChartContextValue | null>(null)\n\nfunction useFunnelChart(): FunnelChartContextValue {\n const context = useContext(FunnelChartContext)\n if (!context) throw new Error('A funnel chart part must be rendered inside <FunnelChart>')\n return context\n}\n\nexport interface FunnelChartProps<TData extends Record<string, unknown>> {\n /** Stage names → their label and paint. Keys must match the `nameKey` values. */\n config: ChartConfig\n /** The stages, widest first. Order is the funnel; it is not sorted for you. */\n data: TData[]\n /** The row field holding each stage's number. */\n dataKey: keyof TData & string\n /** The row field naming each stage. */\n nameKey: keyof TData & string\n /**\n * What the chart shows, in a sentence a reader could act on. Required, and\n * announced to a screen reader even when it is not printed.\n */\n title: string\n /** Prints the title above the plot instead of hiding it from sight. */\n showTitle?: boolean\n /** A line under the title — the unit, the window, the caveat. */\n description?: ReactNode\n /** The composed parts — `<Funnel>`, `<Tooltip>`. */\n children: ReactNode\n /** Merged onto the figure, last, so a call site can size or space it. */\n className?: string\n /** Escape hatch onto the raw Recharts chart element. */\n chartProps?: ComponentProps<typeof RechartsFunnelChart>\n /** Drops the hidden table view. Only correct when the page prints the data itself. */\n hideDataTable?: boolean\n /**\n * What the chart shows when it has nothing to draw. `false` keeps the empty\n * plot, for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * Stages that only ever narrow — a signup flow, a hiring pipeline, a checkout.\n *\n * The caveat is the same one every funnel has: the taper encodes a RATIO\n * between neighbouring stages, and the eye reads the enclosed area, so a funnel\n * exaggerates a shallow drop and flattens a steep one. Where the exact fall-off\n * is the point, put the percentages on the stages — `<Funnel.Label>` does — or\n * use a `<BarChart>`, which encodes each stage on one honest scale.\n *\n * Reach for `<SankeyChart>` instead when the flow can SPLIT rather than only\n * shrink: a funnel has one path through it by construction.\n *\n * @example\n * <FunnelChart title=\"Signup funnel\" config={config} data={stages} dataKey=\"people\" nameKey=\"stage\">\n * <FunnelChart.Funnel>\n * <FunnelChart.Label />\n * </FunnelChart.Funnel>\n * <FunnelChart.Tooltip />\n * </FunnelChart>\n */\nexport function FunnelChart<TData extends Record<string, unknown>>({\n config,\n data,\n dataKey,\n nameKey,\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n hideDataTable = false,\n empty,\n}: FunnelChartProps<TData>) {\n const chartId = useId().replace(/:/g, '')\n\n const context = useMemo<FunnelChartContextValue>(\n () => ({ config, nameKey, dataKey, data }),\n [config, data, dataKey, nameKey],\n )\n\n return (\n <FunnelChartContext.Provider value={context}>\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable\n ? false\n : { rows: data, rowKey: nameKey, columns: [{ key: dataKey, label: 'Value' }] }\n }\n isEmpty={data.length === 0}\n empty={empty}\n >\n <ChartContainer config={config}>\n {/* No `<defs>` here. `<Funnel>` scopes the stage gradients under its\n OWN generated id and paints from those, so a second set under the\n root's id was markup nothing referenced — one gradient definition\n per stage, per chart, drawn and never used. */}\n <RechartsFunnelChart id={chartId} accessibilityLayer {...chartProps}>\n {children}\n </RechartsFunnelChart>\n </ChartContainer>\n </ChartFigure>\n </FunnelChartContext.Provider>\n )\n}\n\nexport interface FunnelProps {\n variant?: FunnelVariant\n /** Whether the funnel narrows downward or along the inline axis. */\n orientation?: 'vertical' | 'horizontal'\n /** Gap between stages, in pixels. */\n gap?: number\n /** `<FunnelChart.Label>`. */\n children?: ReactNode\n funnelProps?: Omit<ComponentProps<typeof RechartsFunnel>, 'data' | 'dataKey'>\n}\n\n/** The stages themselves. */\nfunction Funnel({\n variant = 'stepped',\n orientation = 'vertical',\n gap = 2,\n children,\n funnelProps,\n}: FunnelProps) {\n const { config, data, dataKey, nameKey } = useFunnelChart()\n const chartId = useId().replace(/:/g, '')\n\n // `ramp` walks the series ramp stage by stage; `stepped` holds slot one for\n // all of them and lets the shape do the talking.\n const painted = data.map((row, index) => {\n const name = String(row[nameKey])\n const slot = variant === 'ramp' ? `var(--series-${(index % 8) + 1})` : undefined\n return {\n ...row,\n fill: slot ?? (name in config ? `url(#${chartId}-stage-${cssName(name)})` : 'var(--series-1)'),\n }\n })\n\n return (\n <>\n <RechartsFunnel\n dataKey={dataKey}\n nameKey={nameKey}\n data={painted}\n isAnimationActive={false}\n // A surface-coloured stroke rather than a transparent gap: the stages\n // touch by construction, and a hairline of the page between them is\n // what makes two similar stages countable.\n stroke=\"var(--chart-surface)\"\n strokeWidth={gap}\n orientation={orientation}\n {...funnelProps}\n >\n {children}\n </RechartsFunnel>\n <defs>\n {Object.entries(config).map(([key, series]) => (\n <linearGradient\n key={key}\n id={`${chartId}-stage-${cssName(key)}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"1\"\n y2=\"0\"\n >\n <ColorStops dataKey={cssName(key)} stops={colorStops(series)} />\n </linearGradient>\n ))}\n </defs>\n </>\n )\n}\n\nexport interface FunnelLabelProps {\n /** The field printed on each stage. Defaults to the stage's name. */\n dataKey?: string\n /** Where the label sits relative to its stage. */\n position?: ComponentProps<typeof LabelList>['position']\n labelListProps?: Omit<ComponentProps<typeof LabelList>, 'dataKey'>\n}\n\n/**\n * Names printed on the stages.\n *\n * Worth reaching for: a funnel's taper is a ratio the eye reads badly, and a\n * printed number is the relief for that.\n */\nfunction Label({ dataKey, position = 'right', labelListProps }: FunnelLabelProps) {\n const { nameKey } = useFunnelChart()\n\n return (\n <LabelList\n dataKey={dataKey ?? nameKey}\n position={position}\n stroke=\"none\"\n fontSize={12}\n className=\"fill-(--ink)\"\n {...labelListProps}\n />\n )\n}\n\n/** The hover panel. No heading: the stage's own name is the row label. */\nfunction Tooltip({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) {\n const { nameKey } = useFunnelChart()\n\n return (\n <ChartTooltip\n defaultIndex={defaultIndex}\n cursor={false}\n content={\n <ChartTooltipContent nameKey={nameKey} hideLabel roundness={roundness} variant={variant} />\n }\n />\n )\n}\n\nFunnelChart.Funnel = Funnel\nFunnelChart.Label = Label\nFunnelChart.Tooltip = Tooltip\n\nexport default FunnelChart\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { ChartEmptyProps } from '../lib/empty.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How a cell's value is turned into ink.
|
|
7
|
+
*
|
|
8
|
+
* `sequential` is one ramp light to dark, and is the right answer for a
|
|
9
|
+
* magnitude that only goes up: counts, durations, volume. `diverging` puts the
|
|
10
|
+
* page's own surface at the midpoint and darkens outward in both directions,
|
|
11
|
+
* for a value with a meaningful zero — a change, a delta, a residual.
|
|
12
|
+
*
|
|
13
|
+
* There is no third option, and that is the point. A rainbow scale reads as
|
|
14
|
+
* ordered to nobody, and is the single most common defect in a heatmap.
|
|
15
|
+
*/
|
|
16
|
+
type HeatmapScale = 'sequential' | 'diverging';
|
|
17
|
+
interface HeatmapCell {
|
|
18
|
+
/**
|
|
19
|
+
* The column this cell sits in. Must match one of `columns`, exactly: the
|
|
20
|
+
* grid is drawn by looking each pair up, so a cell naming a column that is
|
|
21
|
+
* not there is a cell the grid has nowhere to put. It is not drawn, and it
|
|
22
|
+
* takes no part in the derived domain either — a misspelt header used to
|
|
23
|
+
* stretch the scale with a number nothing on screen was painted from.
|
|
24
|
+
*/
|
|
25
|
+
column: string;
|
|
26
|
+
/** The row this cell sits in. Must match one of `rows`, on the same terms. */
|
|
27
|
+
row: string;
|
|
28
|
+
/** The number. `null` is drawn as an explicit gap, not as a zero. */
|
|
29
|
+
value: number | null;
|
|
30
|
+
}
|
|
31
|
+
interface HeatmapProps {
|
|
32
|
+
/** What the grid shows. Required, and it names the table. */
|
|
33
|
+
title: string;
|
|
34
|
+
/** Prints the title above the grid instead of hiding it from sight. */
|
|
35
|
+
showTitle?: boolean;
|
|
36
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
37
|
+
description?: ReactNode;
|
|
38
|
+
/** Column headers, in the order they should appear. */
|
|
39
|
+
columns: string[];
|
|
40
|
+
/** Row headers, in the order they should appear. */
|
|
41
|
+
rows: string[];
|
|
42
|
+
cells: HeatmapCell[];
|
|
43
|
+
scale?: HeatmapScale;
|
|
44
|
+
/**
|
|
45
|
+
* The domain, as `[min, max]`. Derived from the data when omitted.
|
|
46
|
+
*
|
|
47
|
+
* Pin it whenever two grids are meant to be compared: two heatmaps on
|
|
48
|
+
* independent domains look alike and mean different things, which is the one
|
|
49
|
+
* failure a shared legend cannot fix.
|
|
50
|
+
*/
|
|
51
|
+
domain?: [number, number];
|
|
52
|
+
/**
|
|
53
|
+
* Formats a value for the cell's announcement and its printed label.
|
|
54
|
+
*
|
|
55
|
+
* The cell is handed over as well, so a grid whose columns are not
|
|
56
|
+
* self-describing can name the reading rather than only the number. A
|
|
57
|
+
* calendar is the case that needs it: two days with the same count are two
|
|
58
|
+
* different readings, and the row and column headers a cell is announced
|
|
59
|
+
* with — "Mon" and a month name over a block of five weeks — do not say
|
|
60
|
+
* which day it was.
|
|
61
|
+
*/
|
|
62
|
+
formatValue?: (value: number, cell: HeatmapCell) => string;
|
|
63
|
+
/** Prints the number inside each cell. Only legible on a coarse grid. */
|
|
64
|
+
showValues?: boolean;
|
|
65
|
+
className?: string;
|
|
66
|
+
/**
|
|
67
|
+
* What the grid shows when it has no rows or no columns to draw.
|
|
68
|
+
*
|
|
69
|
+
* A heatmap with no headers renders as a caption over nothing, which reads
|
|
70
|
+
* as a grid that failed to load rather than as one with nothing in it.
|
|
71
|
+
*/
|
|
72
|
+
empty?: ChartEmptyProps;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A grid of values read by weight — a calendar of activity, a confusion matrix,
|
|
76
|
+
* an hour-by-weekday load.
|
|
77
|
+
*
|
|
78
|
+
* The one form in the set that a monochrome system renders BETTER than a
|
|
79
|
+
* chromatic one. A heatmap needs a scale whose order the eye can read without
|
|
80
|
+
* consulting a legend, and lightness is the only channel that is unambiguously
|
|
81
|
+
* ordered — which is why "one hue, light to dark" is the standing advice
|
|
82
|
+
* everywhere else, and why the rainbow heatmap is a perennial mistake. Here
|
|
83
|
+
* there is no hue left to get wrong.
|
|
84
|
+
*
|
|
85
|
+
* It is built as a real `<table>` rather than as an SVG, so the structure a
|
|
86
|
+
* screen reader walks is the structure the eye reads: a header row, a header
|
|
87
|
+
* column, and a cell that announces its own value. Nothing else in the package
|
|
88
|
+
* can say that, and nothing else needs to — which is also why this one takes no
|
|
89
|
+
* rendering engine at all.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* <Heatmap
|
|
93
|
+
* title="Commits by weekday and hour"
|
|
94
|
+
* columns={hours}
|
|
95
|
+
* rows={weekdays}
|
|
96
|
+
* cells={cells}
|
|
97
|
+
* />
|
|
98
|
+
*/
|
|
99
|
+
declare function Heatmap({ title, showTitle, description, columns, rows, cells, scale, domain, formatValue, showValues, className, empty, }: HeatmapProps): react.JSX.Element;
|
|
100
|
+
|
|
101
|
+
export { Heatmap, type HeatmapCell, type HeatmapProps, type HeatmapScale, Heatmap as default };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { ChartEmpty } from "../lib/empty.js";
|
|
4
|
+
import { clampedFraction } from "../lib/scale.js";
|
|
5
|
+
const LABELLED_CEILING = 0.35;
|
|
6
|
+
function cellKey(row, column) {
|
|
7
|
+
return `${row}\0${column}`;
|
|
8
|
+
}
|
|
9
|
+
function placed(cells, rows, columns) {
|
|
10
|
+
const rowSet = new Set(rows);
|
|
11
|
+
const columnSet = new Set(columns);
|
|
12
|
+
return new Map(
|
|
13
|
+
cells.filter((cell) => rowSet.has(cell.row) && columnSet.has(cell.column)).map((cell) => [cellKey(cell.row, cell.column), cell.value])
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
function Heatmap({
|
|
17
|
+
title,
|
|
18
|
+
showTitle = false,
|
|
19
|
+
description,
|
|
20
|
+
columns,
|
|
21
|
+
rows,
|
|
22
|
+
cells,
|
|
23
|
+
scale = "sequential",
|
|
24
|
+
domain,
|
|
25
|
+
formatValue = (value) => value.toLocaleString(),
|
|
26
|
+
showValues = false,
|
|
27
|
+
className,
|
|
28
|
+
empty
|
|
29
|
+
}) {
|
|
30
|
+
const byKey = placed(cells, rows, columns);
|
|
31
|
+
const values = [...byKey.values()].filter((value) => value !== null);
|
|
32
|
+
const [min, max] = domain ?? [Math.min(0, ...values), Math.max(0, ...values)];
|
|
33
|
+
return /* @__PURE__ */ jsxs("figure", { className: cn("flex w-full flex-col", className), children: [
|
|
34
|
+
/* @__PURE__ */ jsxs("figcaption", { className: cn(!showTitle && "sr-only", showTitle && "mb-3 flex flex-col gap-1"), children: [
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: cn(showTitle && "font-heading text-[length:var(--fs-item)] text-(--ink)"), children: title }),
|
|
36
|
+
description && /* @__PURE__ */ jsx("span", { className: cn(showTitle && "mono-meta text-(--ink-3-aa)"), children: description })
|
|
37
|
+
] }),
|
|
38
|
+
rows.length === 0 || columns.length === 0 ? /* @__PURE__ */ jsx(ChartEmpty, { ...empty || {} }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed border-separate border-spacing-[2px] text-xs", children: [
|
|
39
|
+
/* @__PURE__ */ jsx("caption", { className: "sr-only", children: title }),
|
|
40
|
+
/* @__PURE__ */ jsxs("colgroup", { children: [
|
|
41
|
+
/* @__PURE__ */ jsx("col", { className: "w-20" }),
|
|
42
|
+
/* @__PURE__ */ jsx("col", { span: columns.length })
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
45
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "sr-only", children: "Row" }),
|
|
46
|
+
columns.map((column) => /* @__PURE__ */ jsx("th", { scope: "col", className: "pb-1 mono-meta font-normal text-(--chart-axis)", children: column }, column))
|
|
47
|
+
] }) }),
|
|
48
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
"th",
|
|
51
|
+
{
|
|
52
|
+
scope: "row",
|
|
53
|
+
className: "pe-2 text-end mono-meta font-normal whitespace-nowrap text-(--chart-axis)",
|
|
54
|
+
children: row
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
columns.map((column) => /* @__PURE__ */ jsx(
|
|
58
|
+
HeatmapTile,
|
|
59
|
+
{
|
|
60
|
+
value: byKey.get(cellKey(row, column)) ?? null,
|
|
61
|
+
min,
|
|
62
|
+
max,
|
|
63
|
+
scale,
|
|
64
|
+
row,
|
|
65
|
+
column,
|
|
66
|
+
label: `${row}, ${column}`,
|
|
67
|
+
formatValue,
|
|
68
|
+
showValue: showValues
|
|
69
|
+
},
|
|
70
|
+
column
|
|
71
|
+
))
|
|
72
|
+
] }, row)) })
|
|
73
|
+
] }) })
|
|
74
|
+
] });
|
|
75
|
+
}
|
|
76
|
+
function HeatmapTile({
|
|
77
|
+
value,
|
|
78
|
+
min,
|
|
79
|
+
max,
|
|
80
|
+
scale,
|
|
81
|
+
row,
|
|
82
|
+
column,
|
|
83
|
+
label,
|
|
84
|
+
formatValue,
|
|
85
|
+
showValue
|
|
86
|
+
}) {
|
|
87
|
+
if (value === null) {
|
|
88
|
+
return (
|
|
89
|
+
// A missing reading is not a zero, and drawing it as the palest cell
|
|
90
|
+
// would say that it was. The hairline says "no data" instead.
|
|
91
|
+
/* @__PURE__ */ jsx("td", { className: "h-7 rounded-[2px] border border-dashed border-(--rule) bg-transparent", children: /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
92
|
+
label,
|
|
93
|
+
": no data"
|
|
94
|
+
] }) })
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const t = clampedFraction(value, min, max);
|
|
98
|
+
const ramp = scale === "diverging" ? Math.abs(t - 0.5) * 2 : t;
|
|
99
|
+
const weight = showValue ? ramp * LABELLED_CEILING : ramp;
|
|
100
|
+
return /* @__PURE__ */ jsxs(
|
|
101
|
+
"td",
|
|
102
|
+
{
|
|
103
|
+
className: "h-7 rounded-[2px] text-center align-middle tabular-nums",
|
|
104
|
+
style: {
|
|
105
|
+
// `color-mix` rather than eight discrete steps: a heatmap's whole job is
|
|
106
|
+
// a continuous read, and banding it into a ramp invents boundaries the
|
|
107
|
+
// data does not have.
|
|
108
|
+
backgroundColor: `color-mix(in srgb, var(--series-1) ${(weight * 100).toFixed(1)}%, var(--chart-surface))`,
|
|
109
|
+
// One text colour at every weight, which is only safe because the ramp
|
|
110
|
+
// above is capped when a number is printed on it.
|
|
111
|
+
color: "var(--ink)"
|
|
112
|
+
},
|
|
113
|
+
children: [
|
|
114
|
+
/* @__PURE__ */ jsx("span", { className: cn(!showValue && "sr-only forced-colors:not-sr-only"), children: formatValue(value, { row, column, value }) }),
|
|
115
|
+
!showValue && /* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
var Heatmap_default = Heatmap;
|
|
121
|
+
export {
|
|
122
|
+
Heatmap,
|
|
123
|
+
Heatmap_default as default
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=Heatmap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/Heatmap/Heatmap.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { ChartEmpty, type ChartEmptyProps } from '../lib/empty'\nimport { clampedFraction } from '../lib/scale'\n\n/**\n * How a cell's value is turned into ink.\n *\n * `sequential` is one ramp light to dark, and is the right answer for a\n * magnitude that only goes up: counts, durations, volume. `diverging` puts the\n * page's own surface at the midpoint and darkens outward in both directions,\n * for a value with a meaningful zero — a change, a delta, a residual.\n *\n * There is no third option, and that is the point. A rainbow scale reads as\n * ordered to nobody, and is the single most common defect in a heatmap.\n */\nexport type HeatmapScale = 'sequential' | 'diverging'\n\nexport interface HeatmapCell {\n /**\n * The column this cell sits in. Must match one of `columns`, exactly: the\n * grid is drawn by looking each pair up, so a cell naming a column that is\n * not there is a cell the grid has nowhere to put. It is not drawn, and it\n * takes no part in the derived domain either — a misspelt header used to\n * stretch the scale with a number nothing on screen was painted from.\n */\n column: string\n /** The row this cell sits in. Must match one of `rows`, on the same terms. */\n row: string\n /** The number. `null` is drawn as an explicit gap, not as a zero. */\n value: number | null\n}\n\nexport interface HeatmapProps {\n /** What the grid shows. Required, and it names the table. */\n title: string\n /** Prints the title above the grid instead of hiding it from sight. */\n showTitle?: boolean\n /** A line under the title — the unit, the window, the caveat. */\n description?: ReactNode\n /** Column headers, in the order they should appear. */\n columns: string[]\n /** Row headers, in the order they should appear. */\n rows: string[]\n cells: HeatmapCell[]\n scale?: HeatmapScale\n /**\n * The domain, as `[min, max]`. Derived from the data when omitted.\n *\n * Pin it whenever two grids are meant to be compared: two heatmaps on\n * independent domains look alike and mean different things, which is the one\n * failure a shared legend cannot fix.\n */\n domain?: [number, number]\n /**\n * Formats a value for the cell's announcement and its printed label.\n *\n * The cell is handed over as well, so a grid whose columns are not\n * self-describing can name the reading rather than only the number. A\n * calendar is the case that needs it: two days with the same count are two\n * different readings, and the row and column headers a cell is announced\n * with — \"Mon\" and a month name over a block of five weeks — do not say\n * which day it was.\n */\n formatValue?: (value: number, cell: HeatmapCell) => string\n /** Prints the number inside each cell. Only legible on a coarse grid. */\n showValues?: boolean\n className?: string\n /**\n * What the grid shows when it has no rows or no columns to draw.\n *\n * A heatmap with no headers renders as a caption over nothing, which reads\n * as a grid that failed to load rather than as one with nothing in it.\n */\n empty?: ChartEmptyProps\n}\n\n/**\n * How far up the ramp a cell may go.\n *\n * A printed number has to clear 4.5:1 against whatever it is printed on, and a\n * mid-grey clears it against neither ink nor paper — which is the reason a\n * heatmap with values on it usually ends up with unreadable cells somewhere in\n * the middle of its own scale. Capping the wash is the trade: the ORDER of the\n * cells survives untouched, the contrast range narrows, and the numbers — which\n * are the precise read anyway — become the thing carrying the detail.\n *\n * With no number printed the span is the full ramp, because the only text in\n * the cell is then visually hidden and has nothing to contrast against.\n */\nconst LABELLED_CEILING = 0.35\n\n/**\n * The key a row and a column are looked up by.\n *\n * Joined on a character no header can contain, so `\"a b\" × \"c\"` and\n * `\"a\" × \"b c\"` stay two different cells. This used to be a literal NUL byte in\n * the source — the same key, written invisibly, in a file every text tool then\n * treated as binary.\n */\nfunction cellKey(row: string, column: string): string {\n return `${row}\u0000${column}`\n}\n\n/** The cells the grid can actually place, keyed by the pair that places them. */\nfunction placed(\n cells: HeatmapCell[],\n rows: string[],\n columns: string[],\n): Map<string, number | null> {\n const rowSet = new Set(rows)\n const columnSet = new Set(columns)\n return new Map(\n cells\n .filter((cell) => rowSet.has(cell.row) && columnSet.has(cell.column))\n .map((cell) => [cellKey(cell.row, cell.column), cell.value]),\n )\n}\n\n/**\n * A grid of values read by weight — a calendar of activity, a confusion matrix,\n * an hour-by-weekday load.\n *\n * The one form in the set that a monochrome system renders BETTER than a\n * chromatic one. A heatmap needs a scale whose order the eye can read without\n * consulting a legend, and lightness is the only channel that is unambiguously\n * ordered — which is why \"one hue, light to dark\" is the standing advice\n * everywhere else, and why the rainbow heatmap is a perennial mistake. Here\n * there is no hue left to get wrong.\n *\n * It is built as a real `<table>` rather than as an SVG, so the structure a\n * screen reader walks is the structure the eye reads: a header row, a header\n * column, and a cell that announces its own value. Nothing else in the package\n * can say that, and nothing else needs to — which is also why this one takes no\n * rendering engine at all.\n *\n * @example\n * <Heatmap\n * title=\"Commits by weekday and hour\"\n * columns={hours}\n * rows={weekdays}\n * cells={cells}\n * />\n */\nexport function Heatmap({\n title,\n showTitle = false,\n description,\n columns,\n rows,\n cells,\n scale = 'sequential',\n domain,\n formatValue = (value) => value.toLocaleString(),\n showValues = false,\n className,\n empty,\n}: HeatmapProps) {\n // Keyed first, so the domain comes from the cells the grid draws. A cell\n // whose row or column is not in the headers is never looked up, and it used\n // to stretch the scale anyway — one misspelt header pushing every drawn cell\n // into the first fraction of the ramp, with nothing on screen to explain it.\n const byKey = placed(cells, rows, columns)\n const values = [...byKey.values()].filter((value): value is number => value !== null)\n const [min, max] = domain ?? [Math.min(0, ...values), Math.max(0, ...values)]\n\n return (\n <figure className={cn('flex w-full flex-col', className)}>\n <figcaption className={cn(!showTitle && 'sr-only', showTitle && 'mb-3 flex flex-col gap-1')}>\n <span className={cn(showTitle && 'font-heading text-[length:var(--fs-item)] text-(--ink)')}>\n {title}\n </span>\n {description && (\n <span className={cn(showTitle && 'mono-meta text-(--ink-3-aa)')}>{description}</span>\n )}\n </figcaption>\n\n {rows.length === 0 || columns.length === 0 ? (\n <ChartEmpty {...(empty || {})} />\n ) : (\n <>\n {/* `border-separate` with a spacing rather than a gap on a grid: the two\n pixels of page between cells are what make two neighbouring weights\n countable, and a table is the only layout that keeps a header tied to\n its own line.\n\n `table-fixed`, and not automatic layout: every cell's printed reading\n is `sr-only`, so it has no intrinsic width to size a column by, while\n the row-header column carries real, `whitespace-nowrap` text. Automatic\n layout hands the row-header column all the slack it can find and\n leaves every data column to divide what is left of nothing — a year\n of calendar cells computing 0px wide.\n\n The `colgroup` below is the other half, and has to be a `colgroup`\n rather than a width on a cell: fixed layout only ever reads a\n column's width from its first row, and that row's own corner cell is\n `sr-only` — `position: absolute`, so a width there is never seen by\n the column it sits in. A `col` is read regardless of which row, or\n which cell in it, is hidden. */}\n <table className=\"w-full table-fixed border-separate border-spacing-[2px] text-xs\">\n <caption className=\"sr-only\">{title}</caption>\n <colgroup>\n <col className=\"w-20\" />\n <col span={columns.length} />\n </colgroup>\n <thead>\n <tr>\n <th scope=\"col\" className=\"sr-only\">\n Row\n </th>\n {columns.map((column) => (\n <th key={column} scope=\"col\" className=\"pb-1 mono-meta font-normal text-(--chart-axis)\">\n {column}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row}>\n <th\n scope=\"row\"\n className=\"pe-2 text-end mono-meta font-normal whitespace-nowrap text-(--chart-axis)\"\n >\n {row}\n </th>\n {columns.map((column) => (\n <HeatmapTile\n key={column}\n value={byKey.get(cellKey(row, column)) ?? null}\n min={min}\n max={max}\n scale={scale}\n row={row}\n column={column}\n label={`${row}, ${column}`}\n formatValue={formatValue}\n showValue={showValues}\n />\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </>\n )}\n </figure>\n )\n}\n\nfunction HeatmapTile({\n value,\n min,\n max,\n scale,\n row,\n column,\n label,\n formatValue,\n showValue,\n}: {\n value: number | null\n min: number\n max: number\n scale: HeatmapScale\n row: string\n column: string\n label: string\n formatValue: (value: number, cell: HeatmapCell) => string\n showValue: boolean\n}) {\n if (value === null) {\n return (\n // A missing reading is not a zero, and drawing it as the palest cell\n // would say that it was. The hairline says \"no data\" instead.\n <td className=\"h-7 rounded-[2px] border border-dashed border-(--rule) bg-transparent\">\n <span className=\"sr-only\">{label}: no data</span>\n </td>\n )\n }\n\n const t = clampedFraction(value, min, max)\n // Diverging reads DISTANCE from the midpoint, so both directions darken and\n // the middle of the scale is the page itself.\n const ramp = scale === 'diverging' ? Math.abs(t - 0.5) * 2 : t\n const weight = showValue ? ramp * LABELLED_CEILING : ramp\n\n return (\n <td\n className=\"h-7 rounded-[2px] text-center align-middle tabular-nums\"\n style={{\n // `color-mix` rather than eight discrete steps: a heatmap's whole job is\n // a continuous read, and banding it into a ramp invents boundaries the\n // data does not have.\n backgroundColor: `color-mix(in srgb, var(--series-1) ${(weight * 100).toFixed(1)}%, var(--chart-surface))`,\n // One text colour at every weight, which is only safe because the ramp\n // above is capped when a number is printed on it.\n color: 'var(--ink)',\n }}\n >\n {/* Revealed under forced colours, where the cell's own background is\n remapped away and the wash that WAS the encoding no longer exists.\n The grid degrades to the table it always was underneath, rather than\n to a page of identical empty boxes. */}\n <span className={cn(!showValue && 'sr-only forced-colors:not-sr-only')}>\n {formatValue(value, { row, column, value })}\n </span>\n {!showValue && <span className=\"sr-only\">{label}</span>}\n </td>\n )\n}\n\nexport default Heatmap\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { ChartTooltipSlotProps } from '../AreaChart/AreaChart.js';
|
|
2
|
+
import { ChartXAxisProps, ChartYAxisProps } from '../BarChart/BarChart.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
5
|
+
import { BarChart, Bar, CartesianGrid } from 'recharts';
|
|
6
|
+
import { ChartConfig } from '../lib/chart.js';
|
|
7
|
+
import { ChartEmptyProps } from '../lib/empty.js';
|
|
8
|
+
import { ChartBackgroundVariant } from '../lib/background.js';
|
|
9
|
+
import { ReferenceLine, ReferenceBand, Annotation } from '../lib/annotations.js';
|
|
10
|
+
import '../lib/values.js';
|
|
11
|
+
import '../lib/sonify-control.js';
|
|
12
|
+
import '../lib/sonify.js';
|
|
13
|
+
import '../lib/brush.js';
|
|
14
|
+
import '../lib/toolbar.js';
|
|
15
|
+
import '../lib/zoom.js';
|
|
16
|
+
import '../lib/figure.js';
|
|
17
|
+
import '../lib/paint.js';
|
|
18
|
+
import '../lib/dot.js';
|
|
19
|
+
import '../lib/legend.js';
|
|
20
|
+
import '../lib/tooltip.js';
|
|
21
|
+
import 'recharts/types/component/DefaultTooltipContent';
|
|
22
|
+
|
|
23
|
+
/** What the bar heights mean. */
|
|
24
|
+
type HistogramMode = 'frequency' | 'density';
|
|
25
|
+
/** One bucket, as the chart draws it. */
|
|
26
|
+
interface HistogramBin {
|
|
27
|
+
/** The bucket's lower edge, inclusive. */
|
|
28
|
+
from: number;
|
|
29
|
+
/** The bucket's upper edge, exclusive — except the last, which includes it. */
|
|
30
|
+
to: number;
|
|
31
|
+
/** How many observations fell in it. */
|
|
32
|
+
count: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Observations the bins do not reach, and the edge each fell outside.
|
|
36
|
+
*
|
|
37
|
+
* Only ever non-zero when the call site gave explicit `bins` edges: a derived
|
|
38
|
+
* width spans the data by construction. When it IS non-zero it is the reading
|
|
39
|
+
* that matters most — a tail cut off by a hand-picked range — and dropping it
|
|
40
|
+
* silently hid it from the picture, from the table and from the tooltip's
|
|
41
|
+
* share-of-total all at once.
|
|
42
|
+
*/
|
|
43
|
+
interface HistogramOutside {
|
|
44
|
+
/** How many observations fell below the first edge. */
|
|
45
|
+
below: number;
|
|
46
|
+
/** How many fell above the last. */
|
|
47
|
+
above: number;
|
|
48
|
+
/** The first edge, and the last. */
|
|
49
|
+
edges: [number, number];
|
|
50
|
+
}
|
|
51
|
+
interface HistogramProps {
|
|
52
|
+
/**
|
|
53
|
+
* The single series — its label and its paint. Only the FIRST entry is read;
|
|
54
|
+
* a histogram has one distribution and as many bars as it has buckets.
|
|
55
|
+
*/
|
|
56
|
+
config?: ChartConfig;
|
|
57
|
+
/**
|
|
58
|
+
* The raw observations, in any order. Binned for you by `bins`.
|
|
59
|
+
*
|
|
60
|
+
* Give this OR `data`, not both — `data` wins if both arrive.
|
|
61
|
+
*/
|
|
62
|
+
values?: number[];
|
|
63
|
+
/**
|
|
64
|
+
* Buckets that were counted somewhere else — by a database, by a sketch, by
|
|
65
|
+
* a metrics backend that only ever ships histograms.
|
|
66
|
+
*
|
|
67
|
+
* Uneven bucket widths are drawn at their real widths, which is the whole
|
|
68
|
+
* reason this takes edges rather than labels. Set `mode="density"` when they
|
|
69
|
+
* are uneven, or the wide buckets will read as tall ones.
|
|
70
|
+
*/
|
|
71
|
+
data?: HistogramBin[];
|
|
72
|
+
/**
|
|
73
|
+
* How to cut `values` up: a number of equal-width bins, or the explicit
|
|
74
|
+
* edges. Defaults to Freedman–Diaconis (`2 × IQR × n^(-1/3)`), falling back
|
|
75
|
+
* to Sturges when the interquartile range is zero.
|
|
76
|
+
*
|
|
77
|
+
* Explicit edges are a RANGE as well as a set of buckets: an observation
|
|
78
|
+
* outside the first and last edge has no bucket to fall in. It is counted
|
|
79
|
+
* anyway — into the tooltip's share-of-total, and into a "Below" or "Above"
|
|
80
|
+
* row in the table — so a tail your edges cut off is still somewhere a reader
|
|
81
|
+
* can find it.
|
|
82
|
+
*/
|
|
83
|
+
bins?: number | number[];
|
|
84
|
+
/**
|
|
85
|
+
* What the bar heights mean.
|
|
86
|
+
*
|
|
87
|
+
* `frequency` is the count in each bucket and is what a reader assumes.
|
|
88
|
+
* `density` is `count / (n × bin width)`, so the total area is 1 — which is
|
|
89
|
+
* what makes two histograms of different sample sizes comparable, and what
|
|
90
|
+
* makes uneven buckets honest.
|
|
91
|
+
*/
|
|
92
|
+
mode?: HistogramMode;
|
|
93
|
+
/**
|
|
94
|
+
* What the chart shows, in a sentence a reader could act on. Required, and
|
|
95
|
+
* announced to a screen reader even when it is not printed.
|
|
96
|
+
*/
|
|
97
|
+
title: string;
|
|
98
|
+
/** Prints the title above the plot instead of hiding it from sight. */
|
|
99
|
+
showTitle?: boolean;
|
|
100
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
101
|
+
description?: ReactNode;
|
|
102
|
+
/** The composed parts — axes, grid, tooltip, and `<Histogram.Bars>`. */
|
|
103
|
+
children: ReactNode;
|
|
104
|
+
/** Merged onto the figure, last, so a call site can size or space it. */
|
|
105
|
+
className?: string;
|
|
106
|
+
/** Escape hatch onto the raw Recharts chart element. */
|
|
107
|
+
chartProps?: ComponentProps<typeof BarChart>;
|
|
108
|
+
/** Formats the measured values — bin edges, ticks, the tooltip's heading. */
|
|
109
|
+
formatValue?: (value: number) => string;
|
|
110
|
+
/** Drops the hidden table view. Only correct when the page prints the data itself. */
|
|
111
|
+
hideDataTable?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* What the chart shows when it has nothing to draw. `false` keeps the axes,
|
|
114
|
+
* for a chart whose emptiness is itself the reading.
|
|
115
|
+
*/
|
|
116
|
+
empty?: ChartEmptyProps | false;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The shape of one distribution — where the mass sits, how it leans, whether
|
|
120
|
+
* there is more than one hump in it.
|
|
121
|
+
*
|
|
122
|
+
* The form that answers what a `<BoxPlot>` structurally cannot: two clusters,
|
|
123
|
+
* a hard floor, a pile-up at a timeout value. Reach for the box plot when
|
|
124
|
+
* several distributions have to be compared side by side, and for this one when
|
|
125
|
+
* a single distribution has to be understood.
|
|
126
|
+
*
|
|
127
|
+
* **A histogram's shape is a property of its bin width, not only of its data.**
|
|
128
|
+
* The same numbers cut into eight buckets and into eighty are two different
|
|
129
|
+
* pictures, and a gap between two humps can be created or erased by moving a
|
|
130
|
+
* bin edge. That is not a defect to be fixed, it is what binning IS, and the
|
|
131
|
+
* defence is to say which rule drew the picture — the default here is
|
|
132
|
+
* Freedman–Diaconis — and to look at more than one width before believing a
|
|
133
|
+
* feature. Uneven buckets add a second trap: under `frequency` a bucket twice
|
|
134
|
+
* as wide stands twice as tall at the same underlying rate, which is what
|
|
135
|
+
* `mode="density"` exists to correct.
|
|
136
|
+
*
|
|
137
|
+
* Recharts earns its place here for the axes, the grid and the tooltip, but not
|
|
138
|
+
* for the bars: a bar chart's bars are positioned by CATEGORY and a histogram's
|
|
139
|
+
* are positioned and SIZED by a continuous measurement. So the x axis is
|
|
140
|
+
* numeric and each bar is drawn from its own two edges — which is what lets an
|
|
141
|
+
* uneven bucket be as wide as it really is instead of being flattened into an
|
|
142
|
+
* equal slot beside its neighbours.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* <Histogram title="Response times" values={samples} bins={20}>
|
|
146
|
+
* <Histogram.Grid />
|
|
147
|
+
* <Histogram.XAxis label="ms" />
|
|
148
|
+
* <Histogram.YAxis />
|
|
149
|
+
* <Histogram.Tooltip />
|
|
150
|
+
* <Histogram.Bars />
|
|
151
|
+
* </Histogram>
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Buckets that arrived already counted, with uneven widths.
|
|
155
|
+
* <Histogram title="Payload size" data={buckets} mode="density">
|
|
156
|
+
* <Histogram.XAxis />
|
|
157
|
+
* <Histogram.YAxis />
|
|
158
|
+
* <Histogram.Bars />
|
|
159
|
+
* </Histogram>
|
|
160
|
+
*/
|
|
161
|
+
declare function Histogram({ config, values, data, bins, mode, title, showTitle, description, children, className, chartProps, formatValue, hideDataTable, empty, }: HistogramProps): react.JSX.Element;
|
|
162
|
+
declare namespace Histogram {
|
|
163
|
+
var Bars: ({ radius, hatched, barProps }: HistogramBarsProps) => react.JSX.Element;
|
|
164
|
+
var XAxis: ({ dataKey, type, tickLine, axisLine, tickMargin, minTickGap, label, domain, tickFormatter, ...rest }: ChartXAxisProps) => react.JSX.Element;
|
|
165
|
+
var YAxis: ({ tickLine, axisLine, tickMargin, width, label, tickFormatter, ...rest }: ChartYAxisProps) => react.JSX.Element;
|
|
166
|
+
var Grid: ({ strokeDasharray, vertical, ...rest }: ComponentProps<typeof CartesianGrid>) => react.JSX.Element;
|
|
167
|
+
var Tooltip: ({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) => react.JSX.Element;
|
|
168
|
+
var Background: ({ variant }: {
|
|
169
|
+
variant: ChartBackgroundVariant;
|
|
170
|
+
}) => react.JSX.Element;
|
|
171
|
+
var ReferenceLine: typeof ReferenceLine;
|
|
172
|
+
var ReferenceBand: typeof ReferenceBand;
|
|
173
|
+
var Annotation: typeof Annotation;
|
|
174
|
+
}
|
|
175
|
+
interface HistogramBarsProps {
|
|
176
|
+
/**
|
|
177
|
+
* The bars' corner. Zero by default, unlike `<BarChart>`: a histogram's bars
|
|
178
|
+
* are one continuous surface cut into pieces, and a rounded corner draws a
|
|
179
|
+
* gap between two buckets that are touching.
|
|
180
|
+
*/
|
|
181
|
+
radius?: number;
|
|
182
|
+
/** Adds a 45° texture, for a histogram printed in greyscale or overlaid. */
|
|
183
|
+
hatched?: boolean;
|
|
184
|
+
/** Escape hatch onto the underlying Recharts bar. */
|
|
185
|
+
barProps?: ComponentProps<typeof Bar>;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export { Histogram, type HistogramBarsProps, type HistogramBin, type HistogramMode, type HistogramOutside, type HistogramProps, Histogram as default };
|