@misoto22/design 0.7.0 → 0.9.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 +87 -0
- package/CLAUDE.md +1 -0
- package/README.md +50 -5
- package/bin/misoto22-design.mjs +59 -13
- package/dist/agent/Accordion.md +24 -1
- package/dist/agent/Alert.md +23 -1
- package/dist/agent/AppShell.md +30 -2
- package/dist/agent/ArchitectureFigure.md +25 -2
- package/dist/agent/AreaChart.md +27 -2
- package/dist/agent/Article.md +26 -3
- package/dist/agent/AspectRatio.md +57 -0
- package/dist/agent/Avatar.md +25 -5
- package/dist/agent/Badge.md +22 -1
- package/dist/agent/BarChart.md +29 -2
- package/dist/agent/BarList.md +27 -1
- package/dist/agent/BigNumber.md +26 -2
- package/dist/agent/BoxPlot.md +24 -1
- package/dist/agent/Breadcrumb.md +24 -2
- package/dist/agent/BulletChart.md +23 -1
- package/dist/agent/Button.md +25 -1
- package/dist/agent/Calendar.md +37 -3
- package/dist/agent/Card.md +24 -2
- package/dist/agent/Checkbox.md +23 -2
- package/dist/agent/Code.md +50 -0
- package/dist/agent/CodeBlock.md +74 -0
- package/dist/agent/Collapsible.md +22 -1
- package/dist/agent/ColorPicker.md +75 -0
- package/dist/agent/Combobox.md +29 -3
- package/dist/agent/Command.md +25 -2
- package/dist/agent/ComposedChart.md +26 -2
- package/dist/agent/ContextMenu.md +37 -4
- package/dist/agent/DataflowFigure.md +22 -1
- package/dist/agent/DatePicker.md +34 -6
- package/dist/agent/DescriptionList.md +68 -0
- package/dist/agent/Diagram.md +27 -3
- package/dist/agent/DiagramCanvas.md +24 -1
- package/dist/agent/DiagramExportMenu.md +29 -3
- package/dist/agent/DiagramInspector.md +23 -1
- package/dist/agent/DiagramLegend.md +22 -1
- package/dist/agent/DiagramMinimap.md +24 -4
- package/dist/agent/DiagramToolbar.md +23 -1
- package/dist/agent/Dialog.md +26 -3
- package/dist/agent/DropdownMenu.md +45 -6
- package/dist/agent/EmptyState.md +26 -1
- package/dist/agent/ErrorState.md +27 -2
- package/dist/agent/Facet.md +25 -1
- package/dist/agent/Field.md +45 -4
- package/dist/agent/FigureBand.md +24 -1
- package/dist/agent/FloatingIconButton.md +23 -1
- package/dist/agent/FunnelChart.md +23 -1
- package/dist/agent/Heading.md +64 -0
- package/dist/agent/Heatmap.md +25 -1
- package/dist/agent/Histogram.md +26 -2
- package/dist/agent/Input.md +22 -1
- package/dist/agent/Kbd.md +19 -1
- package/dist/agent/LifecycleFigure.md +22 -1
- package/dist/agent/LineChart.md +26 -2
- package/dist/agent/LinkArrow.md +20 -1
- package/dist/agent/Markdown.md +68 -0
- package/dist/agent/NativeSelect.md +23 -2
- package/dist/agent/NavItem.md +21 -1
- package/dist/agent/NumberField.md +72 -0
- package/dist/agent/Pagination.md +28 -2
- package/dist/agent/PieChart.md +26 -2
- package/dist/agent/Popover.md +23 -1
- package/dist/agent/Progress.md +27 -3
- package/dist/agent/RadarChart.md +26 -2
- package/dist/agent/RadialChart.md +26 -3
- package/dist/agent/RadioGroup.md +23 -2
- package/dist/agent/SankeyChart.md +25 -2
- package/dist/agent/ScatterChart.md +27 -2
- package/dist/agent/ScrollArea.md +24 -3
- package/dist/agent/SearchableMenu.md +23 -1
- package/dist/agent/Select.md +29 -3
- package/dist/agent/Separator.md +28 -4
- package/dist/agent/SequenceFigure.md +23 -1
- package/dist/agent/Sheet.md +25 -2
- package/dist/agent/Sidebar.md +193 -0
- package/dist/agent/Skeleton.md +24 -2
- package/dist/agent/Slider.md +31 -4
- package/dist/agent/Sparkline.md +23 -1
- package/dist/agent/Spinner.md +24 -2
- package/dist/agent/StatusDot.md +20 -1
- package/dist/agent/StatusPill.md +28 -2
- package/dist/agent/Steps.md +24 -1
- package/dist/agent/Switch.md +21 -1
- package/dist/agent/Table.md +28 -3
- package/dist/agent/Tabs.md +24 -2
- package/dist/agent/Tag.md +40 -9
- package/dist/agent/Text.md +65 -0
- package/dist/agent/Textarea.md +20 -1
- package/dist/agent/Timestamp.md +64 -0
- package/dist/agent/Toast.md +26 -2
- package/dist/agent/ToggleGroup.md +24 -2
- package/dist/agent/Toolbar.md +71 -0
- package/dist/agent/Tooltip.md +23 -1
- package/dist/agent/TreemapChart.md +24 -1
- package/dist/agent/WaterfallChart.md +24 -1
- package/dist/agent/WorkflowFigure.md +24 -2
- package/dist/agent/catalog.json +5915 -699
- package/dist/agent/index.md +20 -8
- package/dist/article.css +16 -4
- package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
- package/dist/charts/AreaChart/AreaChart.js +12 -13
- package/dist/charts/AreaChart/AreaChart.js.map +1 -1
- package/dist/charts/BarChart/BarChart.d.ts +14 -3
- package/dist/charts/BarChart/BarChart.js +20 -12
- package/dist/charts/BarChart/BarChart.js.map +1 -1
- package/dist/charts/BarList/BarList.d.ts +9 -1
- package/dist/charts/BarList/BarList.js +9 -1
- package/dist/charts/BarList/BarList.js.map +1 -1
- package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
- package/dist/charts/BigNumber/BigNumber.js +25 -5
- package/dist/charts/BigNumber/BigNumber.js.map +1 -1
- package/dist/charts/BoxPlot/BoxPlot.js +4 -2
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
- package/dist/charts/BulletChart/BulletChart.js +44 -9
- package/dist/charts/BulletChart/BulletChart.js.map +1 -1
- package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
- package/dist/charts/ComposedChart/ComposedChart.js +10 -10
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
- package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
- package/dist/charts/FunnelChart/FunnelChart.js +6 -16
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
- package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
- package/dist/charts/Heatmap/Heatmap.js +20 -11
- package/dist/charts/Heatmap/Heatmap.js.map +1 -1
- package/dist/charts/Histogram/Histogram.d.ts +24 -1
- package/dist/charts/Histogram/Histogram.js +43 -11
- package/dist/charts/Histogram/Histogram.js.map +1 -1
- package/dist/charts/LineChart/LineChart.d.ts +9 -2
- package/dist/charts/LineChart/LineChart.js +11 -12
- package/dist/charts/LineChart/LineChart.js.map +1 -1
- package/dist/charts/PieChart/PieChart.d.ts +15 -3
- package/dist/charts/PieChart/PieChart.js +14 -6
- package/dist/charts/PieChart/PieChart.js.map +1 -1
- package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
- package/dist/charts/RadarChart/RadarChart.js +15 -11
- package/dist/charts/RadarChart/RadarChart.js.map +1 -1
- package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
- package/dist/charts/RadialChart/RadialChart.js +28 -6
- package/dist/charts/RadialChart/RadialChart.js.map +1 -1
- package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
- package/dist/charts/SankeyChart/SankeyChart.js +14 -6
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
- package/dist/charts/ScatterChart/ScatterChart.js +21 -15
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
- package/dist/charts/Sparkline/Sparkline.js +5 -3
- package/dist/charts/Sparkline/Sparkline.js.map +1 -1
- package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
- package/dist/charts/TreemapChart/TreemapChart.js +20 -11
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
- package/dist/charts/lib/export.d.ts +1 -0
- package/dist/charts/lib/figure.d.ts +21 -1
- package/dist/charts/lib/figure.js +5 -2
- package/dist/charts/lib/figure.js.map +1 -1
- 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/toolbar.d.ts +1 -0
- package/dist/components/Accordion/Accordion.js +8 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/AppShell/AppShell.d.ts +6 -0
- package/dist/components/AppShell/AppShell.js +34 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +11 -4
- package/dist/components/Article/Article.js +13 -0
- package/dist/components/Article/Article.js.map +1 -1
- 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 +12 -3
- package/dist/components/Avatar/Avatar.js +6 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +14 -0
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +29 -3
- package/dist/components/Calendar/Calendar.js +60 -12
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +5 -2
- package/dist/components/Checkbox/Checkbox.js +12 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- 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 +141 -0
- package/dist/components/CodeBlock/CodeBlock.js +123 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +10 -2
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- 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 +15 -1
- package/dist/components/Combobox/Combobox.js +25 -5
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.d.ts +4 -2
- package/dist/components/Command/Command.js +14 -2
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
- package/dist/components/ContextMenu/ContextMenu.js +33 -3
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +36 -4
- package/dist/components/DatePicker/DatePicker.js +55 -12
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- 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 +8 -3
- package/dist/components/Diagram/Diagram.js +82 -10
- package/dist/components/Diagram/Diagram.js.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +18 -3
- package/dist/components/Dialog/Dialog.js +21 -3
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
- package/dist/components/DropdownMenu/DropdownMenu.js +33 -3
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +25 -1
- package/dist/components/EmptyState/EmptyState.js +3 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.d.ts +22 -1
- package/dist/components/ErrorState/ErrorState.js +12 -3
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +70 -3
- package/dist/components/Field/Field.js +53 -12
- package/dist/components/Field/Field.js.map +1 -1
- 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/FloatingIconButton/FloatingIconButton.js +2 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
- 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/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/NativeSelect/NativeSelect.d.ts +6 -0
- package/dist/components/NativeSelect/NativeSelect.js +2 -3
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/NavItem/NavItem.js +1 -1
- package/dist/components/NavItem/NavItem.js.map +1 -1
- 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/Pagination/Pagination.d.ts +24 -1
- package/dist/components/Pagination/Pagination.js +6 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Progress/Progress.d.ts +17 -5
- package/dist/components/Progress/Progress.js +18 -6
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroup.js +11 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
- package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
- package/dist/components/Select/Select.d.ts +18 -2
- package/dist/components/Select/Select.js +21 -4
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +21 -3
- package/dist/components/Separator/Separator.js +9 -1
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +3 -0
- package/dist/components/Sheet/Sheet.js +12 -3
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.d.ts +349 -0
- package/dist/components/Sidebar/Sidebar.js +455 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +8 -1
- package/dist/components/Skeleton/Skeleton.js +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +42 -3
- package/dist/components/Slider/Slider.js +121 -30
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +8 -0
- package/dist/components/Spinner/Spinner.js +3 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/StatusPill/StatusPill.d.ts +5 -0
- package/dist/components/StatusPill/StatusPill.js +6 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -1
- package/dist/components/Table/Table.d.ts +20 -0
- package/dist/components/Table/Table.js +3 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tabs/Tabs.js +7 -1
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tag/Tag.d.ts +68 -9
- package/dist/components/Tag/Tag.js +50 -10
- package/dist/components/Tag/Tag.js.map +1 -1
- 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/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 +9 -1
- package/dist/components/Toast/Toast.js +27 -4
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- 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/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +6 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +48 -8
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -1
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +21 -2
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -1
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +14 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +14 -7
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -1
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +38 -4
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +14 -16
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -1
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +2 -2
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -1
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +23 -7
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +45 -18
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -1
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +44 -12
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -1
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +35 -5
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +3 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +76 -28
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -1
- package/dist/diagrams/index.d.ts +1 -0
- package/dist/diagrams/index.js +10 -0
- package/dist/diagrams/index.js.map +1 -1
- 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 +48 -7
- package/dist/diagrams/lib/frame.js +17 -2
- package/dist/diagrams/lib/frame.js.map +1 -1
- package/dist/diagrams/lib/route.d.ts +22 -1
- package/dist/diagrams/lib/route.js +24 -1
- package/dist/diagrams/lib/route.js.map +1 -1
- package/dist/diagrams/lib/wires.js +9 -5
- package/dist/diagrams/lib/wires.js.map +1 -1
- package/dist/diagrams/spec.d.ts +64 -12
- package/dist/index.d.ts +19 -4
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/keyframes.css +57 -3
- 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/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 +14 -4
- package/dist/lib/overlay-container.js.map +1 -1
- 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 +17 -6
- package/dist/styles.css +1 -1
- package/dist/themes.css +8 -0
- package/dist/tokens.css +86 -5
- package/dist/tokens.d.ts +4 -1
- package/dist/tokens.js +56 -36
- package/dist/tokens.json +56 -36
- package/llms.txt +35 -0
- package/package.json +5 -2
- package/skills/misoto22-design/evals/evals.json +84 -0
- package/skills/misoto22-design/rules/a11y.md +55 -3
- package/skills/misoto22-design/rules/forms.md +8 -1
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "recharts";
|
|
17
17
|
import { ChartContainer } from "../lib/chart.js";
|
|
18
18
|
import { ChartFigure } from "../lib/figure.js";
|
|
19
|
-
import {
|
|
19
|
+
import {} from "../lib/empty.js";
|
|
20
20
|
import { ChartBackground } from "../lib/background.js";
|
|
21
21
|
import { ChartTooltip } from "../lib/tooltip.js";
|
|
22
22
|
import { BarHatchedFill, SeriesGradient } from "../lib/paint.js";
|
|
@@ -59,12 +59,23 @@ function binEdges(sorted, bins) {
|
|
|
59
59
|
}
|
|
60
60
|
function bin(values, bins) {
|
|
61
61
|
const sorted = values.filter(Number.isFinite).sort((a, b) => a - b);
|
|
62
|
-
if (sorted.length === 0) return [];
|
|
62
|
+
if (sorted.length === 0) return { bins: [], outside: null };
|
|
63
63
|
const edges = binEdges(sorted, bins);
|
|
64
|
-
if (edges.length < 2) return [];
|
|
64
|
+
if (edges.length < 2) return { bins: [], outside: null };
|
|
65
|
+
const low = edges[0];
|
|
66
|
+
const high = edges[edges.length - 1];
|
|
65
67
|
const counts = new Array(edges.length - 1).fill(0);
|
|
68
|
+
let below = 0;
|
|
69
|
+
let above = 0;
|
|
66
70
|
for (const value of sorted) {
|
|
67
|
-
if (value <
|
|
71
|
+
if (value < low) {
|
|
72
|
+
below += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (value > high) {
|
|
76
|
+
above += 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
68
79
|
let index = counts.length - 1;
|
|
69
80
|
for (let i = 0; i < counts.length; i += 1) {
|
|
70
81
|
if (value < edges[i + 1]) {
|
|
@@ -74,7 +85,10 @@ function bin(values, bins) {
|
|
|
74
85
|
}
|
|
75
86
|
counts[index] = counts[index] + 1;
|
|
76
87
|
}
|
|
77
|
-
return
|
|
88
|
+
return {
|
|
89
|
+
bins: counts.map((count, index) => ({ from: edges[index], to: edges[index + 1], count })),
|
|
90
|
+
outside: below + above > 0 ? { below, above, edges: [low, high] } : null
|
|
91
|
+
};
|
|
78
92
|
}
|
|
79
93
|
function resolve(bins, mode, formatValue) {
|
|
80
94
|
const total = bins.reduce((sum, entry) => sum + entry.count, 0);
|
|
@@ -91,6 +105,18 @@ function resolve(bins, mode, formatValue) {
|
|
|
91
105
|
};
|
|
92
106
|
});
|
|
93
107
|
}
|
|
108
|
+
function tableRows(bins, outside, formatValue) {
|
|
109
|
+
const rows = bins;
|
|
110
|
+
if (!outside) return rows;
|
|
111
|
+
const extra = [];
|
|
112
|
+
if (outside.below > 0) {
|
|
113
|
+
extra.push({ label: `Below ${formatValue(outside.edges[0])}`, count: outside.below });
|
|
114
|
+
}
|
|
115
|
+
if (outside.above > 0) {
|
|
116
|
+
extra.push({ label: `Above ${formatValue(outside.edges[1])}`, count: outside.above });
|
|
117
|
+
}
|
|
118
|
+
return [...rows, ...extra];
|
|
119
|
+
}
|
|
94
120
|
const HistogramContext = createContext(null);
|
|
95
121
|
function useHistogram() {
|
|
96
122
|
const context = useContext(HistogramContext);
|
|
@@ -116,17 +142,21 @@ function Histogram({
|
|
|
116
142
|
}) {
|
|
117
143
|
const chartId = useId().replace(/:/g, "");
|
|
118
144
|
const seriesKey = Object.keys(config)[0] ?? "count";
|
|
145
|
+
const counted = useMemo(
|
|
146
|
+
() => data ? { bins: data, outside: null } : bin(values ?? [], bins),
|
|
147
|
+
[data, values, bins]
|
|
148
|
+
);
|
|
119
149
|
const resolved = useMemo(
|
|
120
|
-
() => resolve(
|
|
121
|
-
[
|
|
150
|
+
() => resolve(counted.bins, mode, formatValue),
|
|
151
|
+
[counted, mode, formatValue]
|
|
122
152
|
);
|
|
123
153
|
const domain = useMemo(
|
|
124
154
|
() => resolved.length > 0 ? [resolved[0].from, resolved[resolved.length - 1].to] : [0, 1],
|
|
125
155
|
[resolved]
|
|
126
156
|
);
|
|
127
157
|
const total = useMemo(
|
|
128
|
-
() => resolved.reduce((sum, entry) => sum + entry.count, 0),
|
|
129
|
-
[resolved]
|
|
158
|
+
() => resolved.reduce((sum, entry) => sum + entry.count, 0) + (counted.outside ? counted.outside.below + counted.outside.above : 0),
|
|
159
|
+
[counted, resolved]
|
|
130
160
|
);
|
|
131
161
|
const context = useMemo(
|
|
132
162
|
() => ({ config, seriesKey, bins: resolved, domain, mode, total, formatValue }),
|
|
@@ -141,14 +171,16 @@ function Histogram({
|
|
|
141
171
|
description,
|
|
142
172
|
className,
|
|
143
173
|
table: hideDataTable ? false : {
|
|
144
|
-
rows: resolved,
|
|
174
|
+
rows: tableRows(resolved, counted.outside, formatValue),
|
|
145
175
|
rowKey: "label",
|
|
146
176
|
columns: [
|
|
147
177
|
{ key: "count", label: "Count" },
|
|
148
178
|
...mode === "density" ? [{ key: "height", label: "Density" }] : []
|
|
149
179
|
]
|
|
150
180
|
},
|
|
151
|
-
|
|
181
|
+
isEmpty,
|
|
182
|
+
empty,
|
|
183
|
+
children: /* @__PURE__ */ jsx(ChartContainer, { config, children: /* @__PURE__ */ jsx(
|
|
152
184
|
RechartsBarChart,
|
|
153
185
|
{
|
|
154
186
|
id: chartId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/charts/Histogram/Histogram.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 Bar as RechartsBar,\n BarChart as RechartsBarChart,\n CartesianGrid,\n XAxis as RechartsXAxis,\n YAxis as RechartsYAxis,\n usePlotArea,\n} from 'recharts'\nimport { ChartContainer, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { ChartEmpty, type ChartEmptyProps } from '../lib/empty'\nimport { ChartBackground, type ChartBackgroundVariant } from '../lib/background'\nimport { ChartTooltip } from '../lib/tooltip'\nimport { BarHatchedFill, SeriesGradient } from '../lib/paint'\nimport { Annotation, ReferenceBand, ReferenceLine } from '../lib/annotations'\nimport { axisLabel } from '../lib/axis'\nimport { defaultTick, formatNumber } from '../lib/format'\nimport { cn } from '../../lib/cn'\nimport type { ChartXAxisProps, ChartYAxisProps } from '../BarChart/BarChart'\nimport type { ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\n/** The series a chart with only one of them falls back to. */\nconst DEFAULT_CONFIG: ChartConfig = { count: { label: 'Count' } }\n\nconst CHART_MARGIN = { top: 12, right: 12, bottom: 0, left: 12 }\n\n/**\n * The most bins the automatic rule will ever ask for.\n *\n * Freedman–Diaconis divides by the interquartile range, so a distribution with\n * a tight middle and a long tail can ask for tens of thousands of bins — each\n * one a rectangle narrower than a pixel. The cap turns that into a coarse\n * histogram rather than into a hung tab.\n */\nconst MAX_BINS = 200\n\n/** Bars touch in a histogram; this is the hairline that keeps them countable. */\nconst BAR_SEPARATION = 1\n\n/** What the bar heights mean. */\nexport type HistogramMode = 'frequency' | 'density'\n\n/** One bucket, as the chart draws it. */\nexport interface HistogramBin {\n /** The bucket's lower edge, inclusive. */\n from: number\n /** The bucket's upper edge, exclusive — except the last, which includes it. */\n to: number\n /** How many observations fell in it. */\n count: number\n}\n\n/** A bin with everything the marks and the table need resolved. */\ninterface ResolvedBin extends HistogramBin {\n /** The bucket's midpoint, which is where Recharts positions the bar. */\n center: number\n /** What the bar's length encodes, per `mode`. */\n height: number\n /** The bucket's range, written out — the table's row header. */\n label: string\n}\n\n/**\n * The quantile at `p`, interpolated between neighbouring order statistics\n * (R type 7 / NumPy default). Used only to get the IQR the bin-width rule\n * needs.\n */\nfunction quantile(sorted: number[], p: number): number {\n if (sorted.length === 0) return Number.NaN\n if (sorted.length === 1) return sorted[0]!\n\n const h = (sorted.length - 1) * p\n const lower = sorted[Math.floor(h)]!\n const upper = sorted[Math.ceil(h)]!\n return lower + (h - Math.floor(h)) * (upper - lower)\n}\n\n/**\n * How many bins to cut the data into when the call site does not say.\n *\n * Freedman–Diaconis: bin width is `2 × IQR × n^(-1/3)`, which is the rule that\n * minimises the difference between the drawn histogram and the density it is\n * standing in for, and — because it reads the IQR rather than the range — the\n * one that a single far outlier cannot stretch into one tall bar and forty\n * empty ones.\n *\n * It has one failure mode: a distribution with more than half its mass on one\n * value has an IQR of zero and asks for infinitely many bins. Sturges' rule,\n * `⌈log₂ n⌉ + 1`, is the fallback there.\n */\nfunction binCount(sorted: number[]): number {\n const n = sorted.length\n const span = sorted[n - 1]! - sorted[0]!\n if (span <= 0) return 1\n\n const iqr = quantile(sorted, 0.75) - quantile(sorted, 0.25)\n const width = 2 * iqr * Math.pow(n, -1 / 3)\n const suggested =\n width > 0 ? Math.ceil(span / width) : Math.ceil(Math.log2(n)) + 1\n\n return Math.max(1, Math.min(MAX_BINS, suggested))\n}\n\n/** The edges the observations are cut at, low to high. */\nfunction binEdges(sorted: number[], bins: number | number[] | undefined): number[] {\n if (Array.isArray(bins)) {\n const edges = [...new Set(bins.filter(Number.isFinite))].sort((a, b) => a - b)\n return edges.length >= 2 ? edges : []\n }\n\n const low = sorted[0]!\n const high = sorted[sorted.length - 1]!\n // Every observation on one value still has to be drawn as something, and a\n // zero-width bar is nothing. One unit of room either side is the smallest\n // honest answer: one bar, centred on the only value there is.\n if (high === low) return [low - 0.5, low + 0.5]\n\n const count = Math.max(1, Math.min(MAX_BINS, typeof bins === 'number' ? bins : binCount(sorted)))\n const width = (high - low) / count\n return Array.from({ length: count + 1 }, (_, index) => low + index * width)\n}\n\n/** Raw observations, cut into buckets. */\nfunction bin(values: number[], bins: number | number[] | undefined): HistogramBin[] {\n const sorted = values.filter(Number.isFinite).sort((a, b) => a - b)\n if (sorted.length === 0) return []\n\n const edges = binEdges(sorted, bins)\n if (edges.length < 2) return []\n\n const counts = new Array<number>(edges.length - 1).fill(0)\n for (const value of sorted) {\n if (value < edges[0]! || value > edges[edges.length - 1]!) continue\n // The top edge belongs to the last bucket. Without that the largest\n // observation falls out of the histogram entirely, which is exactly the\n // point a reader is most likely to be looking for.\n let index = counts.length - 1\n for (let i = 0; i < counts.length; i += 1) {\n if (value < edges[i + 1]!) {\n index = i\n break\n }\n }\n counts[index] = counts[index]! + 1\n }\n\n return counts.map((count, index) => ({ from: edges[index]!, to: edges[index + 1]!, count }))\n}\n\n/** The bins with their midpoints, drawn heights and printed ranges. */\nfunction resolve(\n bins: HistogramBin[],\n mode: HistogramMode,\n formatValue: (value: number) => string,\n): ResolvedBin[] {\n const total = bins.reduce((sum, entry) => sum + entry.count, 0)\n\n return bins.map((entry) => {\n const width = entry.to - entry.from\n return {\n ...entry,\n center: entry.from + width / 2,\n // Density is `count / (n × width)`, so the bars enclose an area of 1 and\n // uneven buckets stop lying: under frequency a bucket twice as wide\n // stands twice as tall for the same underlying rate.\n height:\n mode === 'density' && total > 0 && width > 0 ? entry.count / (total * width) : entry.count,\n label: `${formatValue(entry.from)} – ${formatValue(entry.to)}`,\n }\n })\n}\n\ninterface HistogramContextValue {\n config: ChartConfig\n seriesKey: string\n bins: ResolvedBin[]\n domain: [number, number]\n mode: HistogramMode\n total: number\n formatValue: (value: number) => string\n}\n\nconst HistogramContext = createContext<HistogramContextValue | null>(null)\n\nfunction useHistogram(): HistogramContextValue {\n const context = useContext(HistogramContext)\n if (!context) throw new Error('A histogram part must be rendered inside <Histogram>')\n return context\n}\n\n/** Density values are small and unequal; the count axis is integers. */\nconst densityTick = formatNumber({ style: 'plain', fractionDigits: 3 })\n\nexport interface HistogramProps {\n /**\n * The single series — its label and its paint. Only the FIRST entry is read;\n * a histogram has one distribution and as many bars as it has buckets.\n */\n config?: ChartConfig\n /**\n * The raw observations, in any order. Binned for you by `bins`.\n *\n * Give this OR `data`, not both — `data` wins if both arrive.\n */\n values?: number[]\n /**\n * Buckets that were counted somewhere else — by a database, by a sketch, by\n * a metrics backend that only ever ships histograms.\n *\n * Uneven bucket widths are drawn at their real widths, which is the whole\n * reason this takes edges rather than labels. Set `mode=\"density\"` when they\n * are uneven, or the wide buckets will read as tall ones.\n */\n data?: HistogramBin[]\n /**\n * How to cut `values` up: a number of equal-width bins, or the explicit\n * edges. Defaults to Freedman–Diaconis (`2 × IQR × n^(-1/3)`), falling back\n * to Sturges when the interquartile range is zero.\n */\n bins?: number | number[]\n /**\n * What the bar heights mean.\n *\n * `frequency` is the count in each bucket and is what a reader assumes.\n * `density` is `count / (n × bin width)`, so the total area is 1 — which is\n * what makes two histograms of different sample sizes comparable, and what\n * makes uneven buckets honest.\n */\n mode?: HistogramMode\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 — axes, grid, tooltip, and `<Histogram.Bars>`. */\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 RechartsBarChart>\n /** Formats the measured values — bin edges, ticks, the tooltip's heading. */\n formatValue?: (value: number) => string\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 axes,\n * for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * The shape of one distribution — where the mass sits, how it leans, whether\n * there is more than one hump in it.\n *\n * The form that answers what a `<BoxPlot>` structurally cannot: two clusters,\n * a hard floor, a pile-up at a timeout value. Reach for the box plot when\n * several distributions have to be compared side by side, and for this one when\n * a single distribution has to be understood.\n *\n * **A histogram's shape is a property of its bin width, not only of its data.**\n * The same numbers cut into eight buckets and into eighty are two different\n * pictures, and a gap between two humps can be created or erased by moving a\n * bin edge. That is not a defect to be fixed, it is what binning IS, and the\n * defence is to say which rule drew the picture — the default here is\n * Freedman–Diaconis — and to look at more than one width before believing a\n * feature. Uneven buckets add a second trap: under `frequency` a bucket twice\n * as wide stands twice as tall at the same underlying rate, which is what\n * `mode=\"density\"` exists to correct.\n *\n * Recharts earns its place here for the axes, the grid and the tooltip, but not\n * for the bars: a bar chart's bars are positioned by CATEGORY and a histogram's\n * are positioned and SIZED by a continuous measurement. So the x axis is\n * numeric and each bar is drawn from its own two edges — which is what lets an\n * uneven bucket be as wide as it really is instead of being flattened into an\n * equal slot beside its neighbours.\n *\n * @example\n * <Histogram title=\"Response times\" values={samples} bins={20}>\n * <Histogram.Grid />\n * <Histogram.XAxis label=\"ms\" />\n * <Histogram.YAxis />\n * <Histogram.Tooltip />\n * <Histogram.Bars />\n * </Histogram>\n *\n * @example\n * // Buckets that arrived already counted, with uneven widths.\n * <Histogram title=\"Payload size\" data={buckets} mode=\"density\">\n * <Histogram.XAxis />\n * <Histogram.YAxis />\n * <Histogram.Bars />\n * </Histogram>\n */\nexport function Histogram({\n config = DEFAULT_CONFIG,\n values,\n data,\n bins,\n mode = 'frequency',\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n formatValue = defaultTick,\n hideDataTable = false,\n empty,\n}: HistogramProps) {\n const chartId = useId().replace(/:/g, '')\n const seriesKey = Object.keys(config)[0] ?? 'count'\n\n const resolved = useMemo(\n () => resolve(data ?? bin(values ?? [], bins), mode, formatValue),\n [data, values, bins, mode, formatValue],\n )\n\n const domain = useMemo<[number, number]>(\n () =>\n resolved.length > 0 ? [resolved[0]!.from, resolved[resolved.length - 1]!.to] : [0, 1],\n [resolved],\n )\n\n const total = useMemo(\n () => resolved.reduce((sum, entry) => sum + entry.count, 0),\n [resolved],\n )\n\n const context = useMemo<HistogramContextValue>(\n () => ({ config, seriesKey, bins: resolved, domain, mode, total, formatValue }),\n [config, seriesKey, resolved, domain, mode, total, formatValue],\n )\n\n const isEmpty = empty !== false && resolved.length === 0\n\n return (\n <HistogramContext.Provider value={context}>\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable\n ? false\n : {\n rows: resolved as unknown as Record<string, unknown>[],\n rowKey: 'label',\n columns: [\n { key: 'count', label: 'Count' },\n ...(mode === 'density' ? [{ key: 'height', label: 'Density' }] : []),\n ],\n }\n }\n >\n {isEmpty ? (\n <ChartEmpty {...(empty || {})} />\n ) : (\n <ChartContainer config={config}>\n <RechartsBarChart\n id={chartId}\n accessibilityLayer\n margin={CHART_MARGIN}\n data={resolved}\n {...chartProps}\n >\n {children}\n </RechartsBarChart>\n </ChartContainer>\n )}\n </ChartFigure>\n </HistogramContext.Provider>\n )\n}\n\nexport interface HistogramBarsProps {\n /**\n * The bars' corner. Zero by default, unlike `<BarChart>`: a histogram's bars\n * are one continuous surface cut into pieces, and a rounded corner draws a\n * gap between two buckets that are touching.\n */\n radius?: number\n /** Adds a 45° texture, for a histogram printed in greyscale or overlaid. */\n hatched?: boolean\n /** Escape hatch onto the underlying Recharts bar. */\n barProps?: ComponentProps<typeof RechartsBar>\n}\n\n/**\n * The bars themselves, each drawn between its own two bin edges.\n *\n * Recharts positions a bar on a numeric axis by CENTRING it on the value and\n * sizing it from the band, which would draw every bucket the same width. The\n * shape re-derives both edges from the plot area and the axis domain instead,\n * so a bucket is exactly as wide as the range it counts.\n */\nfunction Bars({ radius = 0, hatched = false, barProps }: HistogramBarsProps) {\n const { config, seriesKey } = useHistogram()\n const id = useId().replace(/:/g, '')\n\n return (\n <>\n <RechartsBar\n dataKey=\"height\"\n name={seriesKey}\n isAnimationActive={false}\n fill={`url(#${id}-colors-${seriesKey})`}\n shape={(props: unknown) => (\n <BinShape {...(props as BinGeometry)} id={id} seriesKey={seriesKey} radius={radius} hatched={hatched} />\n )}\n activeBar={(props: unknown) => (\n <BinShape {...(props as BinGeometry)} id={id} seriesKey={seriesKey} radius={radius} hatched={hatched} />\n )}\n {...barProps}\n />\n <defs>\n <SeriesGradient id={id} dataKey={seriesKey} config={config} direction=\"vertical\" />\n {hatched && <BarHatchedFill id={id} dataKey={seriesKey} />}\n </defs>\n </>\n )\n}\n\n/** The geometry Recharts hands a custom bar shape, plus the bin behind it. */\ninterface BinGeometry {\n x?: number\n y?: number\n width?: number\n height?: number\n payload?: ResolvedBin\n}\n\ninterface BinShapeProps extends BinGeometry {\n id: string\n seriesKey: string\n radius: number\n hatched: boolean\n}\n\n/** One bucket, spanning its real width on the measured axis. */\nfunction BinShape({\n x = 0,\n y = 0,\n width = 0,\n height = 0,\n payload,\n id,\n seriesKey,\n radius,\n hatched,\n}: BinShapeProps) {\n const plot = usePlotArea()\n const { domain } = useHistogram()\n\n if (!payload) return null\n\n const [low, high] = domain\n const span = high - low\n const edges =\n plot && span > 0\n ? {\n start: plot.x + ((payload.from - low) / span) * plot.width,\n end: plot.x + ((payload.to - low) / span) * plot.width,\n }\n : // Before the chart has measured itself there is no plot to map onto,\n // and Recharts' own band is the only geometry available.\n { start: x, end: x + width }\n\n const drawn = Math.max(1, edges.end - edges.start - BAR_SEPARATION)\n\n return (\n <rect\n x={edges.start + BAR_SEPARATION / 2}\n y={y}\n width={drawn}\n height={Math.max(0, height)}\n rx={radius || undefined}\n fill={hatched ? `url(#${id}-hatched-${seriesKey})` : `url(#${id}-colors-${seriesKey})`}\n />\n )\n}\n\n/** The measured axis. Numeric, because the buckets are a cut of a real scale. */\nfunction XAxis({\n dataKey = 'center',\n type = 'number',\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n label,\n domain,\n tickFormatter,\n ...rest\n}: ChartXAxisProps) {\n const { domain: measured, formatValue } = useHistogram()\n\n return (\n <RechartsXAxis\n dataKey={dataKey}\n type={type}\n // Pinned to the outermost bin edges rather than left to Recharts, which\n // would pad the domain out to round numbers and leave the first and last\n // bars floating off their own edges.\n domain={domain ?? measured}\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n tickFormatter={tickFormatter ?? formatValue}\n {...rest}\n >\n {axisLabel(label, 'x')}\n </RechartsXAxis>\n )\n}\n\n/** The count axis, or the density axis. */\nfunction YAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n width = 'auto',\n label,\n tickFormatter,\n ...rest\n}: ChartYAxisProps) {\n const { mode } = useHistogram()\n\n return (\n <RechartsYAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n width={width}\n tickFormatter={tickFormatter ?? (mode === 'density' ? densityTick : defaultTick)}\n {...rest}\n >\n {axisLabel(label ?? (mode === 'density' ? 'Density' : undefined), 'y')}\n </RechartsYAxis>\n )\n}\n\n/** Rules across the count axis. */\nfunction Grid({\n strokeDasharray = '3 3',\n vertical = false,\n ...rest\n}: ComponentProps<typeof CartesianGrid>) {\n return <CartesianGrid strokeDasharray={strokeDasharray} vertical={vertical} {...rest} />\n}\n\n/**\n * The hover panel, printing the bucket's range rather than its midpoint.\n *\n * The generic tooltip would head the panel with the centre value, which is a\n * number no observation necessarily has. What a reader wants from a histogram\n * bar is the interval it counts and how much of the sample fell in it.\n */\nfunction Tooltip({ variant = 'solid', roundness = 'lg', defaultIndex }: ChartTooltipSlotProps) {\n const { mode, total, formatValue } = useHistogram()\n\n return (\n <ChartTooltip\n cursor={false}\n defaultIndex={defaultIndex}\n content={(props) => {\n const { active, payload } = props as unknown as {\n active?: boolean\n payload?: { payload?: ResolvedBin }[]\n }\n const entry = payload?.[0]?.payload\n if (!active || !entry) return <span className=\"p-4\" />\n\n const share = total > 0 ? entry.count / total : 0\n\n return (\n <div\n className={cn(\n 'grid min-w-40 gap-1.5 border border-(--rule-2) px-2.5 py-1.5 text-xs',\n roundness === 'sm' && 'rounded-(--radius-sm)',\n roundness === 'md' && 'rounded-(--radius)',\n roundness === 'lg' && 'rounded-(--radius-lg)',\n variant === 'frosted'\n ? 'bg-(--chart-surface)/75 backdrop-blur-sm'\n : 'bg-(--chart-surface)',\n )}\n >\n <div className=\"font-medium text-(--ink)\">\n {formatValue(entry.from)} – {formatValue(entry.to)}\n </div>\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Count</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {entry.count.toLocaleString()}\n </span>\n </div>\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Share</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {(share * 100).toFixed(1)}%\n </span>\n </div>\n {mode === 'density' && (\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Density</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {densityTick(entry.height)}\n </span>\n </div>\n )}\n </div>\n )\n }}\n />\n )\n}\n\n/** The decorative plate behind the plot. */\nfunction Background({ variant }: { variant: ChartBackgroundVariant }) {\n return <ChartBackground variant={variant} />\n}\n\nHistogram.Bars = Bars\nHistogram.XAxis = XAxis\nHistogram.YAxis = YAxis\nHistogram.Grid = Grid\nHistogram.Tooltip = Tooltip\nHistogram.Background = Background\nHistogram.ReferenceLine = ReferenceLine\nHistogram.ReferenceBand = ReferenceBand\nHistogram.Annotation = Annotation\n\nexport default Histogram\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/Histogram/Histogram.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 Bar as RechartsBar,\n BarChart as RechartsBarChart,\n CartesianGrid,\n XAxis as RechartsXAxis,\n YAxis as RechartsYAxis,\n usePlotArea,\n} from 'recharts'\nimport { ChartContainer, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { type ChartEmptyProps } from '../lib/empty'\nimport { ChartBackground, type ChartBackgroundVariant } from '../lib/background'\nimport { ChartTooltip } from '../lib/tooltip'\nimport { BarHatchedFill, SeriesGradient } from '../lib/paint'\nimport { Annotation, ReferenceBand, ReferenceLine } from '../lib/annotations'\nimport { axisLabel } from '../lib/axis'\nimport { defaultTick, formatNumber } from '../lib/format'\nimport { cn } from '../../lib/cn'\nimport type { ChartXAxisProps, ChartYAxisProps } from '../BarChart/BarChart'\nimport type { ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\n/** The series a chart with only one of them falls back to. */\nconst DEFAULT_CONFIG: ChartConfig = { count: { label: 'Count' } }\n\nconst CHART_MARGIN = { top: 12, right: 12, bottom: 0, left: 12 }\n\n/**\n * The most bins the automatic rule will ever ask for.\n *\n * Freedman–Diaconis divides by the interquartile range, so a distribution with\n * a tight middle and a long tail can ask for tens of thousands of bins — each\n * one a rectangle narrower than a pixel. The cap turns that into a coarse\n * histogram rather than into a hung tab.\n */\nconst MAX_BINS = 200\n\n/** Bars touch in a histogram; this is the hairline that keeps them countable. */\nconst BAR_SEPARATION = 1\n\n/** What the bar heights mean. */\nexport type HistogramMode = 'frequency' | 'density'\n\n/** One bucket, as the chart draws it. */\nexport interface HistogramBin {\n /** The bucket's lower edge, inclusive. */\n from: number\n /** The bucket's upper edge, exclusive — except the last, which includes it. */\n to: number\n /** How many observations fell in it. */\n count: number\n}\n\n/** A bin with everything the marks and the table need resolved. */\ninterface ResolvedBin extends HistogramBin {\n /** The bucket's midpoint, which is where Recharts positions the bar. */\n center: number\n /** What the bar's length encodes, per `mode`. */\n height: number\n /** The bucket's range, written out — the table's row header. */\n label: string\n}\n\n/**\n * The quantile at `p`, interpolated between neighbouring order statistics\n * (R type 7 / NumPy default). Used only to get the IQR the bin-width rule\n * needs.\n */\nfunction quantile(sorted: number[], p: number): number {\n if (sorted.length === 0) return Number.NaN\n if (sorted.length === 1) return sorted[0]!\n\n const h = (sorted.length - 1) * p\n const lower = sorted[Math.floor(h)]!\n const upper = sorted[Math.ceil(h)]!\n return lower + (h - Math.floor(h)) * (upper - lower)\n}\n\n/**\n * How many bins to cut the data into when the call site does not say.\n *\n * Freedman–Diaconis: bin width is `2 × IQR × n^(-1/3)`, which is the rule that\n * minimises the difference between the drawn histogram and the density it is\n * standing in for, and — because it reads the IQR rather than the range — the\n * one that a single far outlier cannot stretch into one tall bar and forty\n * empty ones.\n *\n * It has one failure mode: a distribution with more than half its mass on one\n * value has an IQR of zero and asks for infinitely many bins. Sturges' rule,\n * `⌈log₂ n⌉ + 1`, is the fallback there.\n */\nfunction binCount(sorted: number[]): number {\n const n = sorted.length\n const span = sorted[n - 1]! - sorted[0]!\n if (span <= 0) return 1\n\n const iqr = quantile(sorted, 0.75) - quantile(sorted, 0.25)\n const width = 2 * iqr * Math.pow(n, -1 / 3)\n const suggested =\n width > 0 ? Math.ceil(span / width) : Math.ceil(Math.log2(n)) + 1\n\n return Math.max(1, Math.min(MAX_BINS, suggested))\n}\n\n/** The edges the observations are cut at, low to high. */\nfunction binEdges(sorted: number[], bins: number | number[] | undefined): number[] {\n if (Array.isArray(bins)) {\n const edges = [...new Set(bins.filter(Number.isFinite))].sort((a, b) => a - b)\n return edges.length >= 2 ? edges : []\n }\n\n const low = sorted[0]!\n const high = sorted[sorted.length - 1]!\n // Every observation on one value still has to be drawn as something, and a\n // zero-width bar is nothing. One unit of room either side is the smallest\n // honest answer: one bar, centred on the only value there is.\n if (high === low) return [low - 0.5, low + 0.5]\n\n const count = Math.max(1, Math.min(MAX_BINS, typeof bins === 'number' ? bins : binCount(sorted)))\n const width = (high - low) / count\n return Array.from({ length: count + 1 }, (_, index) => low + index * width)\n}\n\n/**\n * Observations the bins do not reach, and the edge each fell outside.\n *\n * Only ever non-zero when the call site gave explicit `bins` edges: a derived\n * width spans the data by construction. When it IS non-zero it is the reading\n * that matters most — a tail cut off by a hand-picked range — and dropping it\n * silently hid it from the picture, from the table and from the tooltip's\n * share-of-total all at once.\n */\nexport interface HistogramOutside {\n /** How many observations fell below the first edge. */\n below: number\n /** How many fell above the last. */\n above: number\n /** The first edge, and the last. */\n edges: [number, number]\n}\n\n/** Raw observations, cut into buckets, with whatever the buckets missed. */\nfunction bin(\n values: number[],\n bins: number | number[] | undefined,\n): { bins: HistogramBin[]; outside: HistogramOutside | null } {\n const sorted = values.filter(Number.isFinite).sort((a, b) => a - b)\n if (sorted.length === 0) return { bins: [], outside: null }\n\n const edges = binEdges(sorted, bins)\n if (edges.length < 2) return { bins: [], outside: null }\n\n const low = edges[0]!\n const high = edges[edges.length - 1]!\n const counts = new Array<number>(edges.length - 1).fill(0)\n let below = 0\n let above = 0\n\n for (const value of sorted) {\n if (value < low) {\n below += 1\n continue\n }\n if (value > high) {\n above += 1\n continue\n }\n // The top edge belongs to the last bucket. Without that the largest\n // observation falls out of the histogram entirely, which is exactly the\n // point a reader is most likely to be looking for.\n let index = counts.length - 1\n for (let i = 0; i < counts.length; i += 1) {\n if (value < edges[i + 1]!) {\n index = i\n break\n }\n }\n counts[index] = counts[index]! + 1\n }\n\n return {\n bins: counts.map((count, index) => ({ from: edges[index]!, to: edges[index + 1]!, count })),\n outside: below + above > 0 ? { below, above, edges: [low, high] } : null,\n }\n}\n\n/** The bins with their midpoints, drawn heights and printed ranges. */\nfunction resolve(\n bins: HistogramBin[],\n mode: HistogramMode,\n formatValue: (value: number) => string,\n): ResolvedBin[] {\n const total = bins.reduce((sum, entry) => sum + entry.count, 0)\n\n return bins.map((entry) => {\n const width = entry.to - entry.from\n return {\n ...entry,\n center: entry.from + width / 2,\n // Density is `count / (n × width)`, so the bars enclose an area of 1 and\n // uneven buckets stop lying: under frequency a bucket twice as wide\n // stands twice as tall for the same underlying rate.\n height:\n mode === 'density' && total > 0 && width > 0 ? entry.count / (total * width) : entry.count,\n label: `${formatValue(entry.from)} – ${formatValue(entry.to)}`,\n }\n })\n}\n\n/**\n * The table's rows: every bucket, then whatever the buckets did not reach.\n *\n * The out-of-range rows are the only place the dropped observations appear as\n * numbers. They carry no `height`, because they have no width to be drawn at —\n * they are a count, not a bar.\n */\nfunction tableRows(\n bins: ResolvedBin[],\n outside: HistogramOutside | null,\n formatValue: (value: number) => string,\n): Record<string, unknown>[] {\n const rows = bins as unknown as Record<string, unknown>[]\n if (!outside) return rows\n\n const extra: Record<string, unknown>[] = []\n if (outside.below > 0) {\n extra.push({ label: `Below ${formatValue(outside.edges[0])}`, count: outside.below })\n }\n if (outside.above > 0) {\n extra.push({ label: `Above ${formatValue(outside.edges[1])}`, count: outside.above })\n }\n return [...rows, ...extra]\n}\n\ninterface HistogramContextValue {\n config: ChartConfig\n seriesKey: string\n bins: ResolvedBin[]\n domain: [number, number]\n mode: HistogramMode\n total: number\n formatValue: (value: number) => string\n}\n\nconst HistogramContext = createContext<HistogramContextValue | null>(null)\n\nfunction useHistogram(): HistogramContextValue {\n const context = useContext(HistogramContext)\n if (!context) throw new Error('A histogram part must be rendered inside <Histogram>')\n return context\n}\n\n/** Density values are small and unequal; the count axis is integers. */\nconst densityTick = formatNumber({ style: 'plain', fractionDigits: 3 })\n\nexport interface HistogramProps {\n /**\n * The single series — its label and its paint. Only the FIRST entry is read;\n * a histogram has one distribution and as many bars as it has buckets.\n */\n config?: ChartConfig\n /**\n * The raw observations, in any order. Binned for you by `bins`.\n *\n * Give this OR `data`, not both — `data` wins if both arrive.\n */\n values?: number[]\n /**\n * Buckets that were counted somewhere else — by a database, by a sketch, by\n * a metrics backend that only ever ships histograms.\n *\n * Uneven bucket widths are drawn at their real widths, which is the whole\n * reason this takes edges rather than labels. Set `mode=\"density\"` when they\n * are uneven, or the wide buckets will read as tall ones.\n */\n data?: HistogramBin[]\n /**\n * How to cut `values` up: a number of equal-width bins, or the explicit\n * edges. Defaults to Freedman–Diaconis (`2 × IQR × n^(-1/3)`), falling back\n * to Sturges when the interquartile range is zero.\n *\n * Explicit edges are a RANGE as well as a set of buckets: an observation\n * outside the first and last edge has no bucket to fall in. It is counted\n * anyway — into the tooltip's share-of-total, and into a \"Below\" or \"Above\"\n * row in the table — so a tail your edges cut off is still somewhere a reader\n * can find it.\n */\n bins?: number | number[]\n /**\n * What the bar heights mean.\n *\n * `frequency` is the count in each bucket and is what a reader assumes.\n * `density` is `count / (n × bin width)`, so the total area is 1 — which is\n * what makes two histograms of different sample sizes comparable, and what\n * makes uneven buckets honest.\n */\n mode?: HistogramMode\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 — axes, grid, tooltip, and `<Histogram.Bars>`. */\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 RechartsBarChart>\n /** Formats the measured values — bin edges, ticks, the tooltip's heading. */\n formatValue?: (value: number) => string\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 axes,\n * for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * The shape of one distribution — where the mass sits, how it leans, whether\n * there is more than one hump in it.\n *\n * The form that answers what a `<BoxPlot>` structurally cannot: two clusters,\n * a hard floor, a pile-up at a timeout value. Reach for the box plot when\n * several distributions have to be compared side by side, and for this one when\n * a single distribution has to be understood.\n *\n * **A histogram's shape is a property of its bin width, not only of its data.**\n * The same numbers cut into eight buckets and into eighty are two different\n * pictures, and a gap between two humps can be created or erased by moving a\n * bin edge. That is not a defect to be fixed, it is what binning IS, and the\n * defence is to say which rule drew the picture — the default here is\n * Freedman–Diaconis — and to look at more than one width before believing a\n * feature. Uneven buckets add a second trap: under `frequency` a bucket twice\n * as wide stands twice as tall at the same underlying rate, which is what\n * `mode=\"density\"` exists to correct.\n *\n * Recharts earns its place here for the axes, the grid and the tooltip, but not\n * for the bars: a bar chart's bars are positioned by CATEGORY and a histogram's\n * are positioned and SIZED by a continuous measurement. So the x axis is\n * numeric and each bar is drawn from its own two edges — which is what lets an\n * uneven bucket be as wide as it really is instead of being flattened into an\n * equal slot beside its neighbours.\n *\n * @example\n * <Histogram title=\"Response times\" values={samples} bins={20}>\n * <Histogram.Grid />\n * <Histogram.XAxis label=\"ms\" />\n * <Histogram.YAxis />\n * <Histogram.Tooltip />\n * <Histogram.Bars />\n * </Histogram>\n *\n * @example\n * // Buckets that arrived already counted, with uneven widths.\n * <Histogram title=\"Payload size\" data={buckets} mode=\"density\">\n * <Histogram.XAxis />\n * <Histogram.YAxis />\n * <Histogram.Bars />\n * </Histogram>\n */\nexport function Histogram({\n config = DEFAULT_CONFIG,\n values,\n data,\n bins,\n mode = 'frequency',\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n formatValue = defaultTick,\n hideDataTable = false,\n empty,\n}: HistogramProps) {\n const chartId = useId().replace(/:/g, '')\n const seriesKey = Object.keys(config)[0] ?? 'count'\n\n const counted = useMemo(\n () => (data ? { bins: data, outside: null } : bin(values ?? [], bins)),\n [data, values, bins],\n )\n\n const resolved = useMemo(\n () => resolve(counted.bins, mode, formatValue),\n [counted, mode, formatValue],\n )\n\n const domain = useMemo<[number, number]>(\n () =>\n resolved.length > 0 ? [resolved[0]!.from, resolved[resolved.length - 1]!.to] : [0, 1],\n [resolved],\n )\n\n // The SAMPLE, not the drawn buckets. A tooltip whose shares are taken over\n // the bins alone always sums to 100%, however much of the data the bins\n // missed — so the one number that would reveal the cut-off tail is exactly\n // the one that hides it.\n const total = useMemo(\n () =>\n resolved.reduce((sum, entry) => sum + entry.count, 0) +\n (counted.outside ? counted.outside.below + counted.outside.above : 0),\n [counted, resolved],\n )\n\n const context = useMemo<HistogramContextValue>(\n () => ({ config, seriesKey, bins: resolved, domain, mode, total, formatValue }),\n [config, seriesKey, resolved, domain, mode, total, formatValue],\n )\n\n const isEmpty = empty !== false && resolved.length === 0\n\n return (\n <HistogramContext.Provider value={context}>\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable\n ? false\n : {\n rows: tableRows(resolved, counted.outside, formatValue),\n rowKey: 'label',\n columns: [\n { key: 'count', label: 'Count' },\n ...(mode === 'density' ? [{ key: 'height', label: 'Density' }] : []),\n ],\n }\n }\n isEmpty={isEmpty}\n empty={empty}\n >\n <ChartContainer config={config}>\n <RechartsBarChart\n id={chartId}\n accessibilityLayer\n margin={CHART_MARGIN}\n data={resolved}\n {...chartProps}\n >\n {children}\n </RechartsBarChart>\n </ChartContainer>\n </ChartFigure>\n </HistogramContext.Provider>\n )\n}\n\nexport interface HistogramBarsProps {\n /**\n * The bars' corner. Zero by default, unlike `<BarChart>`: a histogram's bars\n * are one continuous surface cut into pieces, and a rounded corner draws a\n * gap between two buckets that are touching.\n */\n radius?: number\n /** Adds a 45° texture, for a histogram printed in greyscale or overlaid. */\n hatched?: boolean\n /** Escape hatch onto the underlying Recharts bar. */\n barProps?: ComponentProps<typeof RechartsBar>\n}\n\n/**\n * The bars themselves, each drawn between its own two bin edges.\n *\n * Recharts positions a bar on a numeric axis by CENTRING it on the value and\n * sizing it from the band, which would draw every bucket the same width. The\n * shape re-derives both edges from the plot area and the axis domain instead,\n * so a bucket is exactly as wide as the range it counts.\n */\nfunction Bars({ radius = 0, hatched = false, barProps }: HistogramBarsProps) {\n const { config, seriesKey } = useHistogram()\n const id = useId().replace(/:/g, '')\n\n return (\n <>\n <RechartsBar\n dataKey=\"height\"\n name={seriesKey}\n isAnimationActive={false}\n fill={`url(#${id}-colors-${seriesKey})`}\n shape={(props: unknown) => (\n <BinShape {...(props as BinGeometry)} id={id} seriesKey={seriesKey} radius={radius} hatched={hatched} />\n )}\n activeBar={(props: unknown) => (\n <BinShape {...(props as BinGeometry)} id={id} seriesKey={seriesKey} radius={radius} hatched={hatched} />\n )}\n {...barProps}\n />\n <defs>\n <SeriesGradient id={id} dataKey={seriesKey} config={config} direction=\"vertical\" />\n {hatched && <BarHatchedFill id={id} dataKey={seriesKey} />}\n </defs>\n </>\n )\n}\n\n/** The geometry Recharts hands a custom bar shape, plus the bin behind it. */\ninterface BinGeometry {\n x?: number\n y?: number\n width?: number\n height?: number\n payload?: ResolvedBin\n}\n\ninterface BinShapeProps extends BinGeometry {\n id: string\n seriesKey: string\n radius: number\n hatched: boolean\n}\n\n/** One bucket, spanning its real width on the measured axis. */\nfunction BinShape({\n x = 0,\n y = 0,\n width = 0,\n height = 0,\n payload,\n id,\n seriesKey,\n radius,\n hatched,\n}: BinShapeProps) {\n const plot = usePlotArea()\n const { domain } = useHistogram()\n\n if (!payload) return null\n\n const [low, high] = domain\n const span = high - low\n const edges =\n plot && span > 0\n ? {\n start: plot.x + ((payload.from - low) / span) * plot.width,\n end: plot.x + ((payload.to - low) / span) * plot.width,\n }\n : // Before the chart has measured itself there is no plot to map onto,\n // and Recharts' own band is the only geometry available.\n { start: x, end: x + width }\n\n const drawn = Math.max(1, edges.end - edges.start - BAR_SEPARATION)\n\n return (\n <rect\n x={edges.start + BAR_SEPARATION / 2}\n y={y}\n width={drawn}\n height={Math.max(0, height)}\n rx={radius || undefined}\n fill={hatched ? `url(#${id}-hatched-${seriesKey})` : `url(#${id}-colors-${seriesKey})`}\n />\n )\n}\n\n/** The measured axis. Numeric, because the buckets are a cut of a real scale. */\nfunction XAxis({\n dataKey = 'center',\n type = 'number',\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n label,\n domain,\n tickFormatter,\n ...rest\n}: ChartXAxisProps) {\n const { domain: measured, formatValue } = useHistogram()\n\n return (\n <RechartsXAxis\n dataKey={dataKey}\n type={type}\n // Pinned to the outermost bin edges rather than left to Recharts, which\n // would pad the domain out to round numbers and leave the first and last\n // bars floating off their own edges.\n domain={domain ?? measured}\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n tickFormatter={tickFormatter ?? formatValue}\n {...rest}\n >\n {axisLabel(label, 'x')}\n </RechartsXAxis>\n )\n}\n\n/** The count axis, or the density axis. */\nfunction YAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n width = 'auto',\n label,\n tickFormatter,\n ...rest\n}: ChartYAxisProps) {\n const { mode } = useHistogram()\n\n return (\n <RechartsYAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n width={width}\n tickFormatter={tickFormatter ?? (mode === 'density' ? densityTick : defaultTick)}\n {...rest}\n >\n {axisLabel(label ?? (mode === 'density' ? 'Density' : undefined), 'y')}\n </RechartsYAxis>\n )\n}\n\n/** Rules across the count axis. */\nfunction Grid({\n strokeDasharray = '3 3',\n vertical = false,\n ...rest\n}: ComponentProps<typeof CartesianGrid>) {\n return <CartesianGrid strokeDasharray={strokeDasharray} vertical={vertical} {...rest} />\n}\n\n/**\n * The hover panel, printing the bucket's range rather than its midpoint.\n *\n * The generic tooltip would head the panel with the centre value, which is a\n * number no observation necessarily has. What a reader wants from a histogram\n * bar is the interval it counts and how much of the sample fell in it.\n */\nfunction Tooltip({ variant = 'solid', roundness = 'lg', defaultIndex }: ChartTooltipSlotProps) {\n const { mode, total, formatValue } = useHistogram()\n\n return (\n <ChartTooltip\n cursor={false}\n defaultIndex={defaultIndex}\n content={(props) => {\n const { active, payload } = props as unknown as {\n active?: boolean\n payload?: { payload?: ResolvedBin }[]\n }\n const entry = payload?.[0]?.payload\n if (!active || !entry) return <span className=\"p-4\" />\n\n const share = total > 0 ? entry.count / total : 0\n\n return (\n <div\n className={cn(\n 'grid min-w-40 gap-1.5 border border-(--rule-2) px-2.5 py-1.5 text-xs',\n roundness === 'sm' && 'rounded-(--radius-sm)',\n roundness === 'md' && 'rounded-(--radius)',\n roundness === 'lg' && 'rounded-(--radius-lg)',\n variant === 'frosted'\n ? 'bg-(--chart-surface)/75 backdrop-blur-sm'\n : 'bg-(--chart-surface)',\n )}\n >\n <div className=\"font-medium text-(--ink)\">\n {formatValue(entry.from)} – {formatValue(entry.to)}\n </div>\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Count</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {entry.count.toLocaleString()}\n </span>\n </div>\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Share</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {(share * 100).toFixed(1)}%\n </span>\n </div>\n {mode === 'density' && (\n <div className=\"flex justify-between gap-4 leading-none\">\n <span className=\"text-(--ink-3-aa)\">Density</span>\n <span className=\"font-mono font-medium tabular-nums text-(--ink)\">\n {densityTick(entry.height)}\n </span>\n </div>\n )}\n </div>\n )\n }}\n />\n )\n}\n\n/** The decorative plate behind the plot. */\nfunction Background({ variant }: { variant: ChartBackgroundVariant }) {\n return <ChartBackground variant={variant} />\n}\n\nHistogram.Bars = Bars\nHistogram.XAxis = XAxis\nHistogram.YAxis = YAxis\nHistogram.Grid = Grid\nHistogram.Tooltip = Tooltip\nHistogram.Background = Background\nHistogram.ReferenceLine = ReferenceLine\nHistogram.ReferenceBand = ReferenceBand\nHistogram.Annotation = Annotation\n\nexport default Histogram\n"],"mappings":"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","names":[]}
|
|
@@ -69,8 +69,15 @@ interface LineChartProps<TData extends Record<string, unknown>, TConfig extends
|
|
|
69
69
|
*/
|
|
70
70
|
curveType?: ChartCurveType;
|
|
71
71
|
animationType?: ChartRevealType;
|
|
72
|
-
/** The series lit on first render
|
|
72
|
+
/** The series lit on first render, when the chart keeps its own selection. */
|
|
73
73
|
defaultSelectedDataKey?: string | null;
|
|
74
|
+
/**
|
|
75
|
+
* The selected series, driven from outside.
|
|
76
|
+
*
|
|
77
|
+
* Give this and the chart follows it; leave it undefined and the chart keeps
|
|
78
|
+
* its own, starting from `defaultSelectedDataKey`.
|
|
79
|
+
*/
|
|
80
|
+
selectedDataKey?: string | null;
|
|
74
81
|
/** Fires when the selection changes, and with null when it is cleared. */
|
|
75
82
|
onSelectionChange?: (selectedDataKey: string | null) => void;
|
|
76
83
|
/**
|
|
@@ -119,7 +126,7 @@ interface LineChartProps<TData extends Record<string, unknown>, TConfig extends
|
|
|
119
126
|
* </LineChart.Line>
|
|
120
127
|
* </LineChart>
|
|
121
128
|
*/
|
|
122
|
-
declare function LineChart<TData extends Record<string, unknown>, TConfig extends Record<string, ChartConfig[string]>>({ config, data, title, showTitle, description, children, className, chartProps, curveType, animationType, defaultSelectedDataKey, onSelectionChange, isLoading, loadingPoints, xDataKey, hideDataTable, empty, }: LineChartProps<TData, TConfig>): react.JSX.Element;
|
|
129
|
+
declare function LineChart<TData extends Record<string, unknown>, TConfig extends Record<string, ChartConfig[string]>>({ config, data, title, showTitle, description, children, className, chartProps, curveType, animationType, defaultSelectedDataKey, selectedDataKey: controlledDataKey, onSelectionChange, isLoading, loadingPoints, xDataKey, hideDataTable, empty, }: LineChartProps<TData, TConfig>): react.JSX.Element;
|
|
123
130
|
declare namespace LineChart {
|
|
124
131
|
var Line: ({ dataKey, strokeVariant, strokeWidth, curveType, animationType, connectNulls, isClickable, glowing, buffer, children, lineProps, }: LineProps) => react.JSX.Element | null;
|
|
125
132
|
var Dot: FC<DotProps>;
|
|
@@ -4,11 +4,9 @@ import {
|
|
|
4
4
|
Children,
|
|
5
5
|
createContext,
|
|
6
6
|
isValidElement,
|
|
7
|
-
useCallback,
|
|
8
7
|
useContext,
|
|
9
8
|
useId,
|
|
10
|
-
useMemo
|
|
11
|
-
useState
|
|
9
|
+
useMemo
|
|
12
10
|
} from "react";
|
|
13
11
|
import {
|
|
14
12
|
CartesianGrid,
|
|
@@ -21,7 +19,8 @@ import {
|
|
|
21
19
|
import { useReducedMotion } from "motion/react";
|
|
22
20
|
import { ChartContainer } from "../lib/chart.js";
|
|
23
21
|
import { ChartFigure } from "../lib/figure.js";
|
|
24
|
-
import {
|
|
22
|
+
import { useChartSelection } from "../lib/selection.js";
|
|
23
|
+
import {} from "../lib/empty.js";
|
|
25
24
|
import { axisLabel } from "../lib/axis.js";
|
|
26
25
|
import { defaultTick } from "../lib/format.js";
|
|
27
26
|
import { Annotation, ReferenceBand, ReferenceLine } from "../lib/annotations.js";
|
|
@@ -67,6 +66,7 @@ function LineChart({
|
|
|
67
66
|
curveType = "linear",
|
|
68
67
|
animationType = "forward",
|
|
69
68
|
defaultSelectedDataKey = null,
|
|
69
|
+
selectedDataKey: controlledDataKey,
|
|
70
70
|
onSelectionChange,
|
|
71
71
|
isLoading = false,
|
|
72
72
|
loadingPoints,
|
|
@@ -75,7 +75,6 @@ function LineChart({
|
|
|
75
75
|
empty
|
|
76
76
|
}) {
|
|
77
77
|
const chartId = useId().replace(/:/g, "");
|
|
78
|
-
const [selectedDataKey, setSelectedDataKey] = useState(defaultSelectedDataKey);
|
|
79
78
|
const { rows: loadingData, onShimmerExit } = useLoadingRows(isLoading, loadingPoints);
|
|
80
79
|
const zoom = useChartZoom({ data, xDataKey });
|
|
81
80
|
const { brushSlot, toolbarSlot, sonifySlot, chartChildren } = useMemo(() => {
|
|
@@ -105,12 +104,10 @@ function LineChart({
|
|
|
105
104
|
config,
|
|
106
105
|
xDataKey
|
|
107
106
|
);
|
|
108
|
-
const selectDataKey =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
[onSelectionChange]
|
|
107
|
+
const [selectedDataKey, selectDataKey] = useChartSelection(
|
|
108
|
+
controlledDataKey,
|
|
109
|
+
defaultSelectedDataKey,
|
|
110
|
+
onSelectionChange
|
|
114
111
|
);
|
|
115
112
|
const context = useMemo(
|
|
116
113
|
() => ({ config, rows: displayData, curveType, animationType, isLoading, selectedDataKey, selectDataKey }),
|
|
@@ -124,9 +121,11 @@ function LineChart({
|
|
|
124
121
|
description,
|
|
125
122
|
className,
|
|
126
123
|
table: hideDataTable ? false : { rows: data, rowKey: xDataKey, columns },
|
|
124
|
+
isEmpty,
|
|
125
|
+
empty,
|
|
127
126
|
children: [
|
|
128
127
|
sonifySlot && /* @__PURE__ */ jsx(ChartSonifyButton, { ...sonifySlot, title, series: sonifySeries }),
|
|
129
|
-
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
130
129
|
ChartControls,
|
|
131
130
|
{
|
|
132
131
|
toolbar: showToolbar ? toolbarSlot : null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/charts/LineChart/LineChart.tsx"],"sourcesContent":["'use client'\n\nimport {\n Children,\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useMemo,\n useState,\n type ComponentProps,\n type FC,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport {\n CartesianGrid,\n Curve,\n Line as RechartsLine,\n LineChart as RechartsLineChart,\n XAxis as RechartsXAxis,\n YAxis as RechartsYAxis,\n} from 'recharts'\nimport type { CurveProps } from 'recharts'\nimport { useReducedMotion } from 'motion/react'\nimport { ChartContainer, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { ChartEmpty, type ChartEmptyProps } from '../lib/empty'\nimport { axisLabel } from '../lib/axis'\nimport { defaultTick } from '../lib/format'\nimport { Annotation, ReferenceBand, ReferenceLine } from '../lib/annotations'\nimport { Values, findSlot, resolveValues, type ValuesProps } from '../lib/values'\nimport {\n ChartSonifyButton,\n Sonify,\n useChartSonifySeries,\n type SonifyProps,\n} from '../lib/sonify-control'\n\n/**\n * The axis props, with `label` narrowed to a string.\n *\n * Recharts' own `label` accepts a render function and a config object, neither\n * of which a call site should be reaching for to name an axis — and both of\n * which would let a consumer opt out of the system's own axis type styling\n * without noticing.\n */\nexport type ChartXAxisProps = Omit<ComponentProps<typeof RechartsXAxis>, 'label'> & {\n /** What this axis measures. Say the unit here or in the series label, once. */\n label?: string\n}\n\nexport type ChartYAxisProps = Omit<ComponentProps<typeof RechartsYAxis>, 'label'> & {\n /** What this axis measures. Say the unit here or in the series label, once. */\n label?: string\n}\n\nimport { ChartBackground, type ChartBackgroundVariant } from '../lib/background'\nimport { ChartDot, type ChartDotVariant } from '../lib/dot'\nimport { ChartLegend, ChartLegendContent } from '../lib/legend'\nimport { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport { Brush, ChartBrush, type BrushProps, type ChartBrushRange } from '../lib/brush'\nimport { ChartControls, Toolbar, type ToolbarProps } from '../lib/toolbar'\nimport { useChartZoom } from '../lib/zoom'\nimport { LoadingIndicator, LoadingShimmer, LOADING_KEY, useLoadingRows } from '../lib/loading'\nimport {\n AnimatedDashedStroke,\n GlowFilter,\n RevealMask,\n SeriesGradient,\n type ChartRevealType,\n} from '../lib/paint'\nimport type {\n AreaStrokeVariant,\n ChartCurveType,\n ChartLegendSlotProps,\n ChartTooltipSlotProps,\n} from '../AreaChart/AreaChart'\n\nconst STROKE_WIDTH = 1.6\n\n/** The dash and gap of a buffer segment, in user units. */\nconst BUFFER_DASH = 4\nconst BUFFER_GAP = 3\n\n/**\n * Room around the plot, so the first and last tick labels are not sliced by the\n * container's edge. Recharts' own default is 5px on every side, which is not\n * enough for a label centred on the axis's first point.\n */\nconst CHART_MARGIN = { top: 8, right: 12, bottom: 0, left: 12 }\n\n/** How a line is drawn. Same vocabulary as an area's stroke. */\nexport type LineStrokeVariant = AreaStrokeVariant\n\ninterface LineChartContextValue {\n config: ChartConfig\n /** The rows on screen, so a mark can label its own extremes. */\n rows: Record<string, unknown>[]\n curveType: ChartCurveType\n animationType: ChartRevealType\n isLoading: boolean\n selectedDataKey: string | null\n selectDataKey: (dataKey: string | null) => void\n}\n\nconst LineChartContext = createContext<LineChartContextValue | null>(null)\n\nfunction useLineChart(): LineChartContextValue {\n const context = useContext(LineChartContext)\n if (!context) throw new Error('A line chart part must be rendered inside <LineChart>')\n return context\n}\n\ntype ValidateKeys<TData, TConfig> = {\n [K in keyof TConfig]: K extends keyof TData ? ChartConfig[string] : never\n}\n\nexport interface LineChartProps<\n TData extends Record<string, unknown>,\n TConfig extends Record<string, ChartConfig[string]>,\n> {\n config: TConfig & ValidateKeys<TData, TConfig>\n /** The rows the chart draws. One entry per point, bar or category. */\n data: TData[]\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 /**\n * The composed parts — axes, grid, tooltip, legend, and the marks\n * themselves.\n */\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 RechartsLineChart>\n /**\n * How the line between two points is interpolated. Every mark inherits it\n * unless it says otherwise.\n */\n curveType?: ChartCurveType\n animationType?: ChartRevealType\n /** The series lit on first render. Selection dims every other series. */\n defaultSelectedDataKey?: string | null\n /** Fires when the selection changes, and with null when it is cleared. */\n onSelectionChange?: (selectedDataKey: string | null) => void\n /**\n * Swaps the marks for an animated skeleton, keeping the measured height so\n * the page does not jump when the data lands.\n */\n isLoading?: boolean\n /** How many points the skeleton draws. */\n loadingPoints?: number\n /**\n * The row field on the category axis. Needed by the brush and by the table\n * view.\n */\n xDataKey?: keyof TData & string\n /**\n * Drops the hidden table view. Only correct when the page prints the data\n * itself.\n */\n hideDataTable?: boolean\n /**\n * What the chart shows when it has nothing to draw.\n *\n * Rendered instead of the plot whenever `data` is empty and the chart is not\n * loading — the state a real dashboard reaches within a week, and the one an\n * empty pair of axes is indistinguishable from a failed load. `false` keeps\n * the axes, for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * Several series compared over a continuous axis — the shape for \"which of\n * these is going where\".\n *\n * The difference from `<AreaChart>` is what the reader is asked to do: an area\n * says \"read the magnitude under this\", a line says \"compare these against each\n * other\". Filling four overlapping series makes the second question unanswerable,\n * which is why a line chart has no fill variant to offer.\n *\n * @example\n * <LineChart title=\"Visitors per month\" config={config} data={data}>\n * <LineChart.Grid />\n * <LineChart.XAxis dataKey=\"month\" />\n * <LineChart.Tooltip />\n * <LineChart.Line dataKey=\"desktop\">\n * <LineChart.Dot variant=\"border\" />\n * </LineChart.Line>\n * </LineChart>\n */\nexport function LineChart<\n TData extends Record<string, unknown>,\n TConfig extends Record<string, ChartConfig[string]>,\n>({\n config,\n data,\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n curveType = 'linear',\n animationType = 'forward',\n defaultSelectedDataKey = null,\n onSelectionChange,\n isLoading = false,\n loadingPoints,\n xDataKey,\n hideDataTable = false,\n empty,\n}: LineChartProps<TData, TConfig>) {\n const chartId = useId().replace(/:/g, '')\n const [selectedDataKey, setSelectedDataKey] = useState<string | null>(defaultSelectedDataKey)\n const { rows: loadingData, onShimmerExit } = useLoadingRows(isLoading, loadingPoints)\n // One window, two views of it: the brush strip below the plot and the\n // toolbar above it both read and write this. See `useChartZoom` for why they\n // are not two separate windows.\n const zoom = useChartZoom({ data, xDataKey })\n\n // The brush, the toolbar and the sonify control are declared as children but\n // never rendered into the Recharts tree — they live in the figure, outside\n // the SVG.\n const { brushSlot, toolbarSlot, sonifySlot, chartChildren } = useMemo(() => {\n const parts = Children.toArray(children)\n const element = parts.find((child) => isValidElement(child) && child.type === Brush)\n const props = (isValidElement(element) ? element.props : {}) as BrushProps\n return {\n brushSlot: { present: isValidElement(element), ...props },\n toolbarSlot: findSlot<ToolbarProps>(parts, Toolbar),\n sonifySlot: findSlot<SonifyProps>(parts, Sonify),\n chartChildren: parts.filter(\n (child) =>\n !(\n isValidElement(child) &&\n (child.type === Brush || child.type === Toolbar || child.type === Sonify)\n ),\n ),\n }\n }, [children])\n\n const columns = useMemo(\n () => Object.entries(config).map(([key, series]) => ({ key, label: series.label })),\n [config],\n )\n\n const showBrush = brushSlot.present && !isLoading\n const showToolbar = toolbarSlot !== null && !isLoading\n // `empty === false` keeps the axes, for a chart whose emptiness is the\n // reading — a monitoring panel that should show a flat, silent range rather\n // than a message.\n const isEmpty = !isLoading && empty !== false && data.length === 0\n const displayData =\n isLoading ? loadingData : showBrush || showToolbar ? zoom.visibleData : data\n\n // The rows on screen, so a brushed range sounds like what it looks like. A\n // skeleton or an empty chart yields no finite value, which is what leaves the\n // control disabled rather than playing silence.\n const sonifySeries = useChartSonifySeries(\n sonifySlot,\n displayData as Record<string, unknown>[],\n config,\n xDataKey,\n )\n\n const selectDataKey = useCallback(\n (next: string | null) => {\n setSelectedDataKey(next)\n onSelectionChange?.(next)\n },\n [onSelectionChange],\n )\n\n const context = useMemo<LineChartContextValue>(\n () => ({ config, rows: displayData as Record<string, unknown>[], curveType, animationType, isLoading, selectedDataKey, selectDataKey }),\n [animationType, config, curveType, displayData, isLoading, selectDataKey, selectedDataKey],\n )\n\n return (\n <LineChartContext.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: xDataKey, columns }\n }\n >\n {sonifySlot && (\n <ChartSonifyButton {...sonifySlot} title={title} series={sonifySeries} />\n )}\n {isEmpty ? (\n <ChartEmpty {...(empty || {})} />\n ) : (\n <ChartControls\n toolbar={showToolbar ? toolbarSlot : null}\n zoom={zoom}\n title={title}\n rows={data}\n columns={columns}\n rowKey={xDataKey}\n >\n <ChartContainer\n config={config}\n footer={\n showBrush && (\n <ChartBrush\n data={data}\n config={config}\n xDataKey={xDataKey}\n variant=\"line\"\n curveType={curveType}\n height={brushSlot.height}\n formatLabel={brushSlot.formatLabel}\n className=\"mt-1\"\n {...zoom.brushProps}\n onChange={(range: ChartBrushRange) => {\n zoom.brushProps.onChange(range)\n brushSlot.onChange?.(range)\n }}\n />\n )\n }\n >\n <RechartsLineChart\n id={chartId}\n accessibilityLayer\n margin={CHART_MARGIN}\n data={displayData}\n {...chartProps}\n >\n {chartChildren}\n {isLoading && (\n <LoadingLine chartId={chartId} curveType={curveType} onShimmerExit={onShimmerExit} />\n )}\n </RechartsLineChart>\n </ChartContainer>\n </ChartControls>\n )}\n <LoadingIndicator isLoading={isLoading} />\n </ChartFigure>\n </LineChartContext.Provider>\n )\n}\n\nexport interface LineProps {\n dataKey: string\n strokeVariant?: LineStrokeVariant\n strokeWidth?: number\n curveType?: ChartCurveType\n animationType?: ChartRevealType\n connectNulls?: boolean\n isClickable?: boolean\n /** A halo around the line — for the one series that is the point of the figure. */\n glowing?: boolean\n /**\n * Draws the LAST segment dashed.\n *\n * The idiom for a projection or a period still open: the line reaches the\n * same point either way, but the last leg is visibly a different kind of fact.\n */\n buffer?: boolean\n children?: ReactNode\n lineProps?: ComponentProps<typeof RechartsLine>\n}\n\n/** One line series, with its own gradient, glow and reveal scoped to its id. */\nfunction Line({\n dataKey,\n strokeVariant = 'solid',\n strokeWidth = STROKE_WIDTH,\n curveType,\n animationType,\n connectNulls = false,\n isClickable = false,\n glowing = false,\n buffer = false,\n children,\n lineProps,\n}: LineProps) {\n const {\n config,\n curveType: defaultCurve,\n animationType: defaultAnimation,\n isLoading,\n rows,\n selectedDataKey,\n selectDataKey,\n } = useLineChart()\n const id = useId().replace(/:/g, '')\n const reduceMotion = useReducedMotion()\n\n if (isLoading) return null\n\n const resolvedCurve = curveType ?? defaultCurve\n const reveal: ChartRevealType = reduceMotion ? 'none' : (animationType ?? defaultAnimation)\n const maskId = reveal === 'none' ? undefined : `${id}-reveal-mask`\n\n const isSelected = selectedDataKey === dataKey\n const hasSelection = selectedDataKey !== null\n const opacity = hasSelection && !isSelected ? { stroke: 0.3, dot: 0.3 } : { stroke: 1, dot: 1 }\n\n const { dot, activeDot } = resolveDots(children, id, dataKey, opacity.dot, maskId)\n const labels = resolveValues(\n findSlot<ValuesProps>(children, Values),\n rows.map((row) => Number(row[dataKey])).filter(Number.isFinite),\n )\n\n const animateDash = strokeVariant === 'animated-dashed' && !hasSelection && !reduceMotion\n const isDashed = strokeVariant !== 'solid'\n\n return (\n <>\n <g>\n {isClickable && (\n // A 15px transparent line under the visible one. A 1.6px stroke is\n // not a pointer target, and WCAG 2.5.8 asks for 24; this is the\n // cheapest way to give a hairline a real hit area.\n <RechartsLine\n type={resolvedCurve}\n dataKey={dataKey}\n connectNulls={connectNulls}\n stroke=\"transparent\"\n strokeWidth={15}\n dot={false}\n activeDot={false}\n isAnimationActive={false}\n legendType=\"none\"\n tooltipType=\"none\"\n style={{ cursor: 'pointer' }}\n onClick={() => selectDataKey(isSelected ? null : dataKey)}\n />\n )}\n <RechartsLine\n type={resolvedCurve}\n dataKey={dataKey}\n connectNulls={connectNulls}\n strokeOpacity={opacity.stroke}\n stroke={`url(#${id}-colors-${dataKey})`}\n filter={glowing ? `url(#${id}-glow-${dataKey})` : undefined}\n dot={dot}\n activeDot={activeDot}\n strokeWidth={strokeWidth}\n // A buffer line writes its own dasharray from the measured path, so\n // the static one has to stay out of its way.\n strokeDasharray={buffer ? undefined : isDashed ? '5 5' : undefined}\n shape={buffer ? bufferShape : undefined}\n isAnimationActive={false}\n style={{\n ...(maskId ? { mask: `url(#${maskId})` } : {}),\n ...(isClickable ? { cursor: 'pointer' } : {}),\n }}\n onClick={() => {\n if (!isClickable) return\n selectDataKey(isSelected ? null : dataKey)\n }}\n {...lineProps}\n >\n {animateDash && <AnimatedDashedStroke dash={5} />}\n {labels}\n </RechartsLine>\n </g>\n <defs>\n {reveal !== 'none' && <RevealMask id={id} type={reveal} />}\n <SeriesGradient id={id} dataKey={dataKey} config={config} />\n {glowing && <GlowFilter id={id} dataKey={dataKey} spread={10} intensity={2} />}\n </defs>\n </>\n )\n}\n\nexport interface DotProps {\n variant?: ChartDotVariant\n}\n\n/** The resting point marker for the line it is composed inside. A slot. */\nconst Dot: FC<DotProps> = () => null\n\n/** The marker under the pointer. */\nconst ActiveDot: FC<DotProps> = () => null\n\nfunction resolveDots(\n children: ReactNode,\n id: string,\n dataKey: string,\n dotOpacity: number,\n maskId: string | undefined,\n) {\n let dot: ComponentProps<typeof RechartsLine>['dot'] = false\n let activeDot: ComponentProps<typeof RechartsLine>['activeDot'] = false\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return\n const { variant } = (child as ReactElement<DotProps>).props\n\n if (child.type === Dot) {\n dot = (\n <ChartDot\n variant={variant}\n dataKey={dataKey}\n chartId={id}\n fillOpacity={dotOpacity}\n maskId={maskId}\n />\n )\n }\n if (child.type === ActiveDot) {\n activeDot = (\n <ChartDot variant={variant} dataKey={dataKey} chartId={id} fillOpacity={dotOpacity} />\n )\n }\n })\n\n return { dot, activeDot }\n}\n\ntype CurvePoint = NonNullable<NonNullable<CurveProps['points']>[number]>\ntype DrawablePoint = CurvePoint & { x: number; y: number }\n\nfunction isDrawable(point: CurvePoint): point is DrawablePoint {\n return typeof point.x === 'number' && typeof point.y === 'number'\n}\n\n/**\n * Binary-searches a path for the length at which it reaches `targetX`.\n *\n * `getPointAtLength` is the browser's own curve solver, so this is exact for\n * every curve type rather than only for straight segments — which is what an\n * arithmetic split on the point list would give.\n */\nfunction lengthAtX(path: SVGPathElement, totalLength: number, targetX: number): number {\n let low = 0\n let high = totalLength\n // Half a pixel is well under what a dash boundary can show.\n while (high - low > 0.5) {\n const mid = (low + high) / 2\n if (path.getPointAtLength(mid).x < targetX) low = mid\n else high = mid\n }\n return (low + high) / 2\n}\n\n/**\n * A line whose last segment is dashed and whose body is not.\n *\n * `stroke-dasharray` has no way to say \"solid until here\": the pattern repeats\n * from the path's start. So the solid run is written as a single leading dash of\n * exactly the measured length, followed by enough dash/gap pairs to cover the\n * rest — which needs the path's real length, which needs the DOM.\n *\n * The ref callback runs during commit, before paint, so there is no frame where\n * the line is drawn undashed.\n */\nfunction bufferShape(props: CurveProps) {\n const { points, ...rest } = props\n if (!points || points.length < 2) return <Curve {...props} />\n\n const drawable = points.filter(isDrawable)\n if (drawable.length < 2) return <Curve {...props} />\n\n const splitX = drawable[drawable.length - 2]!.x\n\n return (\n <g\n ref={(group) => {\n const path = group?.querySelector('path')\n if (!path) return\n\n const total = path.getTotalLength()\n const solid = lengthAtX(path, total, splitX)\n const remaining = total - solid\n const repeats = Math.ceil(remaining / (BUFFER_DASH + BUFFER_GAP)) + 1\n const dashes = Array.from({ length: repeats }, () => `${BUFFER_DASH} ${BUFFER_GAP}`).join(' ')\n\n path.setAttribute('stroke-dasharray', `${solid} 0 ${dashes}`)\n }}\n >\n <Curve {...rest} points={drawable} />\n </g>\n )\n}\n\n/** The category axis. */\nfunction XAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n label,\n ...rest\n}: ChartXAxisProps) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return (\n <RechartsXAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n {...rest}\n >\n {axisLabel(label, 'x')}\n </RechartsXAxis>\n )\n}\n\n/** The value axis. */\nfunction YAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n width = 'auto',\n tickFormatter = defaultTick,\n label,\n ...rest\n}: ChartYAxisProps) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return (\n <RechartsYAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n width={width}\n tickFormatter={tickFormatter}\n {...rest}\n >\n {axisLabel(label, 'y')}\n </RechartsYAxis>\n )\n}\n\n/** Horizontal dashed rules. */\nfunction Grid({\n vertical = false,\n strokeDasharray = '3 3',\n ...rest\n}: ComponentProps<typeof CartesianGrid>) {\n return <CartesianGrid vertical={vertical} strokeDasharray={strokeDasharray} {...rest} />\n}\n\n/** The hover panel, with a crosshair along the axis. */\nfunction Tooltip({ variant, roundness, defaultIndex, cursor = true }: ChartTooltipSlotProps) {\n const { isLoading, selectedDataKey } = useLineChart()\n if (isLoading) return null\n\n return (\n <ChartTooltip\n defaultIndex={defaultIndex}\n cursor={cursor ? { strokeDasharray: '3 3', strokeWidth: 1 } : false}\n content={\n <ChartTooltipContent selected={selectedDataKey} roundness={roundness} variant={variant} />\n }\n />\n )\n}\n\n/** The key. Required above one series. */\nfunction Legend({\n variant,\n align = 'right',\n verticalAlign = 'top',\n isClickable = false,\n}: ChartLegendSlotProps) {\n const { selectedDataKey, selectDataKey } = useLineChart()\n\n return (\n <ChartLegend\n verticalAlign={verticalAlign}\n align={align}\n content={\n <ChartLegendContent\n selected={selectedDataKey}\n onSelectChange={selectDataKey}\n isClickable={isClickable}\n variant={variant}\n />\n }\n />\n )\n}\n\n/** The decorative plate behind the plot. */\nfunction Background({ variant }: { variant: ChartBackgroundVariant }) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return <ChartBackground variant={variant} />\n}\n\n/** The skeleton drawn in place of the real lines. */\nfunction LoadingLine({\n chartId,\n curveType,\n onShimmerExit,\n}: {\n chartId: string\n curveType: ChartCurveType\n onShimmerExit: () => void\n}) {\n return (\n <>\n <RechartsLine\n type={curveType}\n dataKey={LOADING_KEY}\n stroke=\"currentColor\"\n strokeOpacity={0.5}\n strokeWidth={STROKE_WIDTH}\n isAnimationActive={false}\n legendType=\"none\"\n tooltipType=\"none\"\n activeDot={false}\n dot={false}\n className=\"text-(--ink)\"\n style={{ mask: `url(#${chartId}-loading-mask)` }}\n />\n <defs>\n <LoadingShimmer id={chartId} onShimmerExit={onShimmerExit} />\n </defs>\n </>\n )\n}\n\nLineChart.Line = Line\nLineChart.Dot = Dot\nLineChart.ActiveDot = ActiveDot\nLineChart.XAxis = XAxis\nLineChart.YAxis = YAxis\nLineChart.Grid = Grid\nLineChart.Tooltip = Tooltip\nLineChart.Legend = Legend\nLineChart.Background = Background\nLineChart.ReferenceLine = ReferenceLine\nLineChart.ReferenceBand = ReferenceBand\nLineChart.Annotation = Annotation\nLineChart.Values = Values\nLineChart.Brush = Brush\nLineChart.Toolbar = Toolbar\nLineChart.Sonify = Sonify\n\nexport default LineChart\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/LineChart/LineChart.tsx"],"sourcesContent":["'use client'\n\nimport {\n Children,\n createContext,\n isValidElement,\n useContext,\n useId,\n useMemo,\n type ComponentProps,\n type FC,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport {\n CartesianGrid,\n Curve,\n Line as RechartsLine,\n LineChart as RechartsLineChart,\n XAxis as RechartsXAxis,\n YAxis as RechartsYAxis,\n} from 'recharts'\nimport type { CurveProps } from 'recharts'\nimport { useReducedMotion } from 'motion/react'\nimport { ChartContainer, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { useChartSelection } from '../lib/selection'\nimport { type ChartEmptyProps } from '../lib/empty'\nimport { axisLabel } from '../lib/axis'\nimport { defaultTick } from '../lib/format'\nimport { Annotation, ReferenceBand, ReferenceLine } from '../lib/annotations'\nimport { Values, findSlot, resolveValues, type ValuesProps } from '../lib/values'\nimport {\n ChartSonifyButton,\n Sonify,\n useChartSonifySeries,\n type SonifyProps,\n} from '../lib/sonify-control'\n\n/**\n * The axis props, with `label` narrowed to a string.\n *\n * Recharts' own `label` accepts a render function and a config object, neither\n * of which a call site should be reaching for to name an axis — and both of\n * which would let a consumer opt out of the system's own axis type styling\n * without noticing.\n */\nexport type ChartXAxisProps = Omit<ComponentProps<typeof RechartsXAxis>, 'label'> & {\n /** What this axis measures. Say the unit here or in the series label, once. */\n label?: string\n}\n\nexport type ChartYAxisProps = Omit<ComponentProps<typeof RechartsYAxis>, 'label'> & {\n /** What this axis measures. Say the unit here or in the series label, once. */\n label?: string\n}\n\nimport { ChartBackground, type ChartBackgroundVariant } from '../lib/background'\nimport { ChartDot, type ChartDotVariant } from '../lib/dot'\nimport { ChartLegend, ChartLegendContent } from '../lib/legend'\nimport { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport { Brush, ChartBrush, type BrushProps, type ChartBrushRange } from '../lib/brush'\nimport { ChartControls, Toolbar, type ToolbarProps } from '../lib/toolbar'\nimport { useChartZoom } from '../lib/zoom'\nimport { LoadingIndicator, LoadingShimmer, LOADING_KEY, useLoadingRows } from '../lib/loading'\nimport {\n AnimatedDashedStroke,\n GlowFilter,\n RevealMask,\n SeriesGradient,\n type ChartRevealType,\n} from '../lib/paint'\nimport type {\n AreaStrokeVariant,\n ChartCurveType,\n ChartLegendSlotProps,\n ChartTooltipSlotProps,\n} from '../AreaChart/AreaChart'\n\nconst STROKE_WIDTH = 1.6\n\n/** The dash and gap of a buffer segment, in user units. */\nconst BUFFER_DASH = 4\nconst BUFFER_GAP = 3\n\n/**\n * Room around the plot, so the first and last tick labels are not sliced by the\n * container's edge. Recharts' own default is 5px on every side, which is not\n * enough for a label centred on the axis's first point.\n */\nconst CHART_MARGIN = { top: 8, right: 12, bottom: 0, left: 12 }\n\n/** How a line is drawn. Same vocabulary as an area's stroke. */\nexport type LineStrokeVariant = AreaStrokeVariant\n\ninterface LineChartContextValue {\n config: ChartConfig\n /** The rows on screen, so a mark can label its own extremes. */\n rows: Record<string, unknown>[]\n curveType: ChartCurveType\n animationType: ChartRevealType\n isLoading: boolean\n selectedDataKey: string | null\n selectDataKey: (dataKey: string | null) => void\n}\n\nconst LineChartContext = createContext<LineChartContextValue | null>(null)\n\nfunction useLineChart(): LineChartContextValue {\n const context = useContext(LineChartContext)\n if (!context) throw new Error('A line chart part must be rendered inside <LineChart>')\n return context\n}\n\ntype ValidateKeys<TData, TConfig> = {\n [K in keyof TConfig]: K extends keyof TData ? ChartConfig[string] : never\n}\n\nexport interface LineChartProps<\n TData extends Record<string, unknown>,\n TConfig extends Record<string, ChartConfig[string]>,\n> {\n config: TConfig & ValidateKeys<TData, TConfig>\n /** The rows the chart draws. One entry per point, bar or category. */\n data: TData[]\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 /**\n * The composed parts — axes, grid, tooltip, legend, and the marks\n * themselves.\n */\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 RechartsLineChart>\n /**\n * How the line between two points is interpolated. Every mark inherits it\n * unless it says otherwise.\n */\n curveType?: ChartCurveType\n animationType?: ChartRevealType\n /** The series lit on first render, when the chart keeps its own selection. */\n defaultSelectedDataKey?: string | null\n /**\n * The selected series, driven from outside.\n *\n * Give this and the chart follows it; leave it undefined and the chart keeps\n * its own, starting from `defaultSelectedDataKey`.\n */\n selectedDataKey?: string | null\n /** Fires when the selection changes, and with null when it is cleared. */\n onSelectionChange?: (selectedDataKey: string | null) => void\n /**\n * Swaps the marks for an animated skeleton, keeping the measured height so\n * the page does not jump when the data lands.\n */\n isLoading?: boolean\n /** How many points the skeleton draws. */\n loadingPoints?: number\n /**\n * The row field on the category axis. Needed by the brush and by the table\n * view.\n */\n xDataKey?: keyof TData & string\n /**\n * Drops the hidden table view. Only correct when the page prints the data\n * itself.\n */\n hideDataTable?: boolean\n /**\n * What the chart shows when it has nothing to draw.\n *\n * Rendered instead of the plot whenever `data` is empty and the chart is not\n * loading — the state a real dashboard reaches within a week, and the one an\n * empty pair of axes is indistinguishable from a failed load. `false` keeps\n * the axes, for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * Several series compared over a continuous axis — the shape for \"which of\n * these is going where\".\n *\n * The difference from `<AreaChart>` is what the reader is asked to do: an area\n * says \"read the magnitude under this\", a line says \"compare these against each\n * other\". Filling four overlapping series makes the second question unanswerable,\n * which is why a line chart has no fill variant to offer.\n *\n * @example\n * <LineChart title=\"Visitors per month\" config={config} data={data}>\n * <LineChart.Grid />\n * <LineChart.XAxis dataKey=\"month\" />\n * <LineChart.Tooltip />\n * <LineChart.Line dataKey=\"desktop\">\n * <LineChart.Dot variant=\"border\" />\n * </LineChart.Line>\n * </LineChart>\n */\nexport function LineChart<\n TData extends Record<string, unknown>,\n TConfig extends Record<string, ChartConfig[string]>,\n>({\n config,\n data,\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n curveType = 'linear',\n animationType = 'forward',\n defaultSelectedDataKey = null,\n selectedDataKey: controlledDataKey,\n onSelectionChange,\n isLoading = false,\n loadingPoints,\n xDataKey,\n hideDataTable = false,\n empty,\n}: LineChartProps<TData, TConfig>) {\n const chartId = useId().replace(/:/g, '')\n const { rows: loadingData, onShimmerExit } = useLoadingRows(isLoading, loadingPoints)\n // One window, two views of it: the brush strip below the plot and the\n // toolbar above it both read and write this. See `useChartZoom` for why they\n // are not two separate windows.\n const zoom = useChartZoom({ data, xDataKey })\n\n // The brush, the toolbar and the sonify control are declared as children but\n // never rendered into the Recharts tree — they live in the figure, outside\n // the SVG.\n const { brushSlot, toolbarSlot, sonifySlot, chartChildren } = useMemo(() => {\n const parts = Children.toArray(children)\n const element = parts.find((child) => isValidElement(child) && child.type === Brush)\n const props = (isValidElement(element) ? element.props : {}) as BrushProps\n return {\n brushSlot: { present: isValidElement(element), ...props },\n toolbarSlot: findSlot<ToolbarProps>(parts, Toolbar),\n sonifySlot: findSlot<SonifyProps>(parts, Sonify),\n chartChildren: parts.filter(\n (child) =>\n !(\n isValidElement(child) &&\n (child.type === Brush || child.type === Toolbar || child.type === Sonify)\n ),\n ),\n }\n }, [children])\n\n const columns = useMemo(\n () => Object.entries(config).map(([key, series]) => ({ key, label: series.label })),\n [config],\n )\n\n const showBrush = brushSlot.present && !isLoading\n const showToolbar = toolbarSlot !== null && !isLoading\n // `empty === false` keeps the axes, for a chart whose emptiness is the\n // reading — a monitoring panel that should show a flat, silent range rather\n // than a message.\n const isEmpty = !isLoading && empty !== false && data.length === 0\n const displayData =\n isLoading ? loadingData : showBrush || showToolbar ? zoom.visibleData : data\n\n // The rows on screen, so a brushed range sounds like what it looks like. A\n // skeleton or an empty chart yields no finite value, which is what leaves the\n // control disabled rather than playing silence.\n const sonifySeries = useChartSonifySeries(\n sonifySlot,\n displayData as Record<string, unknown>[],\n config,\n xDataKey,\n )\n\n const [selectedDataKey, selectDataKey] = useChartSelection(\n controlledDataKey,\n defaultSelectedDataKey,\n onSelectionChange,\n )\n\n const context = useMemo<LineChartContextValue>(\n () => ({ config, rows: displayData as Record<string, unknown>[], curveType, animationType, isLoading, selectedDataKey, selectDataKey }),\n [animationType, config, curveType, displayData, isLoading, selectDataKey, selectedDataKey],\n )\n\n return (\n <LineChartContext.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: xDataKey, columns }\n }\n isEmpty={isEmpty}\n empty={empty}\n >\n {sonifySlot && (\n <ChartSonifyButton {...sonifySlot} title={title} series={sonifySeries} />\n )}\n <ChartControls\n toolbar={showToolbar ? toolbarSlot : null}\n zoom={zoom}\n title={title}\n rows={data}\n columns={columns}\n rowKey={xDataKey}\n >\n <ChartContainer\n config={config}\n footer={\n showBrush && (\n <ChartBrush\n data={data}\n config={config}\n xDataKey={xDataKey}\n variant=\"line\"\n curveType={curveType}\n height={brushSlot.height}\n formatLabel={brushSlot.formatLabel}\n className=\"mt-1\"\n {...zoom.brushProps}\n onChange={(range: ChartBrushRange) => {\n zoom.brushProps.onChange(range)\n brushSlot.onChange?.(range)\n }}\n />\n )\n }\n >\n <RechartsLineChart\n id={chartId}\n accessibilityLayer\n margin={CHART_MARGIN}\n data={displayData}\n {...chartProps}\n >\n {chartChildren}\n {isLoading && (\n <LoadingLine chartId={chartId} curveType={curveType} onShimmerExit={onShimmerExit} />\n )}\n </RechartsLineChart>\n </ChartContainer>\n </ChartControls>\n <LoadingIndicator isLoading={isLoading} />\n </ChartFigure>\n </LineChartContext.Provider>\n )\n}\n\nexport interface LineProps {\n dataKey: string\n strokeVariant?: LineStrokeVariant\n strokeWidth?: number\n curveType?: ChartCurveType\n animationType?: ChartRevealType\n connectNulls?: boolean\n isClickable?: boolean\n /** A halo around the line — for the one series that is the point of the figure. */\n glowing?: boolean\n /**\n * Draws the LAST segment dashed.\n *\n * The idiom for a projection or a period still open: the line reaches the\n * same point either way, but the last leg is visibly a different kind of fact.\n */\n buffer?: boolean\n children?: ReactNode\n lineProps?: ComponentProps<typeof RechartsLine>\n}\n\n/** One line series, with its own gradient, glow and reveal scoped to its id. */\nfunction Line({\n dataKey,\n strokeVariant = 'solid',\n strokeWidth = STROKE_WIDTH,\n curveType,\n animationType,\n connectNulls = false,\n isClickable = false,\n glowing = false,\n buffer = false,\n children,\n lineProps,\n}: LineProps) {\n const {\n config,\n curveType: defaultCurve,\n animationType: defaultAnimation,\n isLoading,\n rows,\n selectedDataKey,\n selectDataKey,\n } = useLineChart()\n const id = useId().replace(/:/g, '')\n const reduceMotion = useReducedMotion()\n\n if (isLoading) return null\n\n const resolvedCurve = curveType ?? defaultCurve\n const reveal: ChartRevealType = reduceMotion ? 'none' : (animationType ?? defaultAnimation)\n const maskId = reveal === 'none' ? undefined : `${id}-reveal-mask`\n\n const isSelected = selectedDataKey === dataKey\n const hasSelection = selectedDataKey !== null\n const opacity = hasSelection && !isSelected ? { stroke: 0.3, dot: 0.3 } : { stroke: 1, dot: 1 }\n\n const { dot, activeDot } = resolveDots(children, id, dataKey, opacity.dot, maskId)\n const labels = resolveValues(\n findSlot<ValuesProps>(children, Values),\n rows.map((row) => Number(row[dataKey])).filter(Number.isFinite),\n )\n\n const animateDash = strokeVariant === 'animated-dashed' && !hasSelection && !reduceMotion\n const isDashed = strokeVariant !== 'solid'\n\n return (\n <>\n <g>\n {isClickable && (\n // A 15px transparent line under the visible one. A 1.6px stroke is\n // not a pointer target, and WCAG 2.5.8 asks for 24; this is the\n // cheapest way to give a hairline a real hit area.\n <RechartsLine\n type={resolvedCurve}\n dataKey={dataKey}\n connectNulls={connectNulls}\n stroke=\"transparent\"\n strokeWidth={15}\n dot={false}\n activeDot={false}\n isAnimationActive={false}\n legendType=\"none\"\n tooltipType=\"none\"\n style={{ cursor: 'pointer' }}\n onClick={() => selectDataKey(isSelected ? null : dataKey)}\n />\n )}\n <RechartsLine\n type={resolvedCurve}\n dataKey={dataKey}\n connectNulls={connectNulls}\n strokeOpacity={opacity.stroke}\n stroke={`url(#${id}-colors-${dataKey})`}\n filter={glowing ? `url(#${id}-glow-${dataKey})` : undefined}\n dot={dot}\n activeDot={activeDot}\n strokeWidth={strokeWidth}\n // A buffer line writes its own dasharray from the measured path, so\n // the static one has to stay out of its way.\n strokeDasharray={buffer ? undefined : isDashed ? '5 5' : undefined}\n shape={buffer ? bufferShape : undefined}\n isAnimationActive={false}\n style={{\n ...(maskId ? { mask: `url(#${maskId})` } : {}),\n ...(isClickable ? { cursor: 'pointer' } : {}),\n }}\n onClick={() => {\n if (!isClickable) return\n selectDataKey(isSelected ? null : dataKey)\n }}\n {...lineProps}\n >\n {animateDash && <AnimatedDashedStroke dash={5} />}\n {labels}\n </RechartsLine>\n </g>\n <defs>\n {reveal !== 'none' && <RevealMask id={id} type={reveal} />}\n <SeriesGradient id={id} dataKey={dataKey} config={config} />\n {glowing && <GlowFilter id={id} dataKey={dataKey} spread={10} intensity={2} />}\n </defs>\n </>\n )\n}\n\nexport interface DotProps {\n variant?: ChartDotVariant\n}\n\n/** The resting point marker for the line it is composed inside. A slot. */\nconst Dot: FC<DotProps> = () => null\n\n/** The marker under the pointer. */\nconst ActiveDot: FC<DotProps> = () => null\n\nfunction resolveDots(\n children: ReactNode,\n id: string,\n dataKey: string,\n dotOpacity: number,\n maskId: string | undefined,\n) {\n let dot: ComponentProps<typeof RechartsLine>['dot'] = false\n let activeDot: ComponentProps<typeof RechartsLine>['activeDot'] = false\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return\n const { variant } = (child as ReactElement<DotProps>).props\n\n if (child.type === Dot) {\n dot = (\n <ChartDot\n variant={variant}\n dataKey={dataKey}\n chartId={id}\n fillOpacity={dotOpacity}\n maskId={maskId}\n />\n )\n }\n if (child.type === ActiveDot) {\n activeDot = (\n <ChartDot variant={variant} dataKey={dataKey} chartId={id} fillOpacity={dotOpacity} />\n )\n }\n })\n\n return { dot, activeDot }\n}\n\ntype CurvePoint = NonNullable<NonNullable<CurveProps['points']>[number]>\ntype DrawablePoint = CurvePoint & { x: number; y: number }\n\nfunction isDrawable(point: CurvePoint): point is DrawablePoint {\n return typeof point.x === 'number' && typeof point.y === 'number'\n}\n\n/**\n * Binary-searches a path for the length at which it reaches `targetX`.\n *\n * `getPointAtLength` is the browser's own curve solver, so this is exact for\n * every curve type rather than only for straight segments — which is what an\n * arithmetic split on the point list would give.\n */\nfunction lengthAtX(path: SVGPathElement, totalLength: number, targetX: number): number {\n let low = 0\n let high = totalLength\n // Half a pixel is well under what a dash boundary can show.\n while (high - low > 0.5) {\n const mid = (low + high) / 2\n if (path.getPointAtLength(mid).x < targetX) low = mid\n else high = mid\n }\n return (low + high) / 2\n}\n\n/**\n * A line whose last segment is dashed and whose body is not.\n *\n * `stroke-dasharray` has no way to say \"solid until here\": the pattern repeats\n * from the path's start. So the solid run is written as a single leading dash of\n * exactly the measured length, followed by enough dash/gap pairs to cover the\n * rest — which needs the path's real length, which needs the DOM.\n *\n * The ref callback runs during commit, before paint, so there is no frame where\n * the line is drawn undashed.\n */\nfunction bufferShape(props: CurveProps) {\n const { points, ...rest } = props\n if (!points || points.length < 2) return <Curve {...props} />\n\n const drawable = points.filter(isDrawable)\n if (drawable.length < 2) return <Curve {...props} />\n\n const splitX = drawable[drawable.length - 2]!.x\n\n return (\n <g\n ref={(group) => {\n const path = group?.querySelector('path')\n if (!path) return\n\n const total = path.getTotalLength()\n const solid = lengthAtX(path, total, splitX)\n const remaining = total - solid\n const repeats = Math.ceil(remaining / (BUFFER_DASH + BUFFER_GAP)) + 1\n const dashes = Array.from({ length: repeats }, () => `${BUFFER_DASH} ${BUFFER_GAP}`).join(' ')\n\n path.setAttribute('stroke-dasharray', `${solid} 0 ${dashes}`)\n }}\n >\n <Curve {...rest} points={drawable} />\n </g>\n )\n}\n\n/** The category axis. */\nfunction XAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n label,\n ...rest\n}: ChartXAxisProps) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return (\n <RechartsXAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n {...rest}\n >\n {axisLabel(label, 'x')}\n </RechartsXAxis>\n )\n}\n\n/** The value axis. */\nfunction YAxis({\n tickLine = false,\n axisLine = false,\n tickMargin = 8,\n minTickGap = 8,\n width = 'auto',\n tickFormatter = defaultTick,\n label,\n ...rest\n}: ChartYAxisProps) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return (\n <RechartsYAxis\n tickLine={tickLine}\n axisLine={axisLine}\n tickMargin={tickMargin}\n minTickGap={minTickGap}\n width={width}\n tickFormatter={tickFormatter}\n {...rest}\n >\n {axisLabel(label, 'y')}\n </RechartsYAxis>\n )\n}\n\n/** Horizontal dashed rules. */\nfunction Grid({\n vertical = false,\n strokeDasharray = '3 3',\n ...rest\n}: ComponentProps<typeof CartesianGrid>) {\n return <CartesianGrid vertical={vertical} strokeDasharray={strokeDasharray} {...rest} />\n}\n\n/** The hover panel, with a crosshair along the axis. */\nfunction Tooltip({ variant, roundness, defaultIndex, cursor = true }: ChartTooltipSlotProps) {\n const { isLoading, selectedDataKey } = useLineChart()\n if (isLoading) return null\n\n return (\n <ChartTooltip\n defaultIndex={defaultIndex}\n cursor={cursor ? { strokeDasharray: '3 3', strokeWidth: 1 } : false}\n content={\n <ChartTooltipContent selected={selectedDataKey} roundness={roundness} variant={variant} />\n }\n />\n )\n}\n\n/** The key. Required above one series. */\nfunction Legend({\n variant,\n align = 'right',\n verticalAlign = 'top',\n isClickable = false,\n}: ChartLegendSlotProps) {\n const { selectedDataKey, selectDataKey } = useLineChart()\n\n return (\n <ChartLegend\n verticalAlign={verticalAlign}\n align={align}\n content={\n <ChartLegendContent\n selected={selectedDataKey}\n onSelectChange={selectDataKey}\n isClickable={isClickable}\n variant={variant}\n />\n }\n />\n )\n}\n\n/** The decorative plate behind the plot. */\nfunction Background({ variant }: { variant: ChartBackgroundVariant }) {\n const { isLoading } = useLineChart()\n if (isLoading) return null\n return <ChartBackground variant={variant} />\n}\n\n/** The skeleton drawn in place of the real lines. */\nfunction LoadingLine({\n chartId,\n curveType,\n onShimmerExit,\n}: {\n chartId: string\n curveType: ChartCurveType\n onShimmerExit: () => void\n}) {\n return (\n <>\n <RechartsLine\n type={curveType}\n dataKey={LOADING_KEY}\n stroke=\"currentColor\"\n strokeOpacity={0.5}\n strokeWidth={STROKE_WIDTH}\n isAnimationActive={false}\n legendType=\"none\"\n tooltipType=\"none\"\n activeDot={false}\n dot={false}\n className=\"text-(--ink)\"\n style={{ mask: `url(#${chartId}-loading-mask)` }}\n />\n <defs>\n <LoadingShimmer id={chartId} onShimmerExit={onShimmerExit} />\n </defs>\n </>\n )\n}\n\nLineChart.Line = Line\nLineChart.Dot = Dot\nLineChart.ActiveDot = ActiveDot\nLineChart.XAxis = XAxis\nLineChart.YAxis = YAxis\nLineChart.Grid = Grid\nLineChart.Tooltip = Tooltip\nLineChart.Legend = Legend\nLineChart.Background = Background\nLineChart.ReferenceLine = ReferenceLine\nLineChart.ReferenceBand = ReferenceBand\nLineChart.Annotation = Annotation\nLineChart.Values = Values\nLineChart.Brush = Brush\nLineChart.Toolbar = Toolbar\nLineChart.Sonify = Sonify\n\nexport default LineChart\n"],"mappings":";AAqTU,SAuHN,UAvHM,KAgCA,YAhCA;AAnTV;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS;AAAA,OACJ;AAEP,SAAS,wBAAwB;AACjC,SAAS,sBAAwC;AACjD,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,eAAqC;AACrC,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,YAAY,eAAe,qBAAqB;AACzD,SAAS,QAAQ,UAAU,qBAAuC;AAClE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAoBP,SAAS,uBAAoD;AAC7D,SAAS,gBAAsC;AAC/C,SAAS,aAAa,0BAA0B;AAChD,SAAS,cAAc,2BAA2B;AAClD,SAAS,OAAO,kBAAyD;AACzE,SAAS,eAAe,eAAkC;AAC1D,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB,gBAAgB,aAAa,sBAAsB;AAC9E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAQP,MAAM,eAAe;AAGrB,MAAM,cAAc;AACpB,MAAM,aAAa;AAOnB,MAAM,eAAe,EAAE,KAAK,GAAG,OAAO,IAAI,QAAQ,GAAG,MAAM,GAAG;AAgB9D,MAAM,mBAAmB,cAA4C,IAAI;AAEzE,SAAS,eAAsC;AAC7C,QAAM,UAAU,WAAW,gBAAgB;AAC3C,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,uDAAuD;AACrF,SAAO;AACT;AA+FO,SAAS,UAGd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AACF,GAAmC;AACjC,QAAM,UAAU,MAAM,EAAE,QAAQ,MAAM,EAAE;AACxC,QAAM,EAAE,MAAM,aAAa,cAAc,IAAI,eAAe,WAAW,aAAa;AAIpF,QAAM,OAAO,aAAa,EAAE,MAAM,SAAS,CAAC;AAK5C,QAAM,EAAE,WAAW,aAAa,YAAY,cAAc,IAAI,QAAQ,MAAM;AAC1E,UAAM,QAAQ,SAAS,QAAQ,QAAQ;AACvC,UAAM,UAAU,MAAM,KAAK,CAAC,UAAU,eAAe,KAAK,KAAK,MAAM,SAAS,KAAK;AACnF,UAAM,QAAS,eAAe,OAAO,IAAI,QAAQ,QAAQ,CAAC;AAC1D,WAAO;AAAA,MACL,WAAW,EAAE,SAAS,eAAe,OAAO,GAAG,GAAG,MAAM;AAAA,MACxD,aAAa,SAAuB,OAAO,OAAO;AAAA,MAClD,YAAY,SAAsB,OAAO,MAAM;AAAA,MAC/C,eAAe,MAAM;AAAA,QACnB,CAAC,UACC,EACE,eAAe,KAAK,MACnB,MAAM,SAAS,SAAS,MAAM,SAAS,WAAW,MAAM,SAAS;AAAA,MAExE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,UAAU;AAAA,IACd,MAAM,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,OAAO,EAAE,KAAK,OAAO,OAAO,MAAM,EAAE;AAAA,IAClF,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,YAAY,UAAU,WAAW,CAAC;AACxC,QAAM,cAAc,gBAAgB,QAAQ,CAAC;AAI7C,QAAM,UAAU,CAAC,aAAa,UAAU,SAAS,KAAK,WAAW;AACjE,QAAM,cACJ,YAAY,cAAc,aAAa,cAAc,KAAK,cAAc;AAK1E,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,CAAC,iBAAiB,aAAa,IAAI;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,UAAU;AAAA,IACd,OAAO,EAAE,QAAQ,MAAM,aAA0C,WAAW,eAAe,WAAW,iBAAiB,cAAc;AAAA,IACrI,CAAC,eAAe,QAAQ,WAAW,aAAa,WAAW,eAAe,eAAe;AAAA,EAC3F;AAEA,SACE,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,SAChC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OACE,gBACI,QACA,EAAE,MAAM,MAAM,QAAQ,UAAU,QAAQ;AAAA,MAE9C;AAAA,MACA;AAAA,MAEC;AAAA,sBACC,oBAAC,qBAAmB,GAAG,YAAY,OAAc,QAAQ,cAAc;AAAA,QAEzE;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,cAAc,cAAc;AAAA,YACrC;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA,QAAQ;AAAA,YAEV;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA,QACE,aACE;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA,SAAQ;AAAA,oBACR;AAAA,oBACA,QAAQ,UAAU;AAAA,oBAClB,aAAa,UAAU;AAAA,oBACvB,WAAU;AAAA,oBACT,GAAG,KAAK;AAAA,oBACT,UAAU,CAAC,UAA2B;AACpC,2BAAK,WAAW,SAAS,KAAK;AAC9B,gCAAU,WAAW,KAAK;AAAA,oBAC5B;AAAA;AAAA,gBACF;AAAA,gBAIJ;AAAA,kBAAC;AAAA;AAAA,oBACC,IAAI;AAAA,oBACJ,oBAAkB;AAAA,oBAClB,QAAQ;AAAA,oBACR,MAAM;AAAA,oBACL,GAAG;AAAA,oBAEH;AAAA;AAAA,sBACA,aACC,oBAAC,eAAY,SAAkB,WAAsB,eAA8B;AAAA;AAAA;AAAA,gBAEvF;AAAA;AAAA,YACF;AAAA;AAAA,QACA;AAAA,QACA,oBAAC,oBAAiB,WAAsB;AAAA;AAAA;AAAA,EAC1C,GACF;AAEJ;AAwBA,SAAS,KAAK;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd,UAAU;AAAA,EACV,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAAc;AACZ,QAAM;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,IACX,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AACjB,QAAM,KAAK,MAAM,EAAE,QAAQ,MAAM,EAAE;AACnC,QAAM,eAAe,iBAAiB;AAEtC,MAAI,UAAW,QAAO;AAEtB,QAAM,gBAAgB,aAAa;AACnC,QAAM,SAA0B,eAAe,SAAU,iBAAiB;AAC1E,QAAM,SAAS,WAAW,SAAS,SAAY,GAAG,EAAE;AAEpD,QAAM,aAAa,oBAAoB;AACvC,QAAM,eAAe,oBAAoB;AACzC,QAAM,UAAU,gBAAgB,CAAC,aAAa,EAAE,QAAQ,KAAK,KAAK,IAAI,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE;AAE9F,QAAM,EAAE,KAAK,UAAU,IAAI,YAAY,UAAU,IAAI,SAAS,QAAQ,KAAK,MAAM;AACjF,QAAM,SAAS;AAAA,IACb,SAAsB,UAAU,MAAM;AAAA,IACtC,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,OAAO,QAAQ;AAAA,EAChE;AAEA,QAAM,cAAc,kBAAkB,qBAAqB,CAAC,gBAAgB,CAAC;AAC7E,QAAM,WAAW,kBAAkB;AAEnC,SACE,iCACE;AAAA,yBAAC,OACE;AAAA;AAAA;AAAA;AAAA,MAIC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,QAAO;AAAA,UACP,aAAa;AAAA,UACb,KAAK;AAAA,UACL,WAAW;AAAA,UACX,mBAAmB;AAAA,UACnB,YAAW;AAAA,UACX,aAAY;AAAA,UACZ,OAAO,EAAE,QAAQ,UAAU;AAAA,UAC3B,SAAS,MAAM,cAAc,aAAa,OAAO,OAAO;AAAA;AAAA,MAC1D;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,eAAe,QAAQ;AAAA,UACvB,QAAQ,QAAQ,EAAE,WAAW,OAAO;AAAA,UACpC,QAAQ,UAAU,QAAQ,EAAE,SAAS,OAAO,MAAM;AAAA,UAClD;AAAA,UACA;AAAA,UACA;AAAA,UAGA,iBAAiB,SAAS,SAAY,WAAW,QAAQ;AAAA,UACzD,OAAO,SAAS,cAAc;AAAA,UAC9B,mBAAmB;AAAA,UACnB,OAAO;AAAA,YACL,GAAI,SAAS,EAAE,MAAM,QAAQ,MAAM,IAAI,IAAI,CAAC;AAAA,YAC5C,GAAI,cAAc,EAAE,QAAQ,UAAU,IAAI,CAAC;AAAA,UAC7C;AAAA,UACA,SAAS,MAAM;AACb,gBAAI,CAAC,YAAa;AAClB,0BAAc,aAAa,OAAO,OAAO;AAAA,UAC3C;AAAA,UACC,GAAG;AAAA,UAEH;AAAA,2BAAe,oBAAC,wBAAqB,MAAM,GAAG;AAAA,YAC9C;AAAA;AAAA;AAAA,MACH;AAAA,OACF;AAAA,IACA,qBAAC,UACE;AAAA,iBAAW,UAAU,oBAAC,cAAW,IAAQ,MAAM,QAAQ;AAAA,MACxD,oBAAC,kBAAe,IAAQ,SAAkB,QAAgB;AAAA,MACzD,WAAW,oBAAC,cAAW,IAAQ,SAAkB,QAAQ,IAAI,WAAW,GAAG;AAAA,OAC9E;AAAA,KACF;AAEJ;AAOA,MAAM,MAAoB,MAAM;AAGhC,MAAM,YAA0B,MAAM;AAEtC,SAAS,YACP,UACA,IACA,SACA,YACA,QACA;AACA,MAAI,MAAkD;AACtD,MAAI,YAA8D;AAElE,WAAS,QAAQ,UAAU,CAAC,UAAU;AACpC,QAAI,CAAC,eAAe,KAAK,EAAG;AAC5B,UAAM,EAAE,QAAQ,IAAK,MAAiC;AAEtD,QAAI,MAAM,SAAS,KAAK;AACtB,YACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,SAAS;AAAA,UACT,aAAa;AAAA,UACb;AAAA;AAAA,MACF;AAAA,IAEJ;AACA,QAAI,MAAM,SAAS,WAAW;AAC5B,kBACE,oBAAC,YAAS,SAAkB,SAAkB,SAAS,IAAI,aAAa,YAAY;AAAA,IAExF;AAAA,EACF,CAAC;AAED,SAAO,EAAE,KAAK,UAAU;AAC1B;AAKA,SAAS,WAAW,OAA2C;AAC7D,SAAO,OAAO,MAAM,MAAM,YAAY,OAAO,MAAM,MAAM;AAC3D;AASA,SAAS,UAAU,MAAsB,aAAqB,SAAyB;AACrF,MAAI,MAAM;AACV,MAAI,OAAO;AAEX,SAAO,OAAO,MAAM,KAAK;AACvB,UAAM,OAAO,MAAM,QAAQ;AAC3B,QAAI,KAAK,iBAAiB,GAAG,EAAE,IAAI,QAAS,OAAM;AAAA,QAC7C,QAAO;AAAA,EACd;AACA,UAAQ,MAAM,QAAQ;AACxB;AAaA,SAAS,YAAY,OAAmB;AACtC,QAAM,EAAE,QAAQ,GAAG,KAAK,IAAI;AAC5B,MAAI,CAAC,UAAU,OAAO,SAAS,EAAG,QAAO,oBAAC,SAAO,GAAG,OAAO;AAE3D,QAAM,WAAW,OAAO,OAAO,UAAU;AACzC,MAAI,SAAS,SAAS,EAAG,QAAO,oBAAC,SAAO,GAAG,OAAO;AAElD,QAAM,SAAS,SAAS,SAAS,SAAS,CAAC,EAAG;AAE9C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,UAAU;AACd,cAAM,OAAO,OAAO,cAAc,MAAM;AACxC,YAAI,CAAC,KAAM;AAEX,cAAM,QAAQ,KAAK,eAAe;AAClC,cAAM,QAAQ,UAAU,MAAM,OAAO,MAAM;AAC3C,cAAM,YAAY,QAAQ;AAC1B,cAAM,UAAU,KAAK,KAAK,aAAa,cAAc,WAAW,IAAI;AACpE,cAAM,SAAS,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,MAAM,GAAG,WAAW,IAAI,UAAU,EAAE,EAAE,KAAK,GAAG;AAE7F,aAAK,aAAa,oBAAoB,GAAG,KAAK,MAAM,MAAM,EAAE;AAAA,MAC9D;AAAA,MAEA,8BAAC,SAAO,GAAG,MAAM,QAAQ,UAAU;AAAA;AAAA,EACrC;AAEJ;AAGA,SAAS,MAAM;AAAA,EACb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,EAAE,UAAU,IAAI,aAAa;AACnC,MAAI,UAAW,QAAO;AACtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEH,oBAAU,OAAO,GAAG;AAAA;AAAA,EACvB;AAEJ;AAGA,SAAS,MAAM;AAAA,EACb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,EAAE,UAAU,IAAI,aAAa;AACnC,MAAI,UAAW,QAAO;AACtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEH,oBAAU,OAAO,GAAG;AAAA;AAAA,EACvB;AAEJ;AAGA,SAAS,KAAK;AAAA,EACZ,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,GAAG;AACL,GAAyC;AACvC,SAAO,oBAAC,iBAAc,UAAoB,iBAAmC,GAAG,MAAM;AACxF;AAGA,SAAS,QAAQ,EAAE,SAAS,WAAW,cAAc,SAAS,KAAK,GAA0B;AAC3F,QAAM,EAAE,WAAW,gBAAgB,IAAI,aAAa;AACpD,MAAI,UAAW,QAAO;AAEtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,SAAS,EAAE,iBAAiB,OAAO,aAAa,EAAE,IAAI;AAAA,MAC9D,SACE,oBAAC,uBAAoB,UAAU,iBAAiB,WAAsB,SAAkB;AAAA;AAAA,EAE5F;AAEJ;AAGA,SAAS,OAAO;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,cAAc;AAChB,GAAyB;AACvB,QAAM,EAAE,iBAAiB,cAAc,IAAI,aAAa;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SACE;AAAA,QAAC;AAAA;AAAA,UACC,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EAEJ;AAEJ;AAGA,SAAS,WAAW,EAAE,QAAQ,GAAwC;AACpE,QAAM,EAAE,UAAU,IAAI,aAAa;AACnC,MAAI,UAAW,QAAO;AACtB,SAAO,oBAAC,mBAAgB,SAAkB;AAC5C;AAGA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAO;AAAA,QACP,eAAe;AAAA,QACf,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,YAAW;AAAA,QACX,aAAY;AAAA,QACZ,WAAW;AAAA,QACX,KAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO,EAAE,MAAM,QAAQ,OAAO,iBAAiB;AAAA;AAAA,IACjD;AAAA,IACA,oBAAC,UACC,8BAAC,kBAAe,IAAI,SAAS,eAA8B,GAC7D;AAAA,KACF;AAEJ;AAEA,UAAU,OAAO;AACjB,UAAU,MAAM;AAChB,UAAU,YAAY;AACtB,UAAU,QAAQ;AAClB,UAAU,QAAQ;AAClB,UAAU,OAAO;AACjB,UAAU,UAAU;AACpB,UAAU,SAAS;AACnB,UAAU,aAAa;AACvB,UAAU,gBAAgB;AAC1B,UAAU,gBAAgB;AAC1B,UAAU,aAAa;AACvB,UAAU,SAAS;AACnB,UAAU,QAAQ;AAClB,UAAU,UAAU;AACpB,UAAU,SAAS;AAEnB,IAAO,oBAAQ;","names":[]}
|
|
@@ -2,9 +2,9 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode, ComponentProps, FC } from 'react';
|
|
3
3
|
import { PieChart as PieChart$1, Pie, LabelList } from 'recharts';
|
|
4
4
|
import { ChartConfig } from '../lib/chart.js';
|
|
5
|
+
import { ChartEmptyProps } from '../lib/empty.js';
|
|
5
6
|
import { ChartBackgroundVariant } from '../lib/background.js';
|
|
6
7
|
import { ChartTooltipSlotProps, ChartLegendSlotProps } from '../AreaChart/AreaChart.js';
|
|
7
|
-
import '../lib/empty.js';
|
|
8
8
|
import '../lib/values.js';
|
|
9
9
|
import '../lib/sonify-control.js';
|
|
10
10
|
import '../lib/sonify.js';
|
|
@@ -55,8 +55,15 @@ interface PieChartProps<TData extends Record<string, unknown>> {
|
|
|
55
55
|
className?: string;
|
|
56
56
|
/** Escape hatch onto the raw Recharts chart element. */
|
|
57
57
|
chartProps?: ComponentProps<typeof PieChart$1>;
|
|
58
|
-
/** The sector lit on first render. */
|
|
58
|
+
/** The sector lit on first render, when the chart keeps its own selection. */
|
|
59
59
|
defaultSelectedSector?: string | null;
|
|
60
|
+
/**
|
|
61
|
+
* The selected sector, driven from outside.
|
|
62
|
+
*
|
|
63
|
+
* Give this and the chart follows it; leave it undefined and the chart keeps
|
|
64
|
+
* its own, starting from `defaultSelectedSector`.
|
|
65
|
+
*/
|
|
66
|
+
selectedSector?: string | null;
|
|
60
67
|
/** Fires when the selection changes, and with null when it is cleared. */
|
|
61
68
|
onSelectionChange?: (selection: {
|
|
62
69
|
name: string;
|
|
@@ -72,6 +79,11 @@ interface PieChartProps<TData extends Record<string, unknown>> {
|
|
|
72
79
|
* itself.
|
|
73
80
|
*/
|
|
74
81
|
hideDataTable?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* What the chart shows when it has nothing to draw. `false` keeps the empty
|
|
84
|
+
* plot, for a chart whose emptiness is itself the reading.
|
|
85
|
+
*/
|
|
86
|
+
empty?: ChartEmptyProps | false;
|
|
75
87
|
}
|
|
76
88
|
/**
|
|
77
89
|
* Parts of one whole.
|
|
@@ -88,7 +100,7 @@ interface PieChartProps<TData extends Record<string, unknown>> {
|
|
|
88
100
|
* <PieChart.Legend />
|
|
89
101
|
* </PieChart>
|
|
90
102
|
*/
|
|
91
|
-
declare function PieChart<TData extends Record<string, unknown>>({ config, data, dataKey, nameKey, title, showTitle, description, children, className, chartProps, defaultSelectedSector, onSelectionChange, isLoading, hideDataTable, }: PieChartProps<TData>): react.JSX.Element;
|
|
103
|
+
declare function PieChart<TData extends Record<string, unknown>>({ config, data, dataKey, nameKey, title, showTitle, description, children, className, chartProps, defaultSelectedSector, selectedSector: controlledSector, onSelectionChange, isLoading, hideDataTable, empty, }: PieChartProps<TData>): react.JSX.Element;
|
|
92
104
|
declare namespace PieChart {
|
|
93
105
|
var Pie: ({ variant, innerRadius, outerRadius, cornerRadius, paddingAngle, startAngle, endAngle, isClickable, glowingSectors, children, pieProps, }: PieProps) => react.JSX.Element;
|
|
94
106
|
var Label: FC<PieLabelProps>;
|