@misoto22/folio 0.0.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/bin/folio-design.mjs +277 -0
- package/bin/migrate-legacy.mjs +81 -0
- package/dist/agent/Accordion.md +65 -0
- package/dist/agent/Actions.md +49 -0
- package/dist/agent/Alert.md +65 -0
- package/dist/agent/AppShell.md +69 -0
- package/dist/agent/ArchitectureFigure.md +72 -0
- package/dist/agent/AreaChart.md +94 -0
- package/dist/agent/Article.md +65 -0
- package/dist/agent/AspectRatio.md +58 -0
- package/dist/agent/Avatar.md +53 -0
- package/dist/agent/Badge.md +62 -0
- package/dist/agent/BarChart.md +93 -0
- package/dist/agent/BarList.md +67 -0
- package/dist/agent/BigNumber.md +70 -0
- package/dist/agent/BoxPlot.md +82 -0
- package/dist/agent/Breadcrumb.md +55 -0
- package/dist/agent/BulletChart.md +71 -0
- package/dist/agent/Button.md +81 -0
- package/dist/agent/Calendar.md +77 -0
- package/dist/agent/CalendarHeatmap.md +75 -0
- package/dist/agent/Card.md +72 -0
- package/dist/agent/Checkbox.md +57 -0
- package/dist/agent/Code.md +51 -0
- package/dist/agent/CodeBlock.md +77 -0
- package/dist/agent/Collapsible.md +68 -0
- package/dist/agent/Collection.md +169 -0
- package/dist/agent/ColorPicker.md +76 -0
- package/dist/agent/Combobox.md +77 -0
- package/dist/agent/Command.md +122 -0
- package/dist/agent/ComposedChart.md +82 -0
- package/dist/agent/Contact.md +90 -0
- package/dist/agent/Content.md +70 -0
- package/dist/agent/ContextMenu.md +93 -0
- package/dist/agent/Conversation.md +247 -0
- package/dist/agent/DataflowFigure.md +49 -0
- package/dist/agent/DatePicker.md +104 -0
- package/dist/agent/DescriptionList.md +69 -0
- package/dist/agent/Diagram.md +71 -0
- package/dist/agent/DiagramCanvas.md +71 -0
- package/dist/agent/DiagramExportMenu.md +65 -0
- package/dist/agent/DiagramInspector.md +73 -0
- package/dist/agent/DiagramLegend.md +56 -0
- package/dist/agent/DiagramMinimap.md +69 -0
- package/dist/agent/DiagramToolbar.md +70 -0
- package/dist/agent/Dialog.md +76 -0
- package/dist/agent/DropdownMenu.md +110 -0
- package/dist/agent/EmptyState.md +63 -0
- package/dist/agent/ErrorState.md +67 -0
- package/dist/agent/Evidence.md +165 -0
- package/dist/agent/Facet.md +107 -0
- package/dist/agent/Field.md +79 -0
- package/dist/agent/FigureBand.md +49 -0
- package/dist/agent/FloatingIconButton.md +61 -0
- package/dist/agent/FunnelChart.md +75 -0
- package/dist/agent/Heading.md +65 -0
- package/dist/agent/Heatmap.md +78 -0
- package/dist/agent/Histogram.md +88 -0
- package/dist/agent/Input.md +52 -0
- package/dist/agent/Kbd.md +48 -0
- package/dist/agent/LifecycleFigure.md +50 -0
- package/dist/agent/LineChart.md +85 -0
- package/dist/agent/LinkArrow.md +49 -0
- package/dist/agent/Markdown.md +69 -0
- package/dist/agent/Media.md +261 -0
- package/dist/agent/Metric.md +70 -0
- package/dist/agent/Metrics.md +114 -0
- package/dist/agent/Music.md +86 -0
- package/dist/agent/NativeSelect.md +62 -0
- package/dist/agent/NavItem.md +56 -0
- package/dist/agent/NumberField.md +73 -0
- package/dist/agent/PageHeader.md +69 -0
- package/dist/agent/Pagination.md +70 -0
- package/dist/agent/PieChart.md +80 -0
- package/dist/agent/Popover.md +80 -0
- package/dist/agent/Portfolio.md +93 -0
- package/dist/agent/PortfolioIndex.md +34 -0
- package/dist/agent/Progress.md +58 -0
- package/dist/agent/RadarChart.md +79 -0
- package/dist/agent/RadialChart.md +81 -0
- package/dist/agent/RadioGroup.md +66 -0
- package/dist/agent/Reading.md +233 -0
- package/dist/agent/Recovery.md +72 -0
- package/dist/agent/SankeyChart.md +85 -0
- package/dist/agent/ScatterChart.md +80 -0
- package/dist/agent/ScrollArea.md +62 -0
- package/dist/agent/SearchPalette.md +51 -0
- package/dist/agent/SearchableMenu.md +69 -0
- package/dist/agent/Select.md +102 -0
- package/dist/agent/Separator.md +60 -0
- package/dist/agent/SequenceFigure.md +51 -0
- package/dist/agent/Sheet.md +82 -0
- package/dist/agent/Sidebar.md +194 -0
- package/dist/agent/SiteNavigation.md +62 -0
- package/dist/agent/SiteShell.md +67 -0
- package/dist/agent/Skeleton.md +96 -0
- package/dist/agent/Slider.md +67 -0
- package/dist/agent/Sparkline.md +68 -0
- package/dist/agent/Spinner.md +62 -0
- package/dist/agent/StatusDot.md +56 -0
- package/dist/agent/StatusPill.md +55 -0
- package/dist/agent/Steps.md +68 -0
- package/dist/agent/Switch.md +50 -0
- package/dist/agent/Table.md +111 -0
- package/dist/agent/Tabs.md +71 -0
- package/dist/agent/Tag.md +67 -0
- package/dist/agent/Text.md +66 -0
- package/dist/agent/Textarea.md +46 -0
- package/dist/agent/Timeline.md +114 -0
- package/dist/agent/Timestamp.md +65 -0
- package/dist/agent/Toast.md +51 -0
- package/dist/agent/ToggleGroup.md +67 -0
- package/dist/agent/Toolbar.md +72 -0
- package/dist/agent/Tooltip.md +74 -0
- package/dist/agent/TreemapChart.md +76 -0
- package/dist/agent/WaterfallChart.md +86 -0
- package/dist/agent/Workbench.md +142 -0
- package/dist/agent/WorkflowFigure.md +51 -0
- package/dist/agent/catalog.json +8055 -0
- package/dist/agent/index.md +185 -0
- package/dist/article.css +407 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +198 -0
- package/dist/charts/AreaChart/AreaChart.js +479 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +190 -0
- package/dist/charts/BarChart/BarChart.js +599 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +65 -0
- package/dist/charts/BarList/BarList.js +79 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +72 -0
- package/dist/charts/BigNumber/BigNumber.js +51 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +497 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +197 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.d.ts +106 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js +103 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +178 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +106 -0
- package/dist/charts/FunnelChart/FunnelChart.js +137 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +101 -0
- package/dist/charts/Heatmap/Heatmap.js +125 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +188 -0
- package/dist/charts/Histogram/Histogram.js +382 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +174 -0
- package/dist/charts/LineChart/LineChart.js +485 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +140 -0
- package/dist/charts/PieChart/PieChart.js +317 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +135 -0
- package/dist/charts/RadarChart/RadarChart.js +303 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +142 -0
- package/dist/charts/RadialChart/RadialChart.js +279 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +149 -0
- package/dist/charts/SankeyChart/SankeyChart.js +509 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +149 -0
- package/dist/charts/ScatterChart/ScatterChart.js +275 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +95 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +98 -0
- package/dist/charts/TreemapChart/TreemapChart.js +127 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +321 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +43 -0
- package/dist/charts/index.js +130 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +149 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +24 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +94 -0
- package/dist/charts/lib/export.js +62 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +81 -0
- package/dist/charts/lib/figure.js +62 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +144 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +43 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +58 -0
- package/dist/components/AppShell/AppShell.js +126 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Article/Article.d.ts +58 -0
- package/dist/components/Article/Article.js +34 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +38 -0
- package/dist/components/Avatar/Avatar.js +44 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +37 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +46 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +95 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +54 -0
- package/dist/components/Calendar/Calendar.js +369 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +55 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +26 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +145 -0
- package/dist/components/CodeBlock/CodeBlock.js +114 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +45 -0
- package/dist/components/Collapsible/Collapsible.js +60 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +77 -0
- package/dist/components/Combobox/Combobox.js +170 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +125 -0
- package/dist/components/Command/Command.js +204 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +63 -0
- package/dist/components/ContextMenu/ContextMenu.js +109 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +130 -0
- package/dist/components/DatePicker/DatePicker.js +257 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +86 -0
- package/dist/components/Diagram/Diagram.js +211 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +63 -0
- package/dist/components/Dialog/Dialog.js +90 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +87 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +120 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +55 -0
- package/dist/components/EmptyState/EmptyState.js +32 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +55 -0
- package/dist/components/ErrorState/ErrorState.js +41 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +111 -0
- package/dist/components/Field/Field.js +95 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +31 -0
- package/dist/components/FigureBand/FigureBand.js +51 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +34 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +27 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/Metric/Metric.d.ts +61 -0
- package/dist/components/Metric/Metric.js +51 -0
- package/dist/components/Metric/Metric.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +33 -0
- package/dist/components/NativeSelect/NativeSelect.js +44 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +92 -0
- package/dist/components/PageHeader/PageHeader.js +37 -0
- package/dist/components/PageHeader/PageHeader.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +67 -0
- package/dist/components/Pagination/Pagination.js +112 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +43 -0
- package/dist/components/Progress/Progress.js +57 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +49 -0
- package/dist/components/RadioGroup/RadioGroup.js +53 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +46 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +68 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +101 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +87 -0
- package/dist/components/Select/Select.js +130 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +48 -0
- package/dist/components/Separator/Separator.js +43 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +43 -0
- package/dist/components/Sheet/Sheet.js +79 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.d.ts +357 -0
- package/dist/components/Sidebar/Sidebar.js +447 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +74 -0
- package/dist/components/Slider/Slider.js +143 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +58 -0
- package/dist/components/Spinner/Spinner.js +49 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +30 -0
- package/dist/components/StatusPill/StatusPill.js +37 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +25 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +137 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +37 -0
- package/dist/components/Tabs/Tabs.js +205 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +87 -0
- package/dist/components/Tag/Tag.js +62 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +32 -0
- package/dist/components/Toast/Toast.js +64 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +46 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +88 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
- package/dist/diagrams/index.d.ts +17 -0
- package/dist/diagrams/index.js +29 -0
- package/dist/diagrams/index.js.map +1 -0
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +138 -0
- package/dist/diagrams/lib/frame.js +131 -0
- package/dist/diagrams/lib/frame.js.map +1 -0
- package/dist/diagrams/lib/geometry.d.ts +114 -0
- package/dist/diagrams/lib/geometry.js +113 -0
- package/dist/diagrams/lib/geometry.js.map +1 -0
- package/dist/diagrams/lib/legend.d.ts +32 -0
- package/dist/diagrams/lib/legend.js +84 -0
- package/dist/diagrams/lib/legend.js.map +1 -0
- package/dist/diagrams/lib/marks.d.ts +207 -0
- package/dist/diagrams/lib/marks.js +480 -0
- package/dist/diagrams/lib/marks.js.map +1 -0
- package/dist/diagrams/lib/route.d.ts +106 -0
- package/dist/diagrams/lib/route.js +201 -0
- package/dist/diagrams/lib/route.js.map +1 -0
- package/dist/diagrams/lib/wires.d.ts +59 -0
- package/dist/diagrams/lib/wires.js +94 -0
- package/dist/diagrams/lib/wires.js.map +1 -0
- package/dist/diagrams/spec.d.ts +405 -0
- package/dist/diagrams/spec.js +1 -0
- package/dist/diagrams/spec.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +300 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/control.d.ts +32 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +48 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/slot-content.d.ts +8 -0
- package/dist/lib/slot-content.js +17 -0
- package/dist/lib/slot-content.js.map +1 -0
- package/dist/lib/step-rail.d.ts +45 -0
- package/dist/lib/step-rail.js +47 -0
- package/dist/lib/step-rail.js.map +1 -0
- package/dist/lib/svg-export.d.ts +138 -0
- package/dist/lib/svg-export.js +198 -0
- package/dist/lib/svg-export.js.map +1 -0
- package/dist/lib/useClipboardCopy.d.ts +30 -0
- package/dist/lib/useClipboardCopy.js +37 -0
- package/dist/lib/useClipboardCopy.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +49 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +200 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +607 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +666 -0
- package/dist/tokens.d.ts +205 -0
- package/dist/tokens.js +1056 -0
- package/dist/tokens.json +1055 -0
- package/dist/website/Actions/Actions.d.ts +34 -0
- package/dist/website/Actions/Actions.js +29 -0
- package/dist/website/Actions/Actions.js.map +1 -0
- package/dist/website/Collection/Collection.d.ts +128 -0
- package/dist/website/Collection/Collection.js +162 -0
- package/dist/website/Collection/Collection.js.map +1 -0
- package/dist/website/Contact/Contact.d.ts +87 -0
- package/dist/website/Contact/Contact.js +94 -0
- package/dist/website/Contact/Contact.js.map +1 -0
- package/dist/website/Content/CodePanel.d.ts +27 -0
- package/dist/website/Content/CodePanel.js +30 -0
- package/dist/website/Content/CodePanel.js.map +1 -0
- package/dist/website/Content/Content.d.ts +29 -0
- package/dist/website/Content/Content.js +38 -0
- package/dist/website/Content/Content.js.map +1 -0
- package/dist/website/Conversation/Conversation.d.ts +193 -0
- package/dist/website/Conversation/Conversation.js +252 -0
- package/dist/website/Conversation/Conversation.js.map +1 -0
- package/dist/website/Evidence/Evidence.d.ts +116 -0
- package/dist/website/Evidence/Evidence.js +142 -0
- package/dist/website/Evidence/Evidence.js.map +1 -0
- package/dist/website/Media/Media.d.ts +173 -0
- package/dist/website/Media/Media.js +225 -0
- package/dist/website/Media/Media.js.map +1 -0
- package/dist/website/Media/MediaLightbox.d.ts +18 -0
- package/dist/website/Media/MediaLightbox.js +38 -0
- package/dist/website/Media/MediaLightbox.js.map +1 -0
- package/dist/website/Metrics/Metrics.d.ts +74 -0
- package/dist/website/Metrics/Metrics.js +96 -0
- package/dist/website/Metrics/Metrics.js.map +1 -0
- package/dist/website/Music/Music.d.ts +60 -0
- package/dist/website/Music/Music.js +80 -0
- package/dist/website/Music/Music.js.map +1 -0
- package/dist/website/Portfolio/FrameLayout.d.ts +9 -0
- package/dist/website/Portfolio/FrameLayout.js +42 -0
- package/dist/website/Portfolio/FrameLayout.js.map +1 -0
- package/dist/website/Portfolio/Portfolio.d.ts +49 -0
- package/dist/website/Portfolio/Portfolio.js +66 -0
- package/dist/website/Portfolio/Portfolio.js.map +1 -0
- package/dist/website/Portfolio/QuestionCard.d.ts +22 -0
- package/dist/website/Portfolio/QuestionCard.js +33 -0
- package/dist/website/Portfolio/QuestionCard.js.map +1 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.d.ts +21 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js +31 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js.map +1 -0
- package/dist/website/Reading/Reading.d.ts +203 -0
- package/dist/website/Reading/Reading.js +357 -0
- package/dist/website/Reading/Reading.js.map +1 -0
- package/dist/website/Recovery/Recovery.d.ts +39 -0
- package/dist/website/Recovery/Recovery.js +96 -0
- package/dist/website/Recovery/Recovery.js.map +1 -0
- package/dist/website/SearchPalette/SearchPalette.d.ts +59 -0
- package/dist/website/SearchPalette/SearchPalette.js +120 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -0
- package/dist/website/SiteNavigation/SiteNavigation.d.ts +46 -0
- package/dist/website/SiteNavigation/SiteNavigation.js +101 -0
- package/dist/website/SiteNavigation/SiteNavigation.js.map +1 -0
- package/dist/website/SiteShell/SiteShell.d.ts +45 -0
- package/dist/website/SiteShell/SiteShell.js +46 -0
- package/dist/website/SiteShell/SiteShell.js.map +1 -0
- package/dist/website/Timeline/Timeline.d.ts +80 -0
- package/dist/website/Timeline/Timeline.js +99 -0
- package/dist/website/Timeline/Timeline.js.map +1 -0
- package/dist/website/Workbench/Chronology.d.ts +32 -0
- package/dist/website/Workbench/Chronology.js +32 -0
- package/dist/website/Workbench/Chronology.js.map +1 -0
- package/dist/website/Workbench/ContactRow.d.ts +13 -0
- package/dist/website/Workbench/ContactRow.js +11 -0
- package/dist/website/Workbench/ContactRow.js.map +1 -0
- package/dist/website/Workbench/PhotoMosaic.d.ts +13 -0
- package/dist/website/Workbench/PhotoMosaic.js +15 -0
- package/dist/website/Workbench/PhotoMosaic.js.map +1 -0
- package/dist/website/Workbench/Reveal.d.ts +19 -0
- package/dist/website/Workbench/Reveal.js +29 -0
- package/dist/website/Workbench/Reveal.js.map +1 -0
- package/dist/website/Workbench/ToolStrip.d.ts +18 -0
- package/dist/website/Workbench/ToolStrip.js +15 -0
- package/dist/website/Workbench/ToolStrip.js.map +1 -0
- package/dist/website/Workbench/Workbench.d.ts +23 -0
- package/dist/website/Workbench/Workbench.js +22 -0
- package/dist/website/Workbench/Workbench.js.map +1 -0
- package/dist/website/Workbench/WorkbenchCard.d.ts +29 -0
- package/dist/website/Workbench/WorkbenchCard.js +21 -0
- package/dist/website/Workbench/WorkbenchCard.js.map +1 -0
- package/dist/website/Workbench/WorkbenchEntries.d.ts +22 -0
- package/dist/website/Workbench/WorkbenchEntries.js +24 -0
- package/dist/website/Workbench/WorkbenchEntries.js.map +1 -0
- package/dist/website/Workbench/WorkbenchFigure.d.ts +20 -0
- package/dist/website/Workbench/WorkbenchFigure.js +15 -0
- package/dist/website/Workbench/WorkbenchFigure.js.map +1 -0
- package/dist/website/Workbench/WorkbenchHero.d.ts +24 -0
- package/dist/website/Workbench/WorkbenchHero.js +24 -0
- package/dist/website/Workbench/WorkbenchHero.js.map +1 -0
- package/dist/website/Workbench/theme.d.ts +22 -0
- package/dist/website/Workbench/theme.js +12 -0
- package/dist/website/Workbench/theme.js.map +1 -0
- package/dist/website/index.d.ts +38 -0
- package/dist/website/index.js +32 -0
- package/dist/website/index.js.map +1 -0
- package/dist/website-actions.css +6 -0
- package/dist/website-base.css +46 -0
- package/dist/website-collection.css +89 -0
- package/dist/website-contact.css +29 -0
- package/dist/website-content.css +20 -0
- package/dist/website-controls.css +91 -0
- package/dist/website-conversation.css +115 -0
- package/dist/website-evidence.css +56 -0
- package/dist/website-media.css +227 -0
- package/dist/website-metrics.css +15 -0
- package/dist/website-music.css +27 -0
- package/dist/website-portfolio.css +94 -0
- package/dist/website-reading.css +159 -0
- package/dist/website-recovery.css +28 -0
- package/dist/website-search.css +26 -0
- package/dist/website-shell.css +89 -0
- package/dist/website-timeline.css +43 -0
- package/dist/website-workbench.css +162 -0
- package/dist/website.css +26 -0
- package/llms.txt +35 -0
- package/package.json +163 -5
- package/skills/folio-design/SKILL.md +228 -0
- package/skills/folio-design/evals/claims.json +95 -0
- package/skills/folio-design/evals/evals.json +84 -0
- package/skills/folio-design/rules/a11y.md +167 -0
- package/skills/folio-design/rules/composition.md +108 -0
- package/skills/folio-design/rules/forms.md +135 -0
- package/skills/folio-design/rules/naming.md +155 -0
- package/skills/folio-design/rules/tokens.md +135 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { ChartEmptyProps } from './empty.js';
|
|
4
|
+
|
|
5
|
+
interface ChartColumn {
|
|
6
|
+
/** The row field this column reads. */
|
|
7
|
+
key: string;
|
|
8
|
+
/** What the column is called in the table header. */
|
|
9
|
+
label: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
interface ChartDataTableProps {
|
|
12
|
+
caption: string;
|
|
13
|
+
rows: Record<string, unknown>[];
|
|
14
|
+
columns: ChartColumn[];
|
|
15
|
+
/** The field naming each row — the category, the date, the bucket. */
|
|
16
|
+
rowKey?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The chart's data, as a table, for a reader who cannot see the chart.
|
|
20
|
+
*
|
|
21
|
+
* An SVG plot is a picture: `accessibilityLayer` gives Recharts' own keyboard
|
|
22
|
+
* cursor and announces one point at a time, which is navigation rather than
|
|
23
|
+
* access to the figures. This is the table view — visually hidden, in the
|
|
24
|
+
* accessibility tree, and generated from the same rows the marks are drawn
|
|
25
|
+
* from, so the two cannot disagree.
|
|
26
|
+
*
|
|
27
|
+
* `sr-only` rather than `hidden`: `display: none` removes it from the
|
|
28
|
+
* accessibility tree as well as from the page, which would defeat the purpose.
|
|
29
|
+
*/
|
|
30
|
+
declare function ChartDataTable({ caption, rows, columns, rowKey }: ChartDataTableProps): react.JSX.Element | null;
|
|
31
|
+
interface ChartFigureProps {
|
|
32
|
+
/**
|
|
33
|
+
* What the chart shows, in a sentence a reader could act on — "Visitors per
|
|
34
|
+
* month, 2026" rather than "Chart".
|
|
35
|
+
*
|
|
36
|
+
* Required, and required for the same reason `Table.caption` and
|
|
37
|
+
* `Progress.label` are: a plot with no name announces nothing, and it is not
|
|
38
|
+
* a thing a call site can be trusted to remember. Hidden by default, because
|
|
39
|
+
* most call sites already print a heading above the chart; `showTitle` puts
|
|
40
|
+
* it back when they do not.
|
|
41
|
+
*/
|
|
42
|
+
title: string;
|
|
43
|
+
/** Prints the title above the plot instead of hiding it from sight. */
|
|
44
|
+
showTitle?: boolean;
|
|
45
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
46
|
+
description?: ReactNode;
|
|
47
|
+
className?: string;
|
|
48
|
+
children: ReactNode;
|
|
49
|
+
/** The table view. Omit and it is generated; `false` opts out. */
|
|
50
|
+
table?: Omit<ChartDataTableProps, 'caption'> | false;
|
|
51
|
+
/**
|
|
52
|
+
* Whether there is nothing to draw. The plot is replaced by `empty` when it
|
|
53
|
+
* is true.
|
|
54
|
+
*
|
|
55
|
+
* Named as a question rather than derived from `table.rows`, because a chart
|
|
56
|
+
* mid-load has no rows either and wants its skeleton, not a message.
|
|
57
|
+
*/
|
|
58
|
+
isEmpty?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* What stands in for the plot when there is nothing to draw. `false` keeps
|
|
61
|
+
* the plot, for a chart whose emptiness is itself the reading.
|
|
62
|
+
*/
|
|
63
|
+
empty?: ChartEmptyProps | false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The figure a chart is rendered inside: its name, its plot, and its data as a
|
|
67
|
+
* table.
|
|
68
|
+
*
|
|
69
|
+
* Every chart root in the package wraps itself in this, so "the chart is
|
|
70
|
+
* announced and its numbers are reachable" is a property of the system rather
|
|
71
|
+
* than something each call site has to remember to add.
|
|
72
|
+
*
|
|
73
|
+
* The empty state is here for the same reason. Seven of the twenty charts had
|
|
74
|
+
* no `empty` at all — zero rows drew a named figure over a blank box, and
|
|
75
|
+
* `ChartDataTable` renders nothing below one row, so the picture and its text
|
|
76
|
+
* equivalent went silent together and the reader could not tell "no data" from
|
|
77
|
+
* "failed to load". A chart that forgets it now has to forget it here, once.
|
|
78
|
+
*/
|
|
79
|
+
declare function ChartFigure({ title, showTitle, description, className, children, table, isEmpty, empty, }: ChartFigureProps): react.JSX.Element;
|
|
80
|
+
|
|
81
|
+
export { type ChartColumn, ChartDataTable, type ChartDataTableProps, ChartFigure, type ChartFigureProps };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
import { ChartEmpty } from "./empty.js";
|
|
5
|
+
function ChartDataTable({ caption, rows, columns, rowKey }) {
|
|
6
|
+
if (rows.length === 0 || columns.length === 0) return null;
|
|
7
|
+
return /* @__PURE__ */ jsxs("table", { className: "sr-only", children: [
|
|
8
|
+
/* @__PURE__ */ jsx("caption", { children: caption }),
|
|
9
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
10
|
+
rowKey && /* @__PURE__ */ jsx("th", { scope: "col", children: rowKey }),
|
|
11
|
+
columns.map((column) => /* @__PURE__ */ jsx("th", { scope: "col", children: column.label }, column.key))
|
|
12
|
+
] }) }),
|
|
13
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
14
|
+
rowKey && /* @__PURE__ */ jsx("th", { scope: "row", children: cellText(row[rowKey]) || String(index + 1) }),
|
|
15
|
+
columns.map((column) => /* @__PURE__ */ jsx("td", { children: cellText(row[column.key]) }, column.key))
|
|
16
|
+
] }, index)) })
|
|
17
|
+
] });
|
|
18
|
+
}
|
|
19
|
+
function cellText(value) {
|
|
20
|
+
if (value === null || value === void 0) return "";
|
|
21
|
+
if (typeof value === "number") return value.toLocaleString();
|
|
22
|
+
if (typeof value === "string" || typeof value === "boolean") return String(value);
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
function ChartFigure({
|
|
26
|
+
title,
|
|
27
|
+
showTitle = false,
|
|
28
|
+
description,
|
|
29
|
+
className,
|
|
30
|
+
children,
|
|
31
|
+
table,
|
|
32
|
+
isEmpty = false,
|
|
33
|
+
empty
|
|
34
|
+
}) {
|
|
35
|
+
const captionId = `chart-title-${useId().replace(/:/g, "")}`;
|
|
36
|
+
return (
|
|
37
|
+
// Named explicitly rather than relying on the caption. A `<figcaption>` IS
|
|
38
|
+
// the figure's accessible name per the spec, but support for deriving it is
|
|
39
|
+
// uneven across assistive technology — and a chart whose name resolves in
|
|
40
|
+
// only some screen readers is a chart with no name.
|
|
41
|
+
/* @__PURE__ */ jsxs("figure", { "aria-labelledby": captionId, className: cn("flex min-h-0 w-full flex-col", className), children: [
|
|
42
|
+
/* @__PURE__ */ jsxs(
|
|
43
|
+
"figcaption",
|
|
44
|
+
{
|
|
45
|
+
id: captionId,
|
|
46
|
+
className: cn(!showTitle && "sr-only", showTitle && "mb-3 flex flex-col gap-1"),
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx("span", { className: cn(showTitle && "font-heading text-[length:var(--fs-item)] text-(--ink)"), children: title }),
|
|
49
|
+
description && /* @__PURE__ */ jsx("span", { className: cn(showTitle && "mono-meta text-(--ink-3-aa)"), children: description })
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
isEmpty && empty !== false ? /* @__PURE__ */ jsx(ChartEmpty, { ...empty || {} }) : children,
|
|
54
|
+
table && /* @__PURE__ */ jsx(ChartDataTable, { caption: title, ...table })
|
|
55
|
+
] })
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
ChartDataTable,
|
|
60
|
+
ChartFigure
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=figure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/figure.tsx"],"sourcesContent":["import { useId, type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { ChartEmpty, type ChartEmptyProps } from './empty'\n\nexport interface ChartColumn {\n /** The row field this column reads. */\n key: string\n /** What the column is called in the table header. */\n label: ReactNode\n}\n\nexport interface ChartDataTableProps {\n caption: string\n rows: Record<string, unknown>[]\n columns: ChartColumn[]\n /** The field naming each row — the category, the date, the bucket. */\n rowKey?: string\n}\n\n/**\n * The chart's data, as a table, for a reader who cannot see the chart.\n *\n * An SVG plot is a picture: `accessibilityLayer` gives Recharts' own keyboard\n * cursor and announces one point at a time, which is navigation rather than\n * access to the figures. This is the table view — visually hidden, in the\n * accessibility tree, and generated from the same rows the marks are drawn\n * from, so the two cannot disagree.\n *\n * `sr-only` rather than `hidden`: `display: none` removes it from the\n * accessibility tree as well as from the page, which would defeat the purpose.\n */\nexport function ChartDataTable({ caption, rows, columns, rowKey }: ChartDataTableProps) {\n if (rows.length === 0 || columns.length === 0) return null\n\n return (\n <table className=\"sr-only\">\n <caption>{caption}</caption>\n <thead>\n <tr>\n {rowKey && <th scope=\"col\">{rowKey}</th>}\n {columns.map((column) => (\n <th key={column.key} scope=\"col\">\n {column.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, index) => (\n <tr key={index}>\n {rowKey && <th scope=\"row\">{cellText(row[rowKey]) || String(index + 1)}</th>}\n {columns.map((column) => (\n <td key={column.key}>{cellText(row[column.key])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\n/** A cell value as text. Anything that is not a primitive reads as empty. */\nfunction cellText(value: unknown): string {\n if (value === null || value === undefined) return ''\n if (typeof value === 'number') return value.toLocaleString()\n if (typeof value === 'string' || typeof value === 'boolean') return String(value)\n return ''\n}\n\nexport interface ChartFigureProps {\n /**\n * What the chart shows, in a sentence a reader could act on — \"Visitors per\n * month, 2026\" rather than \"Chart\".\n *\n * Required, and required for the same reason `Table.caption` and\n * `Progress.label` are: a plot with no name announces nothing, and it is not\n * a thing a call site can be trusted to remember. Hidden by default, because\n * most call sites already print a heading above the chart; `showTitle` puts\n * it back when they do not.\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 className?: string\n children: ReactNode\n /** The table view. Omit and it is generated; `false` opts out. */\n table?: Omit<ChartDataTableProps, 'caption'> | false\n /**\n * Whether there is nothing to draw. The plot is replaced by `empty` when it\n * is true.\n *\n * Named as a question rather than derived from `table.rows`, because a chart\n * mid-load has no rows either and wants its skeleton, not a message.\n */\n isEmpty?: boolean\n /**\n * What stands in for the plot when there is nothing to draw. `false` keeps\n * the plot, for a chart whose emptiness is itself the reading.\n */\n empty?: ChartEmptyProps | false\n}\n\n/**\n * The figure a chart is rendered inside: its name, its plot, and its data as a\n * table.\n *\n * Every chart root in the package wraps itself in this, so \"the chart is\n * announced and its numbers are reachable\" is a property of the system rather\n * than something each call site has to remember to add.\n *\n * The empty state is here for the same reason. Seven of the twenty charts had\n * no `empty` at all — zero rows drew a named figure over a blank box, and\n * `ChartDataTable` renders nothing below one row, so the picture and its text\n * equivalent went silent together and the reader could not tell \"no data\" from\n * \"failed to load\". A chart that forgets it now has to forget it here, once.\n */\nexport function ChartFigure({\n title,\n showTitle = false,\n description,\n className,\n children,\n table,\n isEmpty = false,\n empty,\n}: ChartFigureProps) {\n const captionId = `chart-title-${useId().replace(/:/g, '')}`\n\n return (\n // Named explicitly rather than relying on the caption. A `<figcaption>` IS\n // the figure's accessible name per the spec, but support for deriving it is\n // uneven across assistive technology — and a chart whose name resolves in\n // only some screen readers is a chart with no name.\n <figure aria-labelledby={captionId} className={cn('flex min-h-0 w-full flex-col', className)}>\n <figcaption\n id={captionId}\n className={cn(!showTitle && 'sr-only', showTitle && 'mb-3 flex flex-col gap-1')}\n >\n <span className={cn(showTitle && 'font-heading text-[length:var(--fs-item)] text-(--ink)')}>{title}</span>\n {description && (\n <span className={cn(showTitle && 'mono-meta text-(--ink-3-aa)')}>{description}</span>\n )}\n </figcaption>\n {isEmpty && empty !== false ? <ChartEmpty {...(empty || {})} /> : children}\n {table && <ChartDataTable caption={title} {...table} />}\n </figure>\n )\n}\n"],"mappings":"AAoCM,cAEE,YAFF;AApCN,SAAS,aAA6B;AACtC,SAAS,UAAU;AACnB,SAAS,kBAAwC;AA6B1C,SAAS,eAAe,EAAE,SAAS,MAAM,SAAS,OAAO,GAAwB;AACtF,MAAI,KAAK,WAAW,KAAK,QAAQ,WAAW,EAAG,QAAO;AAEtD,SACE,qBAAC,WAAM,WAAU,WACf;AAAA,wBAAC,aAAS,mBAAQ;AAAA,IAClB,oBAAC,WACC,+BAAC,QACE;AAAA,gBAAU,oBAAC,QAAG,OAAM,OAAO,kBAAO;AAAA,MAClC,QAAQ,IAAI,CAAC,WACZ,oBAAC,QAAoB,OAAM,OACxB,iBAAO,SADD,OAAO,GAEhB,CACD;AAAA,OACH,GACF;AAAA,IACA,oBAAC,WACE,eAAK,IAAI,CAAC,KAAK,UACd,qBAAC,QACE;AAAA,gBAAU,oBAAC,QAAG,OAAM,OAAO,mBAAS,IAAI,MAAM,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAE;AAAA,MACtE,QAAQ,IAAI,CAAC,WACZ,oBAAC,QAAqB,mBAAS,IAAI,OAAO,GAAG,CAAC,KAArC,OAAO,GAAgC,CACjD;AAAA,SAJM,KAKT,CACD,GACH;AAAA,KACF;AAEJ;AAGA,SAAS,SAAS,OAAwB;AACxC,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,eAAe;AAC3D,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAChF,SAAO;AACT;AAmDO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAAqB;AACnB,QAAM,YAAY,eAAe,MAAM,EAAE,QAAQ,MAAM,EAAE,CAAC;AAE1D;AAAA;AAAA;AAAA;AAAA;AAAA,IAKE,qBAAC,YAAO,mBAAiB,WAAW,WAAW,GAAG,gCAAgC,SAAS,GACzF;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,WAAW,GAAG,CAAC,aAAa,WAAW,aAAa,0BAA0B;AAAA,UAE9E;AAAA,gCAAC,UAAK,WAAW,GAAG,aAAa,wDAAwD,GAAI,iBAAM;AAAA,YAClG,eACC,oBAAC,UAAK,WAAW,GAAG,aAAa,6BAA6B,GAAI,uBAAY;AAAA;AAAA;AAAA,MAElF;AAAA,MACC,WAAW,UAAU,QAAQ,oBAAC,cAAY,GAAI,SAAS,CAAC,GAAI,IAAK;AAAA,MACjE,SAAS,oBAAC,kBAAe,SAAS,OAAQ,GAAG,OAAO;AAAA,OACvD;AAAA;AAEJ;","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a number is written on a chart.
|
|
3
|
+
*
|
|
4
|
+
* `compact` is the one an axis almost always wants and almost never gets:
|
|
5
|
+
* an axis reading 1,200,000 spends four characters saying "this is a big
|
|
6
|
+
* number" and pushes the plot inward to do it, where 1.2M says the same thing
|
|
7
|
+
* in four characters total. Every other option here exists because a bare
|
|
8
|
+
* `toLocaleString` cannot say what the number IS — a share, a price, a span.
|
|
9
|
+
*/
|
|
10
|
+
type NumberStyle = 'plain' | 'compact' | 'percent' | 'currency' | 'duration' | 'bytes';
|
|
11
|
+
interface NumberFormatOptions {
|
|
12
|
+
style?: NumberStyle;
|
|
13
|
+
/** BCP 47 tag. Omit and the reader's own locale decides. */
|
|
14
|
+
locale?: string;
|
|
15
|
+
/** ISO 4217, for `currency`. */
|
|
16
|
+
currency?: string;
|
|
17
|
+
/** Digits after the point. Defaults to what the style needs. */
|
|
18
|
+
fractionDigits?: number;
|
|
19
|
+
/** Written after the number — "req/s", "kB", "°C". Ignored by `currency`. */
|
|
20
|
+
unit?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A formatter for one axis, one tooltip, or one label.
|
|
24
|
+
*
|
|
25
|
+
* Returns a function rather than a string so it can be handed straight to
|
|
26
|
+
* Recharts' `tickFormatter`, which is called once per tick and must not
|
|
27
|
+
* rebuild an `Intl.NumberFormat` each time — constructing one is expensive
|
|
28
|
+
* enough that doing it per tick shows up on a chart with a brush.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* <BarChart.YAxis tickFormatter={formatNumber({ style: 'compact' })} />
|
|
32
|
+
* @example
|
|
33
|
+
* <LineChart.YAxis tickFormatter={formatNumber({ style: 'currency', currency: 'AUD' })} />
|
|
34
|
+
*/
|
|
35
|
+
declare function formatNumber(options?: NumberFormatOptions): (value: number) => string;
|
|
36
|
+
/**
|
|
37
|
+
* The default a chart uses when nothing is said: compact above four digits,
|
|
38
|
+
* plain below it.
|
|
39
|
+
*
|
|
40
|
+
* The threshold is where an axis starts costing the plot real width. Below it,
|
|
41
|
+
* "9,400" is more precise and no wider than "9.4K"; above it, the compact form
|
|
42
|
+
* wins on both counts.
|
|
43
|
+
*/
|
|
44
|
+
declare const defaultTick: (value: number) => string;
|
|
45
|
+
|
|
46
|
+
export { type NumberFormatOptions, type NumberStyle, defaultTick, formatNumber };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const MINUTE = 60;
|
|
2
|
+
const HOUR = 3600;
|
|
3
|
+
const DAY = 86400;
|
|
4
|
+
const BYTE_STEPS = ["B", "kB", "MB", "GB", "TB", "PB"];
|
|
5
|
+
function duration(seconds) {
|
|
6
|
+
const sign = seconds < 0 ? "-" : "";
|
|
7
|
+
const total = Math.abs(seconds);
|
|
8
|
+
if (total < MINUTE) return `${sign}${Math.round(total)}s`;
|
|
9
|
+
if (total < HOUR) {
|
|
10
|
+
const minutes = Math.floor(total / MINUTE);
|
|
11
|
+
const rest = Math.round(total % MINUTE);
|
|
12
|
+
return rest === 0 ? `${sign}${minutes}m` : `${sign}${minutes}m ${rest}s`;
|
|
13
|
+
}
|
|
14
|
+
if (total < DAY) {
|
|
15
|
+
const hours2 = Math.floor(total / HOUR);
|
|
16
|
+
const minutes = Math.round(total % HOUR / MINUTE);
|
|
17
|
+
return minutes === 0 ? `${sign}${hours2}h` : `${sign}${hours2}h ${minutes}m`;
|
|
18
|
+
}
|
|
19
|
+
const days = Math.floor(total / DAY);
|
|
20
|
+
const hours = Math.round(total % DAY / HOUR);
|
|
21
|
+
return hours === 0 ? `${sign}${days}d` : `${sign}${days}d ${hours}h`;
|
|
22
|
+
}
|
|
23
|
+
function bytes(value, fractionDigits, locale) {
|
|
24
|
+
const sign = value < 0 ? "-" : "";
|
|
25
|
+
let size = Math.abs(value);
|
|
26
|
+
let step = 0;
|
|
27
|
+
while (size >= 1024 && step < BYTE_STEPS.length - 1) {
|
|
28
|
+
size /= 1024;
|
|
29
|
+
step += 1;
|
|
30
|
+
}
|
|
31
|
+
const digits = fractionDigits ?? (step === 0 || size >= 100 ? 0 : 1);
|
|
32
|
+
return `${sign}${size.toLocaleString(locale, { maximumFractionDigits: digits })} ${BYTE_STEPS[step]}`;
|
|
33
|
+
}
|
|
34
|
+
function formatNumber(options = {}) {
|
|
35
|
+
const { style = "plain", locale, currency = "USD", fractionDigits, unit } = options;
|
|
36
|
+
if (style === "duration") return (value) => duration(value);
|
|
37
|
+
if (style === "bytes") return (value) => bytes(value, fractionDigits, locale);
|
|
38
|
+
const intl = new Intl.NumberFormat(locale, {
|
|
39
|
+
notation: style === "compact" ? "compact" : "standard",
|
|
40
|
+
compactDisplay: "short",
|
|
41
|
+
style: style === "percent" ? "percent" : style === "currency" ? "currency" : "decimal",
|
|
42
|
+
currency: style === "currency" ? currency : void 0,
|
|
43
|
+
minimumFractionDigits: fractionDigits,
|
|
44
|
+
maximumFractionDigits: fractionDigits ?? (style === "compact" ? 1 : void 0)
|
|
45
|
+
});
|
|
46
|
+
if (!unit || style === "currency") return (value) => intl.format(value);
|
|
47
|
+
return (value) => `${intl.format(value)} ${unit}`;
|
|
48
|
+
}
|
|
49
|
+
const defaultTick = (value) => Math.abs(value) >= 1e4 ? COMPACT(value) : PLAIN(value);
|
|
50
|
+
const COMPACT = formatNumber({ style: "compact" });
|
|
51
|
+
const PLAIN = formatNumber({ style: "plain" });
|
|
52
|
+
export {
|
|
53
|
+
defaultTick,
|
|
54
|
+
formatNumber
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/format.ts"],"sourcesContent":["/**\n * How a number is written on a chart.\n *\n * `compact` is the one an axis almost always wants and almost never gets:\n * an axis reading 1,200,000 spends four characters saying \"this is a big\n * number\" and pushes the plot inward to do it, where 1.2M says the same thing\n * in four characters total. Every other option here exists because a bare\n * `toLocaleString` cannot say what the number IS — a share, a price, a span.\n */\nexport type NumberStyle = 'plain' | 'compact' | 'percent' | 'currency' | 'duration' | 'bytes'\n\nexport interface NumberFormatOptions {\n style?: NumberStyle\n /** BCP 47 tag. Omit and the reader's own locale decides. */\n locale?: string\n /** ISO 4217, for `currency`. */\n currency?: string\n /** Digits after the point. Defaults to what the style needs. */\n fractionDigits?: number\n /** Written after the number — \"req/s\", \"kB\", \"°C\". Ignored by `currency`. */\n unit?: string\n}\n\nconst MINUTE = 60\nconst HOUR = 3600\nconst DAY = 86_400\n\n/** 1024-based steps, because a byte count is not a decimal quantity. */\nconst BYTE_STEPS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'] as const\n\n/**\n * Seconds as a span a person reads — \"1h 12m\", not \"4320\".\n *\n * Two units at most on purpose: \"1h 12m 30s\" is three facts where the reader\n * asked for one, and the third is never the one that mattered.\n */\nfunction duration(seconds: number): string {\n const sign = seconds < 0 ? '-' : ''\n const total = Math.abs(seconds)\n\n if (total < MINUTE) return `${sign}${Math.round(total)}s`\n if (total < HOUR) {\n const minutes = Math.floor(total / MINUTE)\n const rest = Math.round(total % MINUTE)\n return rest === 0 ? `${sign}${minutes}m` : `${sign}${minutes}m ${rest}s`\n }\n if (total < DAY) {\n const hours = Math.floor(total / HOUR)\n const minutes = Math.round((total % HOUR) / MINUTE)\n return minutes === 0 ? `${sign}${hours}h` : `${sign}${hours}h ${minutes}m`\n }\n const days = Math.floor(total / DAY)\n const hours = Math.round((total % DAY) / HOUR)\n return hours === 0 ? `${sign}${days}d` : `${sign}${days}d ${hours}h`\n}\n\nfunction bytes(value: number, fractionDigits: number | undefined, locale?: string): string {\n const sign = value < 0 ? '-' : ''\n let size = Math.abs(value)\n let step = 0\n while (size >= 1024 && step < BYTE_STEPS.length - 1) {\n size /= 1024\n step += 1\n }\n const digits = fractionDigits ?? (step === 0 || size >= 100 ? 0 : 1)\n // A maximum without a minimum: 2048 bytes is \"2 kB\", not \"2.0 kB\". A\n // trailing zero on a size claims a precision the step conversion does not\n // have.\n return `${sign}${size.toLocaleString(locale, { maximumFractionDigits: digits })} ${BYTE_STEPS[step]}`\n}\n\n/**\n * A formatter for one axis, one tooltip, or one label.\n *\n * Returns a function rather than a string so it can be handed straight to\n * Recharts' `tickFormatter`, which is called once per tick and must not\n * rebuild an `Intl.NumberFormat` each time — constructing one is expensive\n * enough that doing it per tick shows up on a chart with a brush.\n *\n * @example\n * <BarChart.YAxis tickFormatter={formatNumber({ style: 'compact' })} />\n * @example\n * <LineChart.YAxis tickFormatter={formatNumber({ style: 'currency', currency: 'AUD' })} />\n */\nexport function formatNumber(options: NumberFormatOptions = {}): (value: number) => string {\n const { style = 'plain', locale, currency = 'USD', fractionDigits, unit } = options\n\n if (style === 'duration') return (value) => duration(value)\n if (style === 'bytes') return (value) => bytes(value, fractionDigits, locale)\n\n const intl = new Intl.NumberFormat(locale, {\n notation: style === 'compact' ? 'compact' : 'standard',\n compactDisplay: 'short',\n style: style === 'percent' ? 'percent' : style === 'currency' ? 'currency' : 'decimal',\n currency: style === 'currency' ? currency : undefined,\n minimumFractionDigits: fractionDigits,\n maximumFractionDigits: fractionDigits ?? (style === 'compact' ? 1 : undefined),\n })\n\n if (!unit || style === 'currency') return (value) => intl.format(value)\n // A plain space, not a thin one: U+2009 is invisible in a diff and the\n // linter flags it, and at 11px on an axis the two are indistinguishable.\n return (value) => `${intl.format(value)} ${unit}`\n}\n\n/**\n * The default a chart uses when nothing is said: compact above four digits,\n * plain below it.\n *\n * The threshold is where an axis starts costing the plot real width. Below it,\n * \"9,400\" is more precise and no wider than \"9.4K\"; above it, the compact form\n * wins on both counts.\n */\nexport const defaultTick = (value: number): string =>\n Math.abs(value) >= 10_000 ? COMPACT(value) : PLAIN(value)\n\nconst COMPACT = formatNumber({ style: 'compact' })\nconst PLAIN = formatNumber({ style: 'plain' })\n"],"mappings":"AAuBA,MAAM,SAAS;AACf,MAAM,OAAO;AACb,MAAM,MAAM;AAGZ,MAAM,aAAa,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,IAAI;AAQrD,SAAS,SAAS,SAAyB;AACzC,QAAM,OAAO,UAAU,IAAI,MAAM;AACjC,QAAM,QAAQ,KAAK,IAAI,OAAO;AAE9B,MAAI,QAAQ,OAAQ,QAAO,GAAG,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AACtD,MAAI,QAAQ,MAAM;AAChB,UAAM,UAAU,KAAK,MAAM,QAAQ,MAAM;AACzC,UAAM,OAAO,KAAK,MAAM,QAAQ,MAAM;AACtC,WAAO,SAAS,IAAI,GAAG,IAAI,GAAG,OAAO,MAAM,GAAG,IAAI,GAAG,OAAO,KAAK,IAAI;AAAA,EACvE;AACA,MAAI,QAAQ,KAAK;AACf,UAAMA,SAAQ,KAAK,MAAM,QAAQ,IAAI;AACrC,UAAM,UAAU,KAAK,MAAO,QAAQ,OAAQ,MAAM;AAClD,WAAO,YAAY,IAAI,GAAG,IAAI,GAAGA,MAAK,MAAM,GAAG,IAAI,GAAGA,MAAK,KAAK,OAAO;AAAA,EACzE;AACA,QAAM,OAAO,KAAK,MAAM,QAAQ,GAAG;AACnC,QAAM,QAAQ,KAAK,MAAO,QAAQ,MAAO,IAAI;AAC7C,SAAO,UAAU,IAAI,GAAG,IAAI,GAAG,IAAI,MAAM,GAAG,IAAI,GAAG,IAAI,KAAK,KAAK;AACnE;AAEA,SAAS,MAAM,OAAe,gBAAoC,QAAyB;AACzF,QAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,MAAI,OAAO,KAAK,IAAI,KAAK;AACzB,MAAI,OAAO;AACX,SAAO,QAAQ,QAAQ,OAAO,WAAW,SAAS,GAAG;AACnD,YAAQ;AACR,YAAQ;AAAA,EACV;AACA,QAAM,SAAS,mBAAmB,SAAS,KAAK,QAAQ,MAAM,IAAI;AAIlE,SAAO,GAAG,IAAI,GAAG,KAAK,eAAe,QAAQ,EAAE,uBAAuB,OAAO,CAAC,CAAC,IAAI,WAAW,IAAI,CAAC;AACrG;AAeO,SAAS,aAAa,UAA+B,CAAC,GAA8B;AACzF,QAAM,EAAE,QAAQ,SAAS,QAAQ,WAAW,OAAO,gBAAgB,KAAK,IAAI;AAE5E,MAAI,UAAU,WAAY,QAAO,CAAC,UAAU,SAAS,KAAK;AAC1D,MAAI,UAAU,QAAS,QAAO,CAAC,UAAU,MAAM,OAAO,gBAAgB,MAAM;AAE5E,QAAM,OAAO,IAAI,KAAK,aAAa,QAAQ;AAAA,IACzC,UAAU,UAAU,YAAY,YAAY;AAAA,IAC5C,gBAAgB;AAAA,IAChB,OAAO,UAAU,YAAY,YAAY,UAAU,aAAa,aAAa;AAAA,IAC7E,UAAU,UAAU,aAAa,WAAW;AAAA,IAC5C,uBAAuB;AAAA,IACvB,uBAAuB,mBAAmB,UAAU,YAAY,IAAI;AAAA,EACtE,CAAC;AAED,MAAI,CAAC,QAAQ,UAAU,WAAY,QAAO,CAAC,UAAU,KAAK,OAAO,KAAK;AAGtE,SAAO,CAAC,UAAU,GAAG,KAAK,OAAO,KAAK,CAAC,IAAI,IAAI;AACjD;AAUO,MAAM,cAAc,CAAC,UAC1B,KAAK,IAAI,KAAK,KAAK,MAAS,QAAQ,KAAK,IAAI,MAAM,KAAK;AAE1D,MAAM,UAAU,aAAa,EAAE,OAAO,UAAU,CAAC;AACjD,MAAM,QAAQ,aAAa,EAAE,OAAO,QAAQ,CAAC;","names":["hours"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as recharts from 'recharts';
|
|
2
|
+
import { DefaultLegendContentProps } from 'recharts';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The shape of a legend's series mark.
|
|
7
|
+
*
|
|
8
|
+
* Seven, because the mark is doing more work here than in a chromatic system:
|
|
9
|
+
* with the monochrome ramp, a bar-shaped swatch beside a bar chart and a
|
|
10
|
+
* dot-shaped one beside a scatter is often the fastest way a reader ties the
|
|
11
|
+
* key to the plot.
|
|
12
|
+
*/
|
|
13
|
+
type ChartLegendVariant = 'square' | 'circle' | 'circle-outline' | 'rounded-square' | 'rounded-square-outline' | 'vertical-bar' | 'horizontal-bar';
|
|
14
|
+
/** Where the legend sits along the inline axis. Recharts' own vocabulary. */
|
|
15
|
+
type ChartLegendAlign = 'left' | 'center' | 'right';
|
|
16
|
+
interface ChartLegendContentProps extends DefaultLegendContentProps {
|
|
17
|
+
className?: string;
|
|
18
|
+
/** Suppresses a config `icon`, falling back to the shape swatch. */
|
|
19
|
+
hideIcon?: boolean;
|
|
20
|
+
/** The row field holding a series name, when it is not the `dataKey`. */
|
|
21
|
+
nameKey?: string;
|
|
22
|
+
/** The chart's selected series, or null when the whole plot is lit. */
|
|
23
|
+
selected?: string | null;
|
|
24
|
+
/** Makes each entry a control that toggles its series. */
|
|
25
|
+
isClickable?: boolean;
|
|
26
|
+
onSelectChange?: (selected: string | null) => void;
|
|
27
|
+
variant?: ChartLegendVariant;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The key to a plot's series.
|
|
31
|
+
*
|
|
32
|
+
* Required above one series and not decorative: the monochrome ramp separates
|
|
33
|
+
* two series by a step of grey and a texture, and neither is self-describing.
|
|
34
|
+
* The chroma palette does not change that — three of its light steps sit below
|
|
35
|
+
* 3:1 on paper, and the legend is the documented relief.
|
|
36
|
+
*
|
|
37
|
+
* When `isClickable` is set each entry is a real `<button>` with `aria-pressed`
|
|
38
|
+
* rather than a `<div>` with a click handler. That is the difference between a
|
|
39
|
+
* filter a keyboard can reach and one it cannot, and it is why the entry is not
|
|
40
|
+
* simply styled to look pressable.
|
|
41
|
+
*/
|
|
42
|
+
declare function ChartLegendContent({ className, hideIcon, nameKey, payload, verticalAlign, align, selected, onSelectChange, isClickable, variant, }: ChartLegendContentProps): react.JSX.Element | null;
|
|
43
|
+
declare const ChartLegend: react.MemoExoticComponent<(outsideProps: recharts.LegendProps) => React.ReactPortal | null>;
|
|
44
|
+
|
|
45
|
+
export { ChartLegend, type ChartLegendAlign, ChartLegendContent, type ChartLegendContentProps, type ChartLegendVariant };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Legend as RechartsLegend } from "recharts";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { colorStops, cssName, seriesFromPayload, useChart } from "./chart.js";
|
|
6
|
+
const ALIGN = {
|
|
7
|
+
left: "justify-start",
|
|
8
|
+
center: "justify-center",
|
|
9
|
+
right: "justify-end"
|
|
10
|
+
};
|
|
11
|
+
function ChartLegendContent({
|
|
12
|
+
className,
|
|
13
|
+
hideIcon = false,
|
|
14
|
+
nameKey,
|
|
15
|
+
payload,
|
|
16
|
+
verticalAlign,
|
|
17
|
+
align = "right",
|
|
18
|
+
selected,
|
|
19
|
+
onSelectChange,
|
|
20
|
+
isClickable,
|
|
21
|
+
variant = "rounded-square"
|
|
22
|
+
}) {
|
|
23
|
+
const { config } = useChart();
|
|
24
|
+
if (!payload?.length) return null;
|
|
25
|
+
return /* @__PURE__ */ jsx(
|
|
26
|
+
"ul",
|
|
27
|
+
{
|
|
28
|
+
className: cn(
|
|
29
|
+
"m-0 flex list-none items-center gap-4 p-0 select-none",
|
|
30
|
+
ALIGN[align],
|
|
31
|
+
verticalAlign === "top" ? "pb-4" : "pt-4",
|
|
32
|
+
className
|
|
33
|
+
),
|
|
34
|
+
children: payload.filter((item) => item.type !== "none").map((item) => {
|
|
35
|
+
const named = nameKey && item.payload ? item.payload[nameKey] : void 0;
|
|
36
|
+
const key = `${named ?? item.value ?? item.dataKey ?? "value"}`;
|
|
37
|
+
const series = seriesFromPayload(config, item, key);
|
|
38
|
+
const isLit = selected === null || selected === void 0 || selected === key;
|
|
39
|
+
const stops = series ? colorStops(series) : 1;
|
|
40
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
series?.icon && !hideIcon ? /* @__PURE__ */ jsx(series.icon, { "aria-hidden": true }) : /* @__PURE__ */ jsx(LegendSwatch, { variant, seriesKey: key, stops }),
|
|
42
|
+
series?.label ?? key
|
|
43
|
+
] });
|
|
44
|
+
const shared = cn(
|
|
45
|
+
"flex items-center gap-1.5 text-(--ink-2) transition-opacity duration-(--duration-fast) [&>svg]:size-3 [&>svg]:text-(--ink-3-aa)",
|
|
46
|
+
!isLit && "opacity-30"
|
|
47
|
+
);
|
|
48
|
+
return /* @__PURE__ */ jsx("li", { children: isClickable ? /* @__PURE__ */ jsx(
|
|
49
|
+
"button",
|
|
50
|
+
{
|
|
51
|
+
type: "button",
|
|
52
|
+
"aria-pressed": selected === key,
|
|
53
|
+
onClick: () => onSelectChange?.(selected === key ? null : key),
|
|
54
|
+
className: cn(
|
|
55
|
+
shared,
|
|
56
|
+
"cursor-pointer rounded-(--radius-sm) hover:text-(--ink)"
|
|
57
|
+
),
|
|
58
|
+
children: body
|
|
59
|
+
}
|
|
60
|
+
) : /* @__PURE__ */ jsx("span", { className: shared, children: body }) }, key);
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function LegendSwatch({
|
|
66
|
+
variant,
|
|
67
|
+
seriesKey,
|
|
68
|
+
stops
|
|
69
|
+
}) {
|
|
70
|
+
const fill = paintStyle(seriesKey, stops);
|
|
71
|
+
const outline = { ...fill, ...MASK };
|
|
72
|
+
switch (variant) {
|
|
73
|
+
case "square":
|
|
74
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0", style: fill });
|
|
75
|
+
case "circle":
|
|
76
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0 rounded-(--radius-pill)", style: fill });
|
|
77
|
+
case "circle-outline":
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
"span",
|
|
80
|
+
{
|
|
81
|
+
"aria-hidden": true,
|
|
82
|
+
className: "size-2.5 shrink-0 rounded-(--radius-pill) p-[1.5px]",
|
|
83
|
+
style: outline
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
case "vertical-bar":
|
|
87
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-3 w-1 shrink-0 rounded-[2px]", style: fill });
|
|
88
|
+
case "horizontal-bar":
|
|
89
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-1 w-3 shrink-0 rounded-[2px]", style: fill });
|
|
90
|
+
case "rounded-square-outline":
|
|
91
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2.5 shrink-0 rounded-[3px] p-[1.5px]", style: outline });
|
|
92
|
+
case "rounded-square":
|
|
93
|
+
default:
|
|
94
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0 rounded-[2px]", style: fill });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const MASK = {
|
|
98
|
+
WebkitMask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
99
|
+
WebkitMaskComposite: "xor",
|
|
100
|
+
mask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
101
|
+
maskComposite: "exclude"
|
|
102
|
+
};
|
|
103
|
+
function paintStyle(seriesKey, stops) {
|
|
104
|
+
const name = cssName(seriesKey);
|
|
105
|
+
if (stops <= 1) return { backgroundColor: `var(--color-${name}-0)` };
|
|
106
|
+
const gradient = Array.from({ length: stops }, (_, index) => {
|
|
107
|
+
const offset = index / (stops - 1) * 100;
|
|
108
|
+
return `var(--color-${name}-${index}) ${offset}%`;
|
|
109
|
+
}).join(", ");
|
|
110
|
+
return { background: `linear-gradient(to right, ${gradient})` };
|
|
111
|
+
}
|
|
112
|
+
const ChartLegend = RechartsLegend;
|
|
113
|
+
export {
|
|
114
|
+
ChartLegend,
|
|
115
|
+
ChartLegendContent
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=legend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/legend.tsx"],"sourcesContent":["'use client'\n\nimport type { CSSProperties } from 'react'\nimport { Legend as RechartsLegend } from 'recharts'\nimport type { DefaultLegendContentProps } from 'recharts'\nimport { cn } from '../../lib/cn'\nimport { colorStops, cssName, seriesFromPayload, useChart } from './chart'\n\n/**\n * The shape of a legend's series mark.\n *\n * Seven, because the mark is doing more work here than in a chromatic system:\n * with the monochrome ramp, a bar-shaped swatch beside a bar chart and a\n * dot-shaped one beside a scatter is often the fastest way a reader ties the\n * key to the plot.\n */\nexport type ChartLegendVariant =\n | 'square'\n | 'circle'\n | 'circle-outline'\n | 'rounded-square'\n | 'rounded-square-outline'\n | 'vertical-bar'\n | 'horizontal-bar'\n\n/** Where the legend sits along the inline axis. Recharts' own vocabulary. */\nexport type ChartLegendAlign = 'left' | 'center' | 'right'\n\nconst ALIGN: Record<ChartLegendAlign, string> = {\n left: 'justify-start',\n center: 'justify-center',\n right: 'justify-end',\n}\n\nexport interface ChartLegendContentProps extends DefaultLegendContentProps {\n className?: string\n /** Suppresses a config `icon`, falling back to the shape swatch. */\n hideIcon?: boolean\n /** The row field holding a series name, when it is not the `dataKey`. */\n nameKey?: string\n /** The chart's selected series, or null when the whole plot is lit. */\n selected?: string | null\n /** Makes each entry a control that toggles its series. */\n isClickable?: boolean\n onSelectChange?: (selected: string | null) => void\n variant?: ChartLegendVariant\n}\n\n/**\n * The key to a plot's series.\n *\n * Required above one series and not decorative: the monochrome ramp separates\n * two series by a step of grey and a texture, and neither is self-describing.\n * The chroma palette does not change that — three of its light steps sit below\n * 3:1 on paper, and the legend is the documented relief.\n *\n * When `isClickable` is set each entry is a real `<button>` with `aria-pressed`\n * rather than a `<div>` with a click handler. That is the difference between a\n * filter a keyboard can reach and one it cannot, and it is why the entry is not\n * simply styled to look pressable.\n */\nexport function ChartLegendContent({\n className,\n hideIcon = false,\n nameKey,\n payload,\n verticalAlign,\n align = 'right',\n selected,\n onSelectChange,\n isClickable,\n variant = 'rounded-square',\n}: ChartLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) return null\n\n return (\n <ul\n className={cn(\n 'm-0 flex list-none items-center gap-4 p-0 select-none',\n ALIGN[align],\n verticalAlign === 'top' ? 'pb-4' : 'pt-4',\n className,\n )}\n >\n {payload\n .filter((item) => item.type !== 'none')\n .map((item) => {\n const named =\n nameKey && item.payload ? (item.payload as Record<string, unknown>)[nameKey] : undefined\n const key = `${named ?? item.value ?? item.dataKey ?? 'value'}`\n const series = seriesFromPayload(config, item, key)\n const isLit = selected === null || selected === undefined || selected === key\n const stops = series ? colorStops(series) : 1\n\n const body = (\n <>\n {series?.icon && !hideIcon ? (\n <series.icon aria-hidden />\n ) : (\n <LegendSwatch variant={variant} seriesKey={key} stops={stops} />\n )}\n {series?.label ?? key}\n </>\n )\n\n const shared = cn(\n 'flex items-center gap-1.5 text-(--ink-2) transition-opacity duration-(--duration-fast) [&>svg]:size-3 [&>svg]:text-(--ink-3-aa)',\n !isLit && 'opacity-30',\n )\n\n return (\n <li key={key}>\n {isClickable ? (\n <button\n type=\"button\"\n aria-pressed={selected === key}\n onClick={() => onSelectChange?.(selected === key ? null : key)}\n className={cn(\n shared,\n 'cursor-pointer rounded-(--radius-sm) hover:text-(--ink)',\n )}\n >\n {body}\n </button>\n ) : (\n <span className={shared}>{body}</span>\n )}\n </li>\n )\n })}\n </ul>\n )\n}\n\n/**\n * The swatch itself. Each variant is its own branch rather than a size lookup,\n * because the outline forms are built differently from the filled ones and a\n * shared branch would have to carry both.\n */\nfunction LegendSwatch({\n variant,\n seriesKey,\n stops,\n}: {\n variant: ChartLegendVariant\n seriesKey: string\n stops: number\n}) {\n const fill = paintStyle(seriesKey, stops)\n const outline = { ...fill, ...MASK }\n\n switch (variant) {\n case 'square':\n return <span aria-hidden className=\"size-2 shrink-0\" style={fill} />\n case 'circle':\n return <span aria-hidden className=\"size-2 shrink-0 rounded-(--radius-pill)\" style={fill} />\n case 'circle-outline':\n return (\n <span\n aria-hidden\n className=\"size-2.5 shrink-0 rounded-(--radius-pill) p-[1.5px]\"\n style={outline}\n />\n )\n case 'vertical-bar':\n return <span aria-hidden className=\"h-3 w-1 shrink-0 rounded-[2px]\" style={fill} />\n case 'horizontal-bar':\n return <span aria-hidden className=\"h-1 w-3 shrink-0 rounded-[2px]\" style={fill} />\n case 'rounded-square-outline':\n return <span aria-hidden className=\"size-2.5 shrink-0 rounded-[3px] p-[1.5px]\" style={outline} />\n case 'rounded-square':\n default:\n return <span aria-hidden className=\"size-2 shrink-0 rounded-[2px]\" style={fill} />\n }\n}\n\n/**\n * Punches the middle out of a filled swatch, leaving its border.\n *\n * `border-color` cannot take a gradient, and a swatch whose series is painted\n * with several stops has to show them. Two masks composited with `exclude`\n * leave only the padding box — which follows the border radius, which a border\n * approximated with an inset box-shadow would not.\n */\nconst MASK: CSSProperties = {\n WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n WebkitMaskComposite: 'xor',\n mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n maskComposite: 'exclude',\n}\n\n/** A swatch's paint: the series colour, or its gradient across the swatch. */\nfunction paintStyle(seriesKey: string, stops: number): CSSProperties {\n const name = cssName(seriesKey)\n if (stops <= 1) return { backgroundColor: `var(--color-${name}-0)` }\n\n const gradient = Array.from({ length: stops }, (_, index) => {\n const offset = (index / (stops - 1)) * 100\n return `var(--color-${name}-${index}) ${offset}%`\n }).join(', ')\n\n return { background: `linear-gradient(to right, ${gradient})` }\n}\n\nexport const ChartLegend = RechartsLegend\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
/** The key the skeleton series is drawn from. Never a real series name. */
|
|
4
|
+
declare const LOADING_KEY = "loading";
|
|
5
|
+
/** Rows for the skeleton plot: one field, values inside a plausible band. */
|
|
6
|
+
declare function loadingRows(points?: number, salt?: number, min?: number, max?: number): {
|
|
7
|
+
loading: number;
|
|
8
|
+
}[];
|
|
9
|
+
/**
|
|
10
|
+
* The skeleton's rows, re-rolled each time the shimmer leaves the plot.
|
|
11
|
+
*
|
|
12
|
+
* The swap is driven by the shimmer's own position rather than by a timer: an
|
|
13
|
+
* interval drifts against the animation and eventually re-rolls the data in
|
|
14
|
+
* full view, which reads as the chart glitching rather than as it loading.
|
|
15
|
+
*/
|
|
16
|
+
declare function useLoadingRows(isLoading: boolean, points?: number): {
|
|
17
|
+
rows: {
|
|
18
|
+
loading: number;
|
|
19
|
+
}[];
|
|
20
|
+
onShimmerExit: () => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The badge over a loading plot.
|
|
24
|
+
*
|
|
25
|
+
* Sits above the skeleton rather than replacing it, so the chart keeps its
|
|
26
|
+
* measured height and the page does not jump when the data lands.
|
|
27
|
+
*/
|
|
28
|
+
declare function LoadingIndicator({ isLoading }: {
|
|
29
|
+
isLoading: boolean;
|
|
30
|
+
}): react.JSX.Element | null;
|
|
31
|
+
/**
|
|
32
|
+
* The travelling mask that makes the skeleton read as "working" rather than as
|
|
33
|
+
* "broken".
|
|
34
|
+
*
|
|
35
|
+
* The plot is normalised to 0–1 and the pattern is three times that wide, so
|
|
36
|
+
* the highlight has a full plot-width of runway on each side. `onShimmerExit`
|
|
37
|
+
* fires as it crosses the far edge — off-screen — which is where the rows are
|
|
38
|
+
* re-rolled, so the loop has no visible seam.
|
|
39
|
+
*
|
|
40
|
+
* With `prefers-reduced-motion` the whole travelling layer is dropped for a
|
|
41
|
+
* flat wash: the skeleton still says "not yet", without anything moving.
|
|
42
|
+
*/
|
|
43
|
+
declare function LoadingShimmer({ id, onShimmerExit }: {
|
|
44
|
+
id: string;
|
|
45
|
+
onShimmerExit: () => void;
|
|
46
|
+
}): react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
export { LOADING_KEY, LoadingIndicator, LoadingShimmer, loadingRows, useLoadingRows };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
5
|
+
const LOADING_KEY = "loading";
|
|
6
|
+
const SHIMMER_SECONDS = 2;
|
|
7
|
+
function noise(index, salt) {
|
|
8
|
+
const x = Math.sin(index * 127.1 + salt * 311.7) * 43758.5453;
|
|
9
|
+
return x - Math.floor(x);
|
|
10
|
+
}
|
|
11
|
+
function loadingRows(points = 14, salt = 0, min = 0, max = 70) {
|
|
12
|
+
return Array.from({ length: points }, (_, index) => ({
|
|
13
|
+
[LOADING_KEY]: Math.floor(noise(index, salt) * (max - min)) + min
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
function useLoadingRows(isLoading, points = 14) {
|
|
17
|
+
const [salt, setSalt] = useState(0);
|
|
18
|
+
const onShimmerExit = useCallback(() => {
|
|
19
|
+
if (isLoading) setSalt((previous) => previous + 1);
|
|
20
|
+
}, [isLoading]);
|
|
21
|
+
const rows = useMemo(() => loadingRows(points, salt), [points, salt]);
|
|
22
|
+
return { rows, onShimmerExit };
|
|
23
|
+
}
|
|
24
|
+
function LoadingIndicator({ isLoading }) {
|
|
25
|
+
if (!isLoading) return null;
|
|
26
|
+
return /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-(--z-rule) flex items-center justify-center", children: /* @__PURE__ */ jsxs(
|
|
27
|
+
"output",
|
|
28
|
+
{
|
|
29
|
+
className: "flex items-center gap-2 rounded-(--radius) border border-(--rule) bg-(--chart-surface) px-2.5 py-1 mono-meta text-(--ink-2)",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
"span",
|
|
33
|
+
{
|
|
34
|
+
"aria-hidden": true,
|
|
35
|
+
"data-folio-animated": true,
|
|
36
|
+
className: "size-3 rounded-(--radius-pill) border border-(--rule-2) border-t-(--ink) motion-safe:animate-[folio-spin_0.8s_linear_infinite]"
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
"Loading"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
) });
|
|
43
|
+
}
|
|
44
|
+
function shimmerStops(steps = 17, min = 0.05, max = 0.9) {
|
|
45
|
+
return Array.from({ length: steps }, (_, index) => {
|
|
46
|
+
const t = index / (steps - 1);
|
|
47
|
+
const eased = Math.sin(t * Math.PI) ** 2;
|
|
48
|
+
return {
|
|
49
|
+
offset: `${Math.round(t * 100)}%`,
|
|
50
|
+
opacity: Number((min + eased * (max - min)).toFixed(3))
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function LoadingShimmer({ id, onShimmerExit }) {
|
|
55
|
+
const reduceMotion = useReducedMotion();
|
|
56
|
+
const stops = shimmerStops();
|
|
57
|
+
const lastX = useRef(-1);
|
|
58
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx("linearGradient", { id: `${id}-loading-gradient`, x1: "0", y1: "0", x2: "1", y2: "0", children: stops.map(({ offset, opacity }) => /* @__PURE__ */ jsx("stop", { offset, stopColor: "white", stopOpacity: opacity }, offset)) }),
|
|
60
|
+
/* @__PURE__ */ jsx("mask", { id: `${id}-loading-mask`, maskUnits: "userSpaceOnUse", children: reduceMotion ? /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: "white", fillOpacity: 0.55 }) : /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}-loading-pattern)` }) }),
|
|
61
|
+
!reduceMotion && /* @__PURE__ */ jsx(
|
|
62
|
+
"pattern",
|
|
63
|
+
{
|
|
64
|
+
id: `${id}-loading-pattern`,
|
|
65
|
+
patternUnits: "objectBoundingBox",
|
|
66
|
+
patternContentUnits: "objectBoundingBox",
|
|
67
|
+
patternTransform: "rotate(25)",
|
|
68
|
+
width: 3,
|
|
69
|
+
height: "1",
|
|
70
|
+
x: "0",
|
|
71
|
+
y: "0",
|
|
72
|
+
children: /* @__PURE__ */ jsx(
|
|
73
|
+
motion.rect,
|
|
74
|
+
{
|
|
75
|
+
y: "0",
|
|
76
|
+
width: "1",
|
|
77
|
+
height: "1",
|
|
78
|
+
fill: `url(#${id}-loading-gradient)`,
|
|
79
|
+
initial: { x: -1 },
|
|
80
|
+
animate: { x: 2 },
|
|
81
|
+
transition: {
|
|
82
|
+
duration: SHIMMER_SECONDS,
|
|
83
|
+
ease: "linear",
|
|
84
|
+
repeat: Infinity,
|
|
85
|
+
repeatType: "loop"
|
|
86
|
+
},
|
|
87
|
+
onUpdate: (latest) => {
|
|
88
|
+
const x = typeof latest.x === "number" ? latest.x : -1;
|
|
89
|
+
if (x >= 1 && lastX.current < 1) onShimmerExit();
|
|
90
|
+
lastX.current = x;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
] });
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
LOADING_KEY,
|
|
100
|
+
LoadingIndicator,
|
|
101
|
+
LoadingShimmer,
|
|
102
|
+
loadingRows,
|
|
103
|
+
useLoadingRows
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/loading.tsx"],"sourcesContent":["'use client'\n\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { motion, useReducedMotion } from 'motion/react'\n\n/** The key the skeleton series is drawn from. Never a real series name. */\nexport const LOADING_KEY = 'loading'\n\n/** One shimmer pass, in seconds. */\nconst SHIMMER_SECONDS = 2\n\n/**\n * A deterministic pseudo-random sequence, seeded by index.\n *\n * The shape this was ported from called `Math.random()` inside a `useMemo`,\n * which runs during render — so the server rendered one skeleton, the client\n * rendered a different one, and React logged a hydration mismatch for every\n * chart on the page. A hash of the index gives the same jagged, un-patterned\n * silhouette on both sides of the wire, which is the only property the\n * skeleton actually needs from randomness.\n */\nfunction noise(index: number, salt: number): number {\n const x = Math.sin(index * 127.1 + salt * 311.7) * 43758.5453\n return x - Math.floor(x)\n}\n\n/** Rows for the skeleton plot: one field, values inside a plausible band. */\nexport function loadingRows(points = 14, salt = 0, min = 0, max = 70) {\n return Array.from({ length: points }, (_, index) => ({\n [LOADING_KEY]: Math.floor(noise(index, salt) * (max - min)) + min,\n }))\n}\n\n/**\n * The skeleton's rows, re-rolled each time the shimmer leaves the plot.\n *\n * The swap is driven by the shimmer's own position rather than by a timer: an\n * interval drifts against the animation and eventually re-rolls the data in\n * full view, which reads as the chart glitching rather than as it loading.\n */\nexport function useLoadingRows(isLoading: boolean, points = 14) {\n const [salt, setSalt] = useState(0)\n\n const onShimmerExit = useCallback(() => {\n if (isLoading) setSalt((previous) => previous + 1)\n }, [isLoading])\n\n const rows = useMemo(() => loadingRows(points, salt), [points, salt])\n\n return { rows, onShimmerExit }\n}\n\n/**\n * The badge over a loading plot.\n *\n * Sits above the skeleton rather than replacing it, so the chart keeps its\n * measured height and the page does not jump when the data lands.\n */\nexport function LoadingIndicator({ isLoading }: { isLoading: boolean }) {\n if (!isLoading) return null\n\n return (\n <div className=\"pointer-events-none absolute inset-0 z-(--z-rule) flex items-center justify-center\">\n <output\n className=\"flex items-center gap-2 rounded-(--radius) border border-(--rule) bg-(--chart-surface) px-2.5 py-1 mono-meta text-(--ink-2)\"\n >\n <span\n aria-hidden\n data-folio-animated\n className=\"size-3 rounded-(--radius-pill) border border-(--rule-2) border-t-(--ink) motion-safe:animate-[folio-spin_0.8s_linear_infinite]\"\n />\n Loading\n </output>\n </div>\n )\n}\n\n/** Bell-curve opacity stops, so the shimmer has no hard edge at either end. */\nfunction shimmerStops(steps = 17, min = 0.05, max = 0.9) {\n return Array.from({ length: steps }, (_, index) => {\n const t = index / (steps - 1)\n const eased = Math.sin(t * Math.PI) ** 2\n return {\n offset: `${Math.round(t * 100)}%`,\n opacity: Number((min + eased * (max - min)).toFixed(3)),\n }\n })\n}\n\n/**\n * The travelling mask that makes the skeleton read as \"working\" rather than as\n * \"broken\".\n *\n * The plot is normalised to 0–1 and the pattern is three times that wide, so\n * the highlight has a full plot-width of runway on each side. `onShimmerExit`\n * fires as it crosses the far edge — off-screen — which is where the rows are\n * re-rolled, so the loop has no visible seam.\n *\n * With `prefers-reduced-motion` the whole travelling layer is dropped for a\n * flat wash: the skeleton still says \"not yet\", without anything moving.\n */\nexport function LoadingShimmer({ id, onShimmerExit }: { id: string; onShimmerExit: () => void }) {\n const reduceMotion = useReducedMotion()\n const stops = shimmerStops()\n const lastX = useRef(-1)\n\n return (\n <>\n <linearGradient id={`${id}-loading-gradient`} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">\n {stops.map(({ offset, opacity }) => (\n <stop key={offset} offset={offset} stopColor=\"white\" stopOpacity={opacity} />\n ))}\n </linearGradient>\n <mask id={`${id}-loading-mask`} maskUnits=\"userSpaceOnUse\">\n {reduceMotion ? (\n <rect width=\"100%\" height=\"100%\" fill=\"white\" fillOpacity={0.55} />\n ) : (\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id}-loading-pattern)`} />\n )}\n </mask>\n {!reduceMotion && (\n <pattern\n id={`${id}-loading-pattern`}\n patternUnits=\"objectBoundingBox\"\n patternContentUnits=\"objectBoundingBox\"\n patternTransform=\"rotate(25)\"\n width={3}\n height=\"1\"\n x=\"0\"\n y=\"0\"\n >\n <motion.rect\n y=\"0\"\n width=\"1\"\n height=\"1\"\n fill={`url(#${id}-loading-gradient)`}\n initial={{ x: -1 }}\n animate={{ x: 2 }}\n transition={{\n duration: SHIMMER_SECONDS,\n ease: 'linear',\n repeat: Infinity,\n repeatType: 'loop',\n }}\n onUpdate={(latest) => {\n const x = typeof latest.x === 'number' ? latest.x : -1\n if (x >= 1 && lastX.current < 1) onShimmerExit()\n lastX.current = x\n }}\n />\n </pattern>\n )}\n </>\n )\n}\n"],"mappings":"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","names":[]}
|