@misoto22/folio 0.0.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/bin/folio-design.mjs +277 -0
- package/bin/migrate-legacy.mjs +81 -0
- package/dist/agent/Accordion.md +65 -0
- package/dist/agent/Actions.md +49 -0
- package/dist/agent/Alert.md +65 -0
- package/dist/agent/AppShell.md +69 -0
- package/dist/agent/ArchitectureFigure.md +72 -0
- package/dist/agent/AreaChart.md +94 -0
- package/dist/agent/Article.md +65 -0
- package/dist/agent/AspectRatio.md +58 -0
- package/dist/agent/Avatar.md +53 -0
- package/dist/agent/Badge.md +62 -0
- package/dist/agent/BarChart.md +93 -0
- package/dist/agent/BarList.md +67 -0
- package/dist/agent/BigNumber.md +70 -0
- package/dist/agent/BoxPlot.md +82 -0
- package/dist/agent/Breadcrumb.md +55 -0
- package/dist/agent/BulletChart.md +71 -0
- package/dist/agent/Button.md +81 -0
- package/dist/agent/Calendar.md +77 -0
- package/dist/agent/CalendarHeatmap.md +75 -0
- package/dist/agent/Card.md +72 -0
- package/dist/agent/Checkbox.md +57 -0
- package/dist/agent/Code.md +51 -0
- package/dist/agent/CodeBlock.md +77 -0
- package/dist/agent/Collapsible.md +68 -0
- package/dist/agent/Collection.md +169 -0
- package/dist/agent/ColorPicker.md +76 -0
- package/dist/agent/Combobox.md +77 -0
- package/dist/agent/Command.md +122 -0
- package/dist/agent/ComposedChart.md +82 -0
- package/dist/agent/Contact.md +90 -0
- package/dist/agent/Content.md +70 -0
- package/dist/agent/ContextMenu.md +93 -0
- package/dist/agent/Conversation.md +247 -0
- package/dist/agent/DataflowFigure.md +49 -0
- package/dist/agent/DatePicker.md +104 -0
- package/dist/agent/DescriptionList.md +69 -0
- package/dist/agent/Diagram.md +71 -0
- package/dist/agent/DiagramCanvas.md +71 -0
- package/dist/agent/DiagramExportMenu.md +65 -0
- package/dist/agent/DiagramInspector.md +73 -0
- package/dist/agent/DiagramLegend.md +56 -0
- package/dist/agent/DiagramMinimap.md +69 -0
- package/dist/agent/DiagramToolbar.md +70 -0
- package/dist/agent/Dialog.md +76 -0
- package/dist/agent/DropdownMenu.md +110 -0
- package/dist/agent/EmptyState.md +63 -0
- package/dist/agent/ErrorState.md +67 -0
- package/dist/agent/Evidence.md +165 -0
- package/dist/agent/Facet.md +107 -0
- package/dist/agent/Field.md +79 -0
- package/dist/agent/FigureBand.md +49 -0
- package/dist/agent/FloatingIconButton.md +61 -0
- package/dist/agent/FunnelChart.md +75 -0
- package/dist/agent/Heading.md +65 -0
- package/dist/agent/Heatmap.md +78 -0
- package/dist/agent/Histogram.md +88 -0
- package/dist/agent/Input.md +52 -0
- package/dist/agent/Kbd.md +48 -0
- package/dist/agent/LifecycleFigure.md +50 -0
- package/dist/agent/LineChart.md +85 -0
- package/dist/agent/LinkArrow.md +49 -0
- package/dist/agent/Markdown.md +69 -0
- package/dist/agent/Media.md +261 -0
- package/dist/agent/Metric.md +70 -0
- package/dist/agent/Metrics.md +114 -0
- package/dist/agent/Music.md +86 -0
- package/dist/agent/NativeSelect.md +62 -0
- package/dist/agent/NavItem.md +56 -0
- package/dist/agent/NumberField.md +73 -0
- package/dist/agent/PageHeader.md +69 -0
- package/dist/agent/Pagination.md +70 -0
- package/dist/agent/PieChart.md +80 -0
- package/dist/agent/Popover.md +80 -0
- package/dist/agent/Portfolio.md +93 -0
- package/dist/agent/PortfolioIndex.md +34 -0
- package/dist/agent/Progress.md +58 -0
- package/dist/agent/RadarChart.md +79 -0
- package/dist/agent/RadialChart.md +81 -0
- package/dist/agent/RadioGroup.md +66 -0
- package/dist/agent/Reading.md +233 -0
- package/dist/agent/Recovery.md +72 -0
- package/dist/agent/SankeyChart.md +85 -0
- package/dist/agent/ScatterChart.md +80 -0
- package/dist/agent/ScrollArea.md +62 -0
- package/dist/agent/SearchPalette.md +51 -0
- package/dist/agent/SearchableMenu.md +69 -0
- package/dist/agent/Select.md +102 -0
- package/dist/agent/Separator.md +60 -0
- package/dist/agent/SequenceFigure.md +51 -0
- package/dist/agent/Sheet.md +82 -0
- package/dist/agent/Sidebar.md +194 -0
- package/dist/agent/SiteNavigation.md +62 -0
- package/dist/agent/SiteShell.md +67 -0
- package/dist/agent/Skeleton.md +96 -0
- package/dist/agent/Slider.md +67 -0
- package/dist/agent/Sparkline.md +68 -0
- package/dist/agent/Spinner.md +62 -0
- package/dist/agent/StatusDot.md +56 -0
- package/dist/agent/StatusPill.md +55 -0
- package/dist/agent/Steps.md +68 -0
- package/dist/agent/Switch.md +50 -0
- package/dist/agent/Table.md +111 -0
- package/dist/agent/Tabs.md +71 -0
- package/dist/agent/Tag.md +67 -0
- package/dist/agent/Text.md +66 -0
- package/dist/agent/Textarea.md +46 -0
- package/dist/agent/Timeline.md +114 -0
- package/dist/agent/Timestamp.md +65 -0
- package/dist/agent/Toast.md +51 -0
- package/dist/agent/ToggleGroup.md +67 -0
- package/dist/agent/Toolbar.md +72 -0
- package/dist/agent/Tooltip.md +74 -0
- package/dist/agent/TreemapChart.md +76 -0
- package/dist/agent/WaterfallChart.md +86 -0
- package/dist/agent/WorkflowFigure.md +51 -0
- package/dist/agent/catalog.json +8006 -0
- package/dist/agent/index.md +182 -0
- package/dist/article.css +407 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +198 -0
- package/dist/charts/AreaChart/AreaChart.js +479 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +190 -0
- package/dist/charts/BarChart/BarChart.js +599 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +65 -0
- package/dist/charts/BarList/BarList.js +79 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +72 -0
- package/dist/charts/BigNumber/BigNumber.js +51 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +497 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +197 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.d.ts +106 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js +103 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +178 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +106 -0
- package/dist/charts/FunnelChart/FunnelChart.js +137 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +101 -0
- package/dist/charts/Heatmap/Heatmap.js +125 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +188 -0
- package/dist/charts/Histogram/Histogram.js +382 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +174 -0
- package/dist/charts/LineChart/LineChart.js +485 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +140 -0
- package/dist/charts/PieChart/PieChart.js +317 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +135 -0
- package/dist/charts/RadarChart/RadarChart.js +303 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +142 -0
- package/dist/charts/RadialChart/RadialChart.js +279 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +149 -0
- package/dist/charts/SankeyChart/SankeyChart.js +509 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +149 -0
- package/dist/charts/ScatterChart/ScatterChart.js +275 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +95 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +98 -0
- package/dist/charts/TreemapChart/TreemapChart.js +127 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +321 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +43 -0
- package/dist/charts/index.js +130 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +149 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +24 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +94 -0
- package/dist/charts/lib/export.js +62 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +81 -0
- package/dist/charts/lib/figure.js +62 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +144 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +43 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +58 -0
- package/dist/components/AppShell/AppShell.js +126 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Article/Article.d.ts +58 -0
- package/dist/components/Article/Article.js +34 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +38 -0
- package/dist/components/Avatar/Avatar.js +44 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +37 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +46 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +95 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +54 -0
- package/dist/components/Calendar/Calendar.js +369 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +55 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +26 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +145 -0
- package/dist/components/CodeBlock/CodeBlock.js +114 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +45 -0
- package/dist/components/Collapsible/Collapsible.js +60 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +77 -0
- package/dist/components/Combobox/Combobox.js +170 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +125 -0
- package/dist/components/Command/Command.js +204 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +63 -0
- package/dist/components/ContextMenu/ContextMenu.js +109 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +130 -0
- package/dist/components/DatePicker/DatePicker.js +257 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +86 -0
- package/dist/components/Diagram/Diagram.js +211 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +63 -0
- package/dist/components/Dialog/Dialog.js +90 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +87 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +120 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +55 -0
- package/dist/components/EmptyState/EmptyState.js +32 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +55 -0
- package/dist/components/ErrorState/ErrorState.js +41 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +111 -0
- package/dist/components/Field/Field.js +95 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +31 -0
- package/dist/components/FigureBand/FigureBand.js +51 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +34 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +27 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/Metric/Metric.d.ts +61 -0
- package/dist/components/Metric/Metric.js +51 -0
- package/dist/components/Metric/Metric.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +33 -0
- package/dist/components/NativeSelect/NativeSelect.js +44 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +92 -0
- package/dist/components/PageHeader/PageHeader.js +37 -0
- package/dist/components/PageHeader/PageHeader.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +67 -0
- package/dist/components/Pagination/Pagination.js +112 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +43 -0
- package/dist/components/Progress/Progress.js +57 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +49 -0
- package/dist/components/RadioGroup/RadioGroup.js +53 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +46 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +68 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +101 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +87 -0
- package/dist/components/Select/Select.js +130 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +48 -0
- package/dist/components/Separator/Separator.js +43 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +43 -0
- package/dist/components/Sheet/Sheet.js +79 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.d.ts +357 -0
- package/dist/components/Sidebar/Sidebar.js +447 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +74 -0
- package/dist/components/Slider/Slider.js +143 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +58 -0
- package/dist/components/Spinner/Spinner.js +49 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +30 -0
- package/dist/components/StatusPill/StatusPill.js +37 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +25 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +137 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +37 -0
- package/dist/components/Tabs/Tabs.js +205 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +87 -0
- package/dist/components/Tag/Tag.js +62 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +32 -0
- package/dist/components/Toast/Toast.js +64 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +46 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +88 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
- package/dist/diagrams/index.d.ts +17 -0
- package/dist/diagrams/index.js +29 -0
- package/dist/diagrams/index.js.map +1 -0
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +138 -0
- package/dist/diagrams/lib/frame.js +131 -0
- package/dist/diagrams/lib/frame.js.map +1 -0
- package/dist/diagrams/lib/geometry.d.ts +114 -0
- package/dist/diagrams/lib/geometry.js +113 -0
- package/dist/diagrams/lib/geometry.js.map +1 -0
- package/dist/diagrams/lib/legend.d.ts +32 -0
- package/dist/diagrams/lib/legend.js +84 -0
- package/dist/diagrams/lib/legend.js.map +1 -0
- package/dist/diagrams/lib/marks.d.ts +207 -0
- package/dist/diagrams/lib/marks.js +480 -0
- package/dist/diagrams/lib/marks.js.map +1 -0
- package/dist/diagrams/lib/route.d.ts +106 -0
- package/dist/diagrams/lib/route.js +201 -0
- package/dist/diagrams/lib/route.js.map +1 -0
- package/dist/diagrams/lib/wires.d.ts +59 -0
- package/dist/diagrams/lib/wires.js +94 -0
- package/dist/diagrams/lib/wires.js.map +1 -0
- package/dist/diagrams/spec.d.ts +405 -0
- package/dist/diagrams/spec.js +1 -0
- package/dist/diagrams/spec.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +300 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/control.d.ts +32 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +48 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/slot-content.d.ts +8 -0
- package/dist/lib/slot-content.js +17 -0
- package/dist/lib/slot-content.js.map +1 -0
- package/dist/lib/step-rail.d.ts +45 -0
- package/dist/lib/step-rail.js +47 -0
- package/dist/lib/step-rail.js.map +1 -0
- package/dist/lib/svg-export.d.ts +138 -0
- package/dist/lib/svg-export.js +198 -0
- package/dist/lib/svg-export.js.map +1 -0
- package/dist/lib/useClipboardCopy.d.ts +30 -0
- package/dist/lib/useClipboardCopy.js +37 -0
- package/dist/lib/useClipboardCopy.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +49 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +193 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +514 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +652 -0
- package/dist/tokens.d.ts +198 -0
- package/dist/tokens.js +1020 -0
- package/dist/tokens.json +1019 -0
- package/dist/website/Actions/Actions.d.ts +34 -0
- package/dist/website/Actions/Actions.js +29 -0
- package/dist/website/Actions/Actions.js.map +1 -0
- package/dist/website/Collection/Collection.d.ts +128 -0
- package/dist/website/Collection/Collection.js +162 -0
- package/dist/website/Collection/Collection.js.map +1 -0
- package/dist/website/Contact/Contact.d.ts +87 -0
- package/dist/website/Contact/Contact.js +94 -0
- package/dist/website/Contact/Contact.js.map +1 -0
- package/dist/website/Content/CodePanel.d.ts +27 -0
- package/dist/website/Content/CodePanel.js +30 -0
- package/dist/website/Content/CodePanel.js.map +1 -0
- package/dist/website/Content/Content.d.ts +29 -0
- package/dist/website/Content/Content.js +38 -0
- package/dist/website/Content/Content.js.map +1 -0
- package/dist/website/Conversation/Conversation.d.ts +193 -0
- package/dist/website/Conversation/Conversation.js +252 -0
- package/dist/website/Conversation/Conversation.js.map +1 -0
- package/dist/website/Evidence/Evidence.d.ts +116 -0
- package/dist/website/Evidence/Evidence.js +142 -0
- package/dist/website/Evidence/Evidence.js.map +1 -0
- package/dist/website/Media/Media.d.ts +173 -0
- package/dist/website/Media/Media.js +225 -0
- package/dist/website/Media/Media.js.map +1 -0
- package/dist/website/Media/MediaLightbox.d.ts +18 -0
- package/dist/website/Media/MediaLightbox.js +38 -0
- package/dist/website/Media/MediaLightbox.js.map +1 -0
- package/dist/website/Metrics/Metrics.d.ts +74 -0
- package/dist/website/Metrics/Metrics.js +96 -0
- package/dist/website/Metrics/Metrics.js.map +1 -0
- package/dist/website/Music/Music.d.ts +60 -0
- package/dist/website/Music/Music.js +80 -0
- package/dist/website/Music/Music.js.map +1 -0
- package/dist/website/Portfolio/FrameLayout.d.ts +9 -0
- package/dist/website/Portfolio/FrameLayout.js +42 -0
- package/dist/website/Portfolio/FrameLayout.js.map +1 -0
- package/dist/website/Portfolio/Portfolio.d.ts +49 -0
- package/dist/website/Portfolio/Portfolio.js +66 -0
- package/dist/website/Portfolio/Portfolio.js.map +1 -0
- package/dist/website/Portfolio/QuestionCard.d.ts +22 -0
- package/dist/website/Portfolio/QuestionCard.js +33 -0
- package/dist/website/Portfolio/QuestionCard.js.map +1 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.d.ts +21 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js +31 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js.map +1 -0
- package/dist/website/Reading/Reading.d.ts +203 -0
- package/dist/website/Reading/Reading.js +357 -0
- package/dist/website/Reading/Reading.js.map +1 -0
- package/dist/website/Recovery/Recovery.d.ts +39 -0
- package/dist/website/Recovery/Recovery.js +96 -0
- package/dist/website/Recovery/Recovery.js.map +1 -0
- package/dist/website/SearchPalette/SearchPalette.d.ts +59 -0
- package/dist/website/SearchPalette/SearchPalette.js +120 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -0
- package/dist/website/SiteNavigation/SiteNavigation.d.ts +46 -0
- package/dist/website/SiteNavigation/SiteNavigation.js +101 -0
- package/dist/website/SiteNavigation/SiteNavigation.js.map +1 -0
- package/dist/website/SiteShell/SiteShell.d.ts +45 -0
- package/dist/website/SiteShell/SiteShell.js +46 -0
- package/dist/website/SiteShell/SiteShell.js.map +1 -0
- package/dist/website/Timeline/Timeline.d.ts +80 -0
- package/dist/website/Timeline/Timeline.js +99 -0
- package/dist/website/Timeline/Timeline.js.map +1 -0
- package/dist/website/index.d.ts +27 -0
- package/dist/website/index.js +21 -0
- package/dist/website/index.js.map +1 -0
- package/dist/website-actions.css +6 -0
- package/dist/website-base.css +46 -0
- package/dist/website-collection.css +89 -0
- package/dist/website-contact.css +29 -0
- package/dist/website-content.css +17 -0
- package/dist/website-controls.css +91 -0
- package/dist/website-conversation.css +115 -0
- package/dist/website-evidence.css +56 -0
- package/dist/website-media.css +227 -0
- package/dist/website-metrics.css +15 -0
- package/dist/website-music.css +27 -0
- package/dist/website-portfolio.css +94 -0
- package/dist/website-reading.css +159 -0
- package/dist/website-recovery.css +28 -0
- package/dist/website-search.css +26 -0
- package/dist/website-shell.css +89 -0
- package/dist/website-timeline.css +43 -0
- package/dist/website.css +25 -0
- package/llms.txt +35 -0
- package/package.json +163 -5
- package/skills/folio-design/SKILL.md +228 -0
- package/skills/folio-design/evals/claims.json +95 -0
- package/skills/folio-design/evals/evals.json +84 -0
- package/skills/folio-design/rules/a11y.md +167 -0
- package/skills/folio-design/rules/composition.md +108 -0
- package/skills/folio-design/rules/forms.md +135 -0
- package/skills/folio-design/rules/naming.md +155 -0
- package/skills/folio-design/rules/tokens.md +133 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
function Skeleton({ className, ...rest }) {
|
|
4
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: cn("h-3 bg-(--stone)", className), ...rest });
|
|
5
|
+
}
|
|
6
|
+
function SkeletonLine({ className, ...rest }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Skeleton, { className: cn("h-3 rounded-(--radius-pill)", className), ...rest });
|
|
8
|
+
}
|
|
9
|
+
function SkeletonBlock({ className, ...rest }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(Skeleton, { className: cn("rounded-(--radius-sm)", className), ...rest });
|
|
11
|
+
}
|
|
12
|
+
function SkeletonCircle({ className, ...rest }) {
|
|
13
|
+
return /* @__PURE__ */ jsx(Skeleton, { className: cn("size-9 rounded-full", className), ...rest });
|
|
14
|
+
}
|
|
15
|
+
function SkeletonText({ lines = 3, className, ...rest }) {
|
|
16
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2.5", className), ...rest, children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx(SkeletonLine, { className: index === lines - 1 ? "w-[62%]" : "w-full" }, index)) });
|
|
17
|
+
}
|
|
18
|
+
function SkeletonPage({ label, children, className, ...rest }) {
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
"div",
|
|
21
|
+
{
|
|
22
|
+
role: "status",
|
|
23
|
+
"aria-busy": "true",
|
|
24
|
+
"data-folio-animated": true,
|
|
25
|
+
className: cn("animate-pulse motion-reduce:animate-none", className),
|
|
26
|
+
...rest,
|
|
27
|
+
children: [
|
|
28
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: label }),
|
|
29
|
+
children
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
var Skeleton_default = Skeleton;
|
|
35
|
+
export {
|
|
36
|
+
Skeleton,
|
|
37
|
+
SkeletonBlock,
|
|
38
|
+
SkeletonCircle,
|
|
39
|
+
SkeletonLine,
|
|
40
|
+
SkeletonPage,
|
|
41
|
+
SkeletonText,
|
|
42
|
+
Skeleton_default as default
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=Skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport type SkeletonProps = HTMLAttributes<HTMLDivElement>\n\n/**\n * The fill every skeleton part is drawn from: `--stone`, at the height of one\n * line until something says otherwise.\n *\n * Deliberately NOT a shimmer. A shimmer sweeps a highlight across the shape,\n * which implies a light source; the White Reset has none, so the sweep reads as\n * a bug rather than as loading. The whole page breathes together instead —\n * see `SkeletonPage`, which owns the single pulse.\n *\n * `h-3` is a default rather than a design. A `<div>` is already full width, so\n * height was the one dimension a caller could omit and get nothing for — a\n * bare `<Skeleton />` was a zero-height box, which is not a small skeleton but\n * an absent one. Twelve pixels is the height `SkeletonLine` already chose, and\n * any class the caller passes replaces it.\n *\n * @example\n * <Skeleton className=\"h-3 w-40 rounded-(--radius-pill)\" />\n */\nexport function Skeleton({ className, ...rest }: SkeletonProps) {\n return <div aria-hidden=\"true\" className={cn('h-3 bg-(--stone)', className)} {...rest} />\n}\n\n/** A line of type. Height is the line's; width is how far it runs. */\nexport function SkeletonLine({ className, ...rest }: SkeletonProps) {\n return <Skeleton className={cn('h-3 rounded-(--radius-pill)', className)} {...rest} />\n}\n\n/** A block: an image mount, a plate, a chart. */\nexport function SkeletonBlock({ className, ...rest }: SkeletonProps) {\n return <Skeleton className={cn('rounded-(--radius-sm)', className)} {...rest} />\n}\n\n/** A circle: an avatar, a marker. */\nexport function SkeletonCircle({ className, ...rest }: SkeletonProps) {\n return <Skeleton className={cn('size-9 rounded-full', className)} {...rest} />\n}\n\nexport interface SkeletonTextProps extends SkeletonProps {\n /** How many lines of prose to stand in for. */\n lines?: number\n}\n\n/**\n * A paragraph.\n *\n * The last line is short, because real prose ends mid-measure. A block of equal\n * full-width bars reads as a table, and the reader then flinches when a\n * paragraph arrives instead.\n */\nexport function SkeletonText({ lines = 3, className, ...rest }: SkeletonTextProps) {\n return (\n <div className={cn('flex flex-col gap-2.5', className)} {...rest}>\n {Array.from({ length: lines }, (_, index) => (\n <SkeletonLine key={index} className={index === lines - 1 ? 'w-[62%]' : 'w-full'} />\n ))}\n </div>\n )\n}\n\nexport interface SkeletonPageProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * What is loading, in words. Announced once; the shapes themselves are\n * `aria-hidden`, so this sentence is the entire experience for a screen\n * reader and \"Loading\" alone tells it nothing.\n */\n label: string\n children: ReactNode\n}\n\n/**\n * The frame a skeleton sits in: the live region, and the single pulse.\n *\n * One `animate-pulse` on the wrapper rather than one per part, so the page\n * breathes together instead of shimmering out of phase — twenty independently\n * animated bars is a visual noise floor, not a loading state.\n *\n * A skeleton whose shape does not match what replaces it is worse than none: it\n * promises a layout and then the page jumps out from under the reader. Compose\n * the parts to match the real thing, and change both together.\n *\n * @example\n * <SkeletonPage label=\"Loading projects\">\n * <SkeletonLine className=\"h-2.5 w-28\" />\n * <SkeletonBlock className=\"mt-6 h-40\" />\n * </SkeletonPage>\n */\nexport function SkeletonPage({ label, children, className, ...rest }: SkeletonPageProps) {\n return (\n <div\n role=\"status\"\n aria-busy=\"true\"\n data-folio-animated\n className={cn('animate-pulse motion-reduce:animate-none', className)}\n {...rest}\n >\n <span className=\"sr-only\">{label}</span>\n {children}\n </div>\n )\n}\n\nexport default Skeleton\n"],"mappings":"AAwBS,cAqEL,YArEK;AAvBT,SAAS,UAAU;AAsBZ,SAAS,SAAS,EAAE,WAAW,GAAG,KAAK,GAAkB;AAC9D,SAAO,oBAAC,SAAI,eAAY,QAAO,WAAW,GAAG,oBAAoB,SAAS,GAAI,GAAG,MAAM;AACzF;AAGO,SAAS,aAAa,EAAE,WAAW,GAAG,KAAK,GAAkB;AAClE,SAAO,oBAAC,YAAS,WAAW,GAAG,+BAA+B,SAAS,GAAI,GAAG,MAAM;AACtF;AAGO,SAAS,cAAc,EAAE,WAAW,GAAG,KAAK,GAAkB;AACnE,SAAO,oBAAC,YAAS,WAAW,GAAG,yBAAyB,SAAS,GAAI,GAAG,MAAM;AAChF;AAGO,SAAS,eAAe,EAAE,WAAW,GAAG,KAAK,GAAkB;AACpE,SAAO,oBAAC,YAAS,WAAW,GAAG,uBAAuB,SAAS,GAAI,GAAG,MAAM;AAC9E;AAcO,SAAS,aAAa,EAAE,QAAQ,GAAG,WAAW,GAAG,KAAK,GAAsB;AACjF,SACE,oBAAC,SAAI,WAAW,GAAG,yBAAyB,SAAS,GAAI,GAAG,MACzD,gBAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,UACjC,oBAAC,gBAAyB,WAAW,UAAU,QAAQ,IAAI,YAAY,YAApD,KAA8D,CAClF,GACH;AAEJ;AA6BO,SAAS,aAAa,EAAE,OAAO,UAAU,WAAW,GAAG,KAAK,GAAsB;AACvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,uBAAmB;AAAA,MACnB,WAAW,GAAG,4CAA4C,SAAS;AAAA,MAClE,GAAG;AAAA,MAEJ;AAAA,4BAAC,UAAK,WAAU,WAAW,iBAAM;AAAA,QAChC;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,mBAAQ;","names":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
4
|
+
|
|
5
|
+
interface SliderProps extends ComponentProps<typeof SliderPrimitive.Root> {
|
|
6
|
+
/**
|
|
7
|
+
* Names the control. Required: a slider with no name announces only a number,
|
|
8
|
+
* and a number with no noun is not information.
|
|
9
|
+
*
|
|
10
|
+
* A range slider (two thumbs) needs one name per thumb — pass an array.
|
|
11
|
+
*/
|
|
12
|
+
label: string | [string, string];
|
|
13
|
+
/**
|
|
14
|
+
* Prints the current value beside the label.
|
|
15
|
+
*
|
|
16
|
+
* A two-thumb range prints both names and both values, in the same order —
|
|
17
|
+
* the heading used to print the first name over a pair of numbers, which read
|
|
18
|
+
* as "Minimum" over "10 – 90".
|
|
19
|
+
*/
|
|
20
|
+
showValue?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Turns that readout into a box the number can be typed into, and implies
|
|
23
|
+
* `showValue`.
|
|
24
|
+
*
|
|
25
|
+
* A slider is a control for a NEIGHBOURHOOD; someone who needs 1,150 rather
|
|
26
|
+
* than roughly 1,200 is dragging a 16px thumb across a hundred steps to get
|
|
27
|
+
* it. This is the way out, in the place the value already is, rather than a
|
|
28
|
+
* second field beside the track that has to be kept in step by hand.
|
|
29
|
+
*
|
|
30
|
+
* The box shows `format`'s output at rest and the bare number while it has
|
|
31
|
+
* focus, so a reader still sees "$1,200" and a typist is never asked to type
|
|
32
|
+
* a currency symbol back.
|
|
33
|
+
*/
|
|
34
|
+
editable?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Renders the value with a unit or a currency, e.g. `(n) => n + '%'`.
|
|
37
|
+
*
|
|
38
|
+
* Reaches assistive tech as well as the readout: it becomes each thumb's
|
|
39
|
+
* `aria-valuetext`, so a thumb showing "$1,200" announces that rather than the
|
|
40
|
+
* bare number. Left off, the platform announces the value itself.
|
|
41
|
+
*/
|
|
42
|
+
format?: (value: number) => string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A value chosen along a range.
|
|
46
|
+
*
|
|
47
|
+
* Radix owns the keyboard contract — arrows step, Page keys jump, Home and End
|
|
48
|
+
* reach the ends — and the ARIA that reports the value. What is here is the
|
|
49
|
+
* look, and the labelling, which is the part a slider most often gets wrong: a
|
|
50
|
+
* thumb that announces "42" and nothing else leaves a screen reader user with a
|
|
51
|
+
* number and no idea what it measures.
|
|
52
|
+
*
|
|
53
|
+
* A 44px hit area sits invisibly around the 16px thumb, because a thumb sized
|
|
54
|
+
* for the design is well under any pointer-target guideline.
|
|
55
|
+
*
|
|
56
|
+
* `editable` is the answer to the thing a slider cannot do. Reach for it
|
|
57
|
+
* whenever the exact figure is the point — a budget, a timeout, a price — and
|
|
58
|
+
* leave it off when the value is genuinely approximate, because a box invites
|
|
59
|
+
* precision the setting may not have.
|
|
60
|
+
*
|
|
61
|
+
* Inside a `Field`, the hint, the error and the requirement land on the THUMB,
|
|
62
|
+
* which is the element carrying `role="slider"` — on the root they would sit on
|
|
63
|
+
* a `<span>` with no role and announce nothing. The NAME still comes from
|
|
64
|
+
* `label` here: a field's label above a slider points at that same roleless
|
|
65
|
+
* root, so it neither names the control nor clicks through to it.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* <Slider label="Quality" defaultValue={[80]} max={100} step={5} showValue format={(n) => `${n}%`} />
|
|
69
|
+
* @example
|
|
70
|
+
* <Slider label="Monthly budget" defaultValue={[1200]} max={5000} step={50} editable format={(n) => `$${n}`} />
|
|
71
|
+
*/
|
|
72
|
+
declare function Slider({ label, showValue, editable, format, className, onValueChange, value: controlledValue, defaultValue, min, max, step, 'aria-describedby': describedBy, 'aria-required': ariaRequired, 'aria-invalid': ariaInvalid, ...props }: SliderProps): react.JSX.Element;
|
|
73
|
+
|
|
74
|
+
export { Slider, type SliderProps, Slider as default };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
4
|
+
import { Fragment, useRef, useState } from "react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { clampToRange, parseNumber, snapToStep } from "../../lib/numeric.js";
|
|
7
|
+
import { warnBlankName } from "../../lib/warn.js";
|
|
8
|
+
function Slider({
|
|
9
|
+
label,
|
|
10
|
+
showValue = false,
|
|
11
|
+
editable = false,
|
|
12
|
+
format,
|
|
13
|
+
className,
|
|
14
|
+
onValueChange,
|
|
15
|
+
value: controlledValue,
|
|
16
|
+
defaultValue,
|
|
17
|
+
min = 0,
|
|
18
|
+
max = 100,
|
|
19
|
+
step = 1,
|
|
20
|
+
"aria-describedby": describedBy,
|
|
21
|
+
"aria-required": ariaRequired,
|
|
22
|
+
"aria-invalid": ariaInvalid,
|
|
23
|
+
...props
|
|
24
|
+
}) {
|
|
25
|
+
const names = Array.isArray(label) ? label : [label];
|
|
26
|
+
warnBlankName("Slider", "label", names[0], "the thumb is announced with no name and its value describes nothing");
|
|
27
|
+
const [uncontrolled, setUncontrolled] = useState(defaultValue ?? [min]);
|
|
28
|
+
const current = controlledValue ?? uncontrolled;
|
|
29
|
+
const [draft, setDraft] = useState(null);
|
|
30
|
+
const draftRef = useRef(null);
|
|
31
|
+
const edit = (next) => {
|
|
32
|
+
draftRef.current = next;
|
|
33
|
+
setDraft(next);
|
|
34
|
+
};
|
|
35
|
+
const handleChange = (next) => {
|
|
36
|
+
if (controlledValue === void 0) setUncontrolled(next);
|
|
37
|
+
onValueChange?.(next);
|
|
38
|
+
};
|
|
39
|
+
const commit = (index, text) => {
|
|
40
|
+
const parsed = parseNumber(text);
|
|
41
|
+
if (parsed === null) return false;
|
|
42
|
+
const lower = index > 0 ? current[index - 1] ?? min : min;
|
|
43
|
+
const upper = index < current.length - 1 ? current[index + 1] ?? max : max;
|
|
44
|
+
const next = clampToRange(snapToStep(parsed, step, min), Math.max(min, lower), Math.min(max, upper));
|
|
45
|
+
if (next !== current[index]) handleChange(current.map((value, i) => i === index ? next : value));
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
const print = format ?? String;
|
|
49
|
+
const heading = names.length > 1 ? current.map((_, index) => names[index] ?? names[0]).join(" \u2013 ") : names[0];
|
|
50
|
+
const readout = showValue || editable;
|
|
51
|
+
return /* @__PURE__ */ jsxs(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
className: cn(
|
|
55
|
+
"flex w-full flex-col gap-3",
|
|
56
|
+
// On the wrapper, and driven by the prop: the thumb is a <span>, so a
|
|
57
|
+
// `disabled:` variant compiles to `&:disabled` and matches nothing —
|
|
58
|
+
// the control was drawn exactly like a live one while refusing to move.
|
|
59
|
+
// The wrapper is also what dims the readout above the track.
|
|
60
|
+
props.disabled && "opacity-(--disabled-opacity) pointer-events-none",
|
|
61
|
+
className
|
|
62
|
+
),
|
|
63
|
+
children: [
|
|
64
|
+
readout && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-4 mono-meta text-(--ink-3-aa)", children: [
|
|
65
|
+
/* @__PURE__ */ jsx("span", { children: heading }),
|
|
66
|
+
editable ? /* @__PURE__ */ jsx("span", { className: "flex items-baseline gap-1.5", children: current.map((value, index) => {
|
|
67
|
+
const editing = draft?.index === index;
|
|
68
|
+
const text = editing ? draft.text : print(value);
|
|
69
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
+
index > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2013" }),
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"input",
|
|
73
|
+
{
|
|
74
|
+
type: "text",
|
|
75
|
+
inputMode: "decimal",
|
|
76
|
+
disabled: props.disabled,
|
|
77
|
+
value: text,
|
|
78
|
+
"aria-label": `${names[index] ?? names[0]}, exact value`,
|
|
79
|
+
"aria-describedby": describedBy,
|
|
80
|
+
"aria-required": ariaRequired,
|
|
81
|
+
"aria-invalid": editing && parseNumber(draft.text) === null || ariaInvalid || void 0,
|
|
82
|
+
onFocus: () => edit({ index, text: String(value) }),
|
|
83
|
+
onChange: (event) => edit({ index, text: event.target.value }),
|
|
84
|
+
onBlur: () => {
|
|
85
|
+
const pending = draftRef.current;
|
|
86
|
+
if (pending?.index === index) commit(index, pending.text);
|
|
87
|
+
edit(null);
|
|
88
|
+
},
|
|
89
|
+
onKeyDown: (event) => {
|
|
90
|
+
const pending = draftRef.current;
|
|
91
|
+
if (event.key === "Enter") {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
if (pending?.index === index && commit(index, pending.text)) edit(null);
|
|
94
|
+
}
|
|
95
|
+
if (event.key === "Escape") {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
edit(null);
|
|
98
|
+
event.currentTarget.blur();
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
className: "w-20 rounded-(--radius-sm) border border-(--rule-2) bg-(--paper) px-1.5 py-0.5 text-end tabular-nums text-(--ink) transition-colors duration-(--duration-fast) hover:border-(--rule-hard) focus:border-(--ink) aria-invalid:border-(--danger)"
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
] }, index);
|
|
105
|
+
}) }) : /* @__PURE__ */ jsx("span", { className: "tabular-nums text-(--ink)", children: current.map((value) => print(value)).join(" \u2013 ") })
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsxs(
|
|
108
|
+
SliderPrimitive.Root,
|
|
109
|
+
{
|
|
110
|
+
className: "group relative flex w-full touch-none select-none items-center py-3",
|
|
111
|
+
value: current,
|
|
112
|
+
min,
|
|
113
|
+
max,
|
|
114
|
+
step,
|
|
115
|
+
onValueChange: handleChange,
|
|
116
|
+
...props,
|
|
117
|
+
children: [
|
|
118
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Track, { className: "relative h-1 w-full grow overflow-hidden rounded-(--radius-pill) bg-(--stone) transition-[height] duration-(--duration-fast) group-hover:h-1.5", children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: "absolute h-full bg-(--accent)" }) }),
|
|
119
|
+
current.map((value, index) => /* @__PURE__ */ jsx(
|
|
120
|
+
SliderPrimitive.Thumb,
|
|
121
|
+
{
|
|
122
|
+
"aria-label": names[index] ?? names[0],
|
|
123
|
+
"aria-describedby": describedBy,
|
|
124
|
+
"aria-required": ariaRequired,
|
|
125
|
+
"aria-invalid": ariaInvalid,
|
|
126
|
+
"aria-valuetext": format ? format(value) : void 0,
|
|
127
|
+
className: "relative block size-4 rounded-(--radius-pill) border border-(--accent) bg-(--paper) transition-[transform,background-color] duration-(--duration-fast) ease-(--ease-out-expo) before:absolute before:left-1/2 before:top-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] hover:scale-110 hover:bg-(--stone) active:scale-125 data-[state=active]:scale-125 motion-reduce:transition-none"
|
|
128
|
+
},
|
|
129
|
+
index
|
|
130
|
+
))
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
var Slider_default = Slider;
|
|
139
|
+
export {
|
|
140
|
+
Slider,
|
|
141
|
+
Slider_default as default
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=Slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["'use client'\n\nimport * as SliderPrimitive from '@radix-ui/react-slider'\nimport { Fragment, useRef, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { clampToRange, parseNumber, snapToStep } from '../../lib/numeric'\nimport { warnBlankName } from '../../lib/warn'\n\nexport interface SliderProps extends ComponentProps<typeof SliderPrimitive.Root> {\n /**\n * Names the control. Required: a slider with no name announces only a number,\n * and a number with no noun is not information.\n *\n * A range slider (two thumbs) needs one name per thumb — pass an array.\n */\n label: string | [string, string]\n /**\n * Prints the current value beside the label.\n *\n * A two-thumb range prints both names and both values, in the same order —\n * the heading used to print the first name over a pair of numbers, which read\n * as \"Minimum\" over \"10 – 90\".\n */\n showValue?: boolean\n /**\n * Turns that readout into a box the number can be typed into, and implies\n * `showValue`.\n *\n * A slider is a control for a NEIGHBOURHOOD; someone who needs 1,150 rather\n * than roughly 1,200 is dragging a 16px thumb across a hundred steps to get\n * it. This is the way out, in the place the value already is, rather than a\n * second field beside the track that has to be kept in step by hand.\n *\n * The box shows `format`'s output at rest and the bare number while it has\n * focus, so a reader still sees \"$1,200\" and a typist is never asked to type\n * a currency symbol back.\n */\n editable?: boolean\n /**\n * Renders the value with a unit or a currency, e.g. `(n) => n + '%'`.\n *\n * Reaches assistive tech as well as the readout: it becomes each thumb's\n * `aria-valuetext`, so a thumb showing \"$1,200\" announces that rather than the\n * bare number. Left off, the platform announces the value itself.\n */\n format?: (value: number) => string\n}\n\n/** Which box is being typed into, and what is in it. Only one can have focus. */\ninterface Draft {\n index: number\n text: string\n}\n\n/**\n * A value chosen along a range.\n *\n * Radix owns the keyboard contract — arrows step, Page keys jump, Home and End\n * reach the ends — and the ARIA that reports the value. What is here is the\n * look, and the labelling, which is the part a slider most often gets wrong: a\n * thumb that announces \"42\" and nothing else leaves a screen reader user with a\n * number and no idea what it measures.\n *\n * A 44px hit area sits invisibly around the 16px thumb, because a thumb sized\n * for the design is well under any pointer-target guideline.\n *\n * `editable` is the answer to the thing a slider cannot do. Reach for it\n * whenever the exact figure is the point — a budget, a timeout, a price — and\n * leave it off when the value is genuinely approximate, because a box invites\n * precision the setting may not have.\n *\n * Inside a `Field`, the hint, the error and the requirement land on the THUMB,\n * which is the element carrying `role=\"slider\"` — on the root they would sit on\n * a `<span>` with no role and announce nothing. The NAME still comes from\n * `label` here: a field's label above a slider points at that same roleless\n * root, so it neither names the control nor clicks through to it.\n *\n * @example\n * <Slider label=\"Quality\" defaultValue={[80]} max={100} step={5} showValue format={(n) => `${n}%`} />\n * @example\n * <Slider label=\"Monthly budget\" defaultValue={[1200]} max={5000} step={50} editable format={(n) => `$${n}`} />\n */\nexport function Slider({\n label,\n showValue = false,\n editable = false,\n format,\n className,\n onValueChange,\n value: controlledValue,\n defaultValue,\n min = 0,\n max = 100,\n step = 1,\n 'aria-describedby': describedBy,\n 'aria-required': ariaRequired,\n 'aria-invalid': ariaInvalid,\n ...props\n}: SliderProps) {\n const names = Array.isArray(label) ? label : [label]\n\n // The other five guarded naming props are plain strings; this one is a\n // string or a pair, so the first name is what is checked — a range whose\n // lower thumb has no name is the same silence as a single one with none.\n // It catches a blank, not an absent: `label` is required, so a missing one\n // is a type error everywhere except a caller that has already left the\n // types behind.\n warnBlankName('Slider', 'label', names[0], 'the thumb is announced with no name and its value describes nothing')\n\n // Tracked here, not read off the props. An uncontrolled slider's\n // `defaultValue` never changes, so the printed figure sat at its starting\n // number while the thumb moved — the one thing `showValue` exists to avoid.\n //\n // The fallback is the primitive's own — one thumb at the minimum. The thumbs\n // are rendered from THIS array rather than from Radix's, so an empty one is a\n // track with nothing on it to drag, which is what `<Slider label=\"Volume\" />`\n // used to render.\n const [uncontrolled, setUncontrolled] = useState<number[]>(defaultValue ?? [min])\n const current = controlledValue ?? uncontrolled\n\n // Mirrored into a ref because Escape clears the draft and blurs the box in\n // the SAME event: the state update has not been applied by the time the\n // blur handler runs, so a handler reading the state variable would see the\n // abandoned text and commit exactly what Escape was pressed to discard.\n const [draft, setDraft] = useState<Draft | null>(null)\n const draftRef = useRef<Draft | null>(null)\n const edit = (next: Draft | null) => {\n draftRef.current = next\n setDraft(next)\n }\n\n const handleChange = (next: number[]) => {\n if (controlledValue === undefined) setUncontrolled(next)\n onValueChange?.(next)\n }\n\n /**\n * Commits one typed box, or reports that there was no number in it.\n *\n * A thumb is also bounded by its NEIGHBOURS, which is the bound a typed\n * value can cross and a dragged one cannot: typing 90 into the lower end of a\n * range whose upper end is at 70 would otherwise hand Radix an unsorted array\n * and leave the two thumbs crossed over.\n */\n const commit = (index: number, text: string): boolean => {\n const parsed = parseNumber(text)\n if (parsed === null) return false\n const lower = index > 0 ? (current[index - 1] ?? min) : min\n const upper = index < current.length - 1 ? (current[index + 1] ?? max) : max\n const next = clampToRange(snapToStep(parsed, step, min), Math.max(min, lower), Math.min(max, upper))\n if (next !== current[index]) handleChange(current.map((value, i) => (i === index ? next : value)))\n return true\n }\n\n const print = format ?? String\n // One name per thumb, in the thumbs' own order, so the heading lines up with\n // the numbers under it. A single name stays a single name however many thumbs\n // there are — a price filter called \"Price\" is not \"Price – Price\".\n const heading =\n names.length > 1 ? current.map((_, index) => names[index] ?? names[0]).join(' – ') : names[0]\n\n const readout = showValue || editable\n\n return (\n <div\n className={cn(\n 'flex w-full flex-col gap-3',\n // On the wrapper, and driven by the prop: the thumb is a <span>, so a\n // `disabled:` variant compiles to `&:disabled` and matches nothing —\n // the control was drawn exactly like a live one while refusing to move.\n // The wrapper is also what dims the readout above the track.\n props.disabled && 'opacity-(--disabled-opacity) pointer-events-none',\n className,\n )}\n >\n {readout && (\n <div className=\"flex items-baseline justify-between gap-4 mono-meta text-(--ink-3-aa)\">\n <span>{heading}</span>\n {editable ? (\n <span className=\"flex items-baseline gap-1.5\">\n {current.map((value, index) => {\n const editing = draft?.index === index\n const text = editing ? draft.text : print(value)\n return (\n <Fragment key={index}>\n {index > 0 && <span aria-hidden=\"true\">–</span>}\n <input\n type=\"text\"\n // Not `type=\"number\"`: the box holds `format`'s output at\n // rest — \"$1,200\" — which a number input refuses to\n // display and silently blanks. `inputMode` is what still\n // brings up the numeric keypad on a phone.\n inputMode=\"decimal\"\n // `disabled` on the wrapper is `pointer-events-none`,\n // which a keyboard walks straight past. Without this, the\n // one editable part of a disabled slider stays editable.\n disabled={props.disabled}\n value={text}\n // The name has to differ from the thumb's: both carry the\n // same value, and two controls announcing \"Quality\" is a\n // reader hearing the same control twice.\n aria-label={`${names[index] ?? names[0]}, exact value`}\n aria-describedby={describedBy}\n aria-required={ariaRequired}\n aria-invalid={(editing && parseNumber(draft.text) === null) || ariaInvalid || undefined}\n onFocus={() => edit({ index, text: String(value) })}\n onChange={(event) => edit({ index, text: event.target.value })}\n onBlur={() => {\n const pending = draftRef.current\n if (pending?.index === index) commit(index, pending.text)\n edit(null)\n }}\n onKeyDown={(event) => {\n const pending = draftRef.current\n if (event.key === 'Enter') {\n event.preventDefault()\n if (pending?.index === index && commit(index, pending.text)) edit(null)\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n edit(null)\n event.currentTarget.blur()\n }\n }}\n className=\"w-20 rounded-(--radius-sm) border border-(--rule-2) bg-(--paper) px-1.5 py-0.5 text-end tabular-nums text-(--ink) transition-colors duration-(--duration-fast) hover:border-(--rule-hard) focus:border-(--ink) aria-invalid:border-(--danger)\"\n />\n </Fragment>\n )\n })}\n </span>\n ) : (\n <span className=\"tabular-nums text-(--ink)\">\n {current.map((value) => print(value)).join(' – ')}\n </span>\n )}\n </div>\n )}\n {/* Controlled from THIS component's state even when the caller left it\n uncontrolled, because the thumbs have to answer to more than dragging:\n a number typed into the readout never passes through Radix, so a Root\n holding its own `defaultValue` would keep the thumb where it was and\n leave the figure above it disagreeing with the track. `min`, `max` and\n `step` are passed on rather than spread for the same reason — the\n typed value is reconciled against them here. */}\n <SliderPrimitive.Root\n className=\"group relative flex w-full touch-none select-none items-center py-3\"\n value={current}\n min={min}\n max={max}\n step={step}\n onValueChange={handleChange}\n {...props}\n >\n <SliderPrimitive.Track className=\"relative h-1 w-full grow overflow-hidden rounded-(--radius-pill) bg-(--stone) transition-[height] duration-(--duration-fast) group-hover:h-1.5\">\n <SliderPrimitive.Range className=\"absolute h-full bg-(--accent)\" />\n </SliderPrimitive.Track>\n {current.map((value, index) => (\n <SliderPrimitive.Thumb\n key={index}\n aria-label={names[index] ?? names[0]}\n // The thumb is what carries role=\"slider\", so this is where a\n // Field's description and requirement have to land — on the root\n // they sit on a <span> with no role, which announces nothing.\n aria-describedby={describedBy}\n aria-required={ariaRequired}\n aria-invalid={ariaInvalid}\n // Only when a format was given: setting it otherwise would replace\n // the platform's own reading of the value with the same digits.\n aria-valuetext={format ? format(value) : undefined}\n // The visible thumb is 16px; the `before` pseudo-element widens the\n // hit area to 44px without changing what is drawn.\n // `transition-transform` and not `all`: the thumb's own position is\n // set by Radix as a `left` percentage, and transitioning that would\n // make it lag the pointer. Only the grow-on-grab is animated.\n className=\"relative block size-4 rounded-(--radius-pill) border border-(--accent) bg-(--paper) transition-[transform,background-color] duration-(--duration-fast) ease-(--ease-out-expo) before:absolute before:left-1/2 before:top-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] hover:scale-110 hover:bg-(--stone) active:scale-125 data-[state=active]:scale-125 motion-reduce:transition-none\"\n />\n ))}\n </SliderPrimitive.Root>\n </div>\n )\n}\n\nexport default Slider\n"],"mappings":";AAiLU,cAOQ,YAPR;AA/KV,YAAY,qBAAqB;AACjC,SAAS,UAAU,QAAQ,gBAAqC;AAChE,SAAS,UAAU;AACnB,SAAS,cAAc,aAAa,kBAAkB;AACtD,SAAS,qBAAqB;AA4EvB,SAAS,OAAO;AAAA,EACrB;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,GAAG;AACL,GAAgB;AACd,QAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAQnD,gBAAc,UAAU,SAAS,MAAM,CAAC,GAAG,qEAAqE;AAUhH,QAAM,CAAC,cAAc,eAAe,IAAI,SAAmB,gBAAgB,CAAC,GAAG,CAAC;AAChF,QAAM,UAAU,mBAAmB;AAMnC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,WAAW,OAAqB,IAAI;AAC1C,QAAM,OAAO,CAAC,SAAuB;AACnC,aAAS,UAAU;AACnB,aAAS,IAAI;AAAA,EACf;AAEA,QAAM,eAAe,CAAC,SAAmB;AACvC,QAAI,oBAAoB,OAAW,iBAAgB,IAAI;AACvD,oBAAgB,IAAI;AAAA,EACtB;AAUA,QAAM,SAAS,CAAC,OAAe,SAA0B;AACvD,UAAM,SAAS,YAAY,IAAI;AAC/B,QAAI,WAAW,KAAM,QAAO;AAC5B,UAAM,QAAQ,QAAQ,IAAK,QAAQ,QAAQ,CAAC,KAAK,MAAO;AACxD,UAAM,QAAQ,QAAQ,QAAQ,SAAS,IAAK,QAAQ,QAAQ,CAAC,KAAK,MAAO;AACzE,UAAM,OAAO,aAAa,WAAW,QAAQ,MAAM,GAAG,GAAG,KAAK,IAAI,KAAK,KAAK,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC;AACnG,QAAI,SAAS,QAAQ,KAAK,EAAG,cAAa,QAAQ,IAAI,CAAC,OAAO,MAAO,MAAM,QAAQ,OAAO,KAAM,CAAC;AACjG,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,UAAU;AAIxB,QAAM,UACJ,MAAM,SAAS,IAAI,QAAQ,IAAI,CAAC,GAAG,UAAU,MAAM,KAAK,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,UAAK,IAAI,MAAM,CAAC;AAE9F,QAAM,UAAU,aAAa;AAE7B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,MAAM,YAAY;AAAA,QAClB;AAAA,MACF;AAAA,MAEC;AAAA,mBACC,qBAAC,SAAI,WAAU,yEACb;AAAA,8BAAC,UAAM,mBAAQ;AAAA,UACd,WACC,oBAAC,UAAK,WAAU,+BACb,kBAAQ,IAAI,CAAC,OAAO,UAAU;AAC7B,kBAAM,UAAU,OAAO,UAAU;AACjC,kBAAM,OAAO,UAAU,MAAM,OAAO,MAAM,KAAK;AAC/C,mBACE,qBAAC,YACE;AAAA,sBAAQ,KAAK,oBAAC,UAAK,eAAY,QAAO,oBAAC;AAAA,cACxC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBAKL,WAAU;AAAA,kBAIV,UAAU,MAAM;AAAA,kBAChB,OAAO;AAAA,kBAIP,cAAY,GAAG,MAAM,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,kBACvC,oBAAkB;AAAA,kBAClB,iBAAe;AAAA,kBACf,gBAAe,WAAW,YAAY,MAAM,IAAI,MAAM,QAAS,eAAe;AAAA,kBAC9E,SAAS,MAAM,KAAK,EAAE,OAAO,MAAM,OAAO,KAAK,EAAE,CAAC;AAAA,kBAClD,UAAU,CAAC,UAAU,KAAK,EAAE,OAAO,MAAM,MAAM,OAAO,MAAM,CAAC;AAAA,kBAC7D,QAAQ,MAAM;AACZ,0BAAM,UAAU,SAAS;AACzB,wBAAI,SAAS,UAAU,MAAO,QAAO,OAAO,QAAQ,IAAI;AACxD,yBAAK,IAAI;AAAA,kBACX;AAAA,kBACA,WAAW,CAAC,UAAU;AACpB,0BAAM,UAAU,SAAS;AACzB,wBAAI,MAAM,QAAQ,SAAS;AACzB,4BAAM,eAAe;AACrB,0BAAI,SAAS,UAAU,SAAS,OAAO,OAAO,QAAQ,IAAI,EAAG,MAAK,IAAI;AAAA,oBACxE;AACA,wBAAI,MAAM,QAAQ,UAAU;AAC1B,4BAAM,eAAe;AACrB,2BAAK,IAAI;AACT,4BAAM,cAAc,KAAK;AAAA,oBAC3B;AAAA,kBACF;AAAA,kBACA,WAAU;AAAA;AAAA,cACZ;AAAA,iBAzCa,KA0Cf;AAAA,UAEJ,CAAC,GACH,IAEA,oBAAC,UAAK,WAAU,6BACb,kBAAQ,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,KAAK,UAAK,GAClD;AAAA,WAEJ;AAAA,QASF;AAAA,UAAC,gBAAgB;AAAA,UAAhB;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,YACA,eAAe;AAAA,YACd,GAAG;AAAA,YAEJ;AAAA,kCAAC,gBAAgB,OAAhB,EAAsB,WAAU,kJAC/B,8BAAC,gBAAgB,OAAhB,EAAsB,WAAU,iCAAgC,GACnE;AAAA,cACC,QAAQ,IAAI,CAAC,OAAO,UACnB;AAAA,gBAAC,gBAAgB;AAAA,gBAAhB;AAAA,kBAEC,cAAY,MAAM,KAAK,KAAK,MAAM,CAAC;AAAA,kBAInC,oBAAkB;AAAA,kBAClB,iBAAe;AAAA,kBACf,gBAAc;AAAA,kBAGd,kBAAgB,SAAS,OAAO,KAAK,IAAI;AAAA,kBAMzC,WAAU;AAAA;AAAA,gBAhBL;AAAA,cAiBP,CACD;AAAA;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,iBAAQ;","names":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
/** 14px / 18px / 26px. Match the size of the type it sits beside. */
|
|
6
|
+
size?: 'sm' | 'md' | 'lg';
|
|
7
|
+
/**
|
|
8
|
+
* `default` draws the ring against the page — a hairline track in the rule
|
|
9
|
+
* colour with the leading quarter in ink. `current` draws it in the inherited
|
|
10
|
+
* text colour, which is what a spinner inside a filled button needs: on an
|
|
11
|
+
* ink ground an ink ring is invisible.
|
|
12
|
+
*/
|
|
13
|
+
tone?: 'default' | 'current';
|
|
14
|
+
/** Merged onto the RING, after `size` and `tone`, so it overrides both. */
|
|
15
|
+
className?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Announced to assistive tech. Pass the specific thing being waited on
|
|
18
|
+
* ("Loading projects"), not the generic word — a screen reader user hearing
|
|
19
|
+
* "Loading" three times cannot tell which three things.
|
|
20
|
+
*
|
|
21
|
+
* Pass `null` for a spinner that sits inside a control which already names
|
|
22
|
+
* the operation (a button whose own label changes to "Saving…"), so the two
|
|
23
|
+
* are not read out twice.
|
|
24
|
+
*/
|
|
25
|
+
label?: string | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The system's one "working" indicator.
|
|
29
|
+
*
|
|
30
|
+
* A ring, not a blurred glow and not a shimmer: the White Reset has no light
|
|
31
|
+
* source, so depth and softness are not available to it. The leading quarter is
|
|
32
|
+
* the only thing that distinguishes the ring from a plain circle, which is why
|
|
33
|
+
* the track stays a hairline — a spinner is a hint that time is passing, not a
|
|
34
|
+
* feature of the page.
|
|
35
|
+
*
|
|
36
|
+
* It spins under `motion-safe` only. A reader who has asked for less motion
|
|
37
|
+
* gets a static ring, which still reads as "not finished" because the leading
|
|
38
|
+
* quarter is darker than the track.
|
|
39
|
+
*
|
|
40
|
+
* For a wait long enough that the reader would otherwise wonder whether the
|
|
41
|
+
* page is broken, prefer `Skeleton` — a shape that describes what is coming
|
|
42
|
+
* beats a dot that describes nothing.
|
|
43
|
+
*
|
|
44
|
+
* `className` reaches the RING, alongside `size` and `tone`, and overrides
|
|
45
|
+
* them: every utility a caller has for a spinner is about the ring, and merged
|
|
46
|
+
* onto the wrapper instead `className="size-8"` grew an invisible box around an
|
|
47
|
+
* unchanged 18px circle. Layout still works from there — the wrapper is
|
|
48
|
+
* `inline-flex` and takes the ring's margin box as its own.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* <Spinner size="lg" label="Loading projects" />
|
|
52
|
+
* @example
|
|
53
|
+
* // Inside a filled button, where the ground is ink:
|
|
54
|
+
* <Spinner size="sm" tone="current" label={null} />
|
|
55
|
+
*/
|
|
56
|
+
declare function Spinner({ size, tone, className, label, ...rest }: SpinnerProps): react.JSX.Element;
|
|
57
|
+
|
|
58
|
+
export { Spinner, type SpinnerProps, Spinner as default };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
const SIZE = {
|
|
4
|
+
sm: "size-3.5 border-[1.5px]",
|
|
5
|
+
md: "size-[18px] border-2",
|
|
6
|
+
lg: "size-6.5 border-2"
|
|
7
|
+
};
|
|
8
|
+
const TONE = {
|
|
9
|
+
default: "border-(--rule-2) border-t-(--ink)",
|
|
10
|
+
current: "border-current/25 border-t-current"
|
|
11
|
+
};
|
|
12
|
+
function Spinner({
|
|
13
|
+
size = "md",
|
|
14
|
+
tone = "default",
|
|
15
|
+
className,
|
|
16
|
+
label = "Loading",
|
|
17
|
+
...rest
|
|
18
|
+
}) {
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
"span",
|
|
21
|
+
{
|
|
22
|
+
role: label === null ? void 0 : "status",
|
|
23
|
+
"aria-hidden": label === null ? true : void 0,
|
|
24
|
+
className: "inline-flex shrink-0 items-center justify-center",
|
|
25
|
+
...rest,
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"span",
|
|
29
|
+
{
|
|
30
|
+
"data-folio-animated": true,
|
|
31
|
+
className: cn(
|
|
32
|
+
"inline-block rounded-full border-solid motion-safe:animate-[folio-spin_0.7s_linear_infinite]",
|
|
33
|
+
SIZE[size],
|
|
34
|
+
TONE[tone],
|
|
35
|
+
className
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
label !== null && /* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
var Spinner_default = Spinner;
|
|
45
|
+
export {
|
|
46
|
+
Spinner,
|
|
47
|
+
Spinner_default as default
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=Spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Spinner/Spinner.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {\n /** 14px / 18px / 26px. Match the size of the type it sits beside. */\n size?: 'sm' | 'md' | 'lg'\n /**\n * `default` draws the ring against the page — a hairline track in the rule\n * colour with the leading quarter in ink. `current` draws it in the inherited\n * text colour, which is what a spinner inside a filled button needs: on an\n * ink ground an ink ring is invisible.\n */\n tone?: 'default' | 'current'\n /** Merged onto the RING, after `size` and `tone`, so it overrides both. */\n className?: string\n /**\n * Announced to assistive tech. Pass the specific thing being waited on\n * (\"Loading projects\"), not the generic word — a screen reader user hearing\n * \"Loading\" three times cannot tell which three things.\n *\n * Pass `null` for a spinner that sits inside a control which already names\n * the operation (a button whose own label changes to \"Saving…\"), so the two\n * are not read out twice.\n */\n label?: string | null\n}\n\nconst SIZE = {\n sm: 'size-3.5 border-[1.5px]',\n md: 'size-[18px] border-2',\n lg: 'size-6.5 border-2',\n} as const\n\nconst TONE = {\n default: 'border-(--rule-2) border-t-(--ink)',\n current: 'border-current/25 border-t-current',\n} as const\n\n/**\n * The system's one \"working\" indicator.\n *\n * A ring, not a blurred glow and not a shimmer: the White Reset has no light\n * source, so depth and softness are not available to it. The leading quarter is\n * the only thing that distinguishes the ring from a plain circle, which is why\n * the track stays a hairline — a spinner is a hint that time is passing, not a\n * feature of the page.\n *\n * It spins under `motion-safe` only. A reader who has asked for less motion\n * gets a static ring, which still reads as \"not finished\" because the leading\n * quarter is darker than the track.\n *\n * For a wait long enough that the reader would otherwise wonder whether the\n * page is broken, prefer `Skeleton` — a shape that describes what is coming\n * beats a dot that describes nothing.\n *\n * `className` reaches the RING, alongside `size` and `tone`, and overrides\n * them: every utility a caller has for a spinner is about the ring, and merged\n * onto the wrapper instead `className=\"size-8\"` grew an invisible box around an\n * unchanged 18px circle. Layout still works from there — the wrapper is\n * `inline-flex` and takes the ring's margin box as its own.\n *\n * @example\n * <Spinner size=\"lg\" label=\"Loading projects\" />\n * @example\n * // Inside a filled button, where the ground is ink:\n * <Spinner size=\"sm\" tone=\"current\" label={null} />\n */\nexport function Spinner({\n size = 'md',\n tone = 'default',\n className,\n label = 'Loading',\n ...rest\n}: SpinnerProps) {\n return (\n <span\n role={label === null ? undefined : 'status'}\n aria-hidden={label === null ? true : undefined}\n className=\"inline-flex shrink-0 items-center justify-center\"\n {...rest}\n >\n <span\n data-folio-animated\n className={cn(\n 'inline-block rounded-full border-solid motion-safe:animate-[folio-spin_0.7s_linear_infinite]',\n SIZE[size],\n TONE[tone],\n className,\n )}\n />\n {label !== null && <span className=\"sr-only\">{label}</span>}\n </span>\n )\n}\n\nexport default Spinner\n"],"mappings":"AA2EI,SAME,KANF;AA1EJ,SAAS,UAAU;AA0BnB,MAAM,OAAO;AAAA,EACX,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,OAAO;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AACX;AA+BO,SAAS,QAAQ;AAAA,EACtB,OAAO;AAAA,EACP,OAAO;AAAA,EACP;AAAA,EACA,QAAQ;AAAA,EACR,GAAG;AACL,GAAiB;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,UAAU,OAAO,SAAY;AAAA,MACnC,eAAa,UAAU,OAAO,OAAO;AAAA,MACrC,WAAU;AAAA,MACT,GAAG;AAAA,MAEJ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,uBAAmB;AAAA,YACnB,WAAW;AAAA,cACT;AAAA,cACA,KAAK,IAAI;AAAA,cACT,KAAK,IAAI;AAAA,cACT;AAAA,YACF;AAAA;AAAA,QACF;AAAA,QACC,UAAU,QAAQ,oBAAC,UAAK,WAAU,WAAW,iBAAM;AAAA;AAAA;AAAA,EACtD;AAEJ;AAEA,IAAO,kBAAQ;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
type StatusTone = 'success' | 'warning' | 'danger' | 'neutral';
|
|
5
|
+
interface StatusDotProps extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
/** 7px / 8px. `md` is the default. */
|
|
7
|
+
size?: 'sm' | 'md';
|
|
8
|
+
tone?: StatusTone;
|
|
9
|
+
/** A halo that grows and dissolves, for "live right now". Off for a settled state. */
|
|
10
|
+
pulse?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The dot beside a status word.
|
|
14
|
+
*
|
|
15
|
+
* `aria-hidden` without exception: the dot repeats a state the adjacent label
|
|
16
|
+
* already names, and a screen reader announcing "available" twice is worse than
|
|
17
|
+
* not announcing the decoration at all. If a call site has no visible label,
|
|
18
|
+
* the fix is a label, not an `aria-label` on the dot.
|
|
19
|
+
*
|
|
20
|
+
* The halo is a separate absolutely-positioned ring rather than a box-shadow,
|
|
21
|
+
* because Law 2 of this system is that a shadow is never blurred — and it is
|
|
22
|
+
* motion-safe, so a reader who asked for less motion gets a static dot.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <span className="inline-flex items-center gap-2"><StatusDot /> Available</span>
|
|
26
|
+
*/
|
|
27
|
+
declare function StatusDot({ size, tone, pulse, className, ...rest }: StatusDotProps): react.JSX.Element;
|
|
28
|
+
|
|
29
|
+
export { StatusDot, type StatusDotProps, type StatusTone, StatusDot as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
const SIZE = { sm: "size-[7px]", md: "size-2" };
|
|
4
|
+
const TONE = {
|
|
5
|
+
success: "bg-(--ok)",
|
|
6
|
+
warning: "bg-(--warn)",
|
|
7
|
+
danger: "bg-(--danger)",
|
|
8
|
+
neutral: "bg-(--ink-3-aa)"
|
|
9
|
+
};
|
|
10
|
+
function StatusDot({
|
|
11
|
+
size = "md",
|
|
12
|
+
tone = "success",
|
|
13
|
+
pulse = true,
|
|
14
|
+
className,
|
|
15
|
+
...rest
|
|
16
|
+
}) {
|
|
17
|
+
return /* @__PURE__ */ jsxs(
|
|
18
|
+
"span",
|
|
19
|
+
{
|
|
20
|
+
"aria-hidden": "true",
|
|
21
|
+
className: cn("relative inline-grid shrink-0 place-items-center", SIZE[size], className),
|
|
22
|
+
...rest,
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx("span", { className: cn("absolute inset-0 rounded-full", TONE[tone]) }),
|
|
25
|
+
pulse && /* @__PURE__ */ jsx(
|
|
26
|
+
"span",
|
|
27
|
+
{
|
|
28
|
+
"data-folio-animated": true,
|
|
29
|
+
className: cn(
|
|
30
|
+
"absolute inset-0 rounded-full motion-safe:animate-[folio-halo_2.4s_ease-out_infinite]",
|
|
31
|
+
TONE[tone]
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
var StatusDot_default = StatusDot;
|
|
40
|
+
export {
|
|
41
|
+
StatusDot,
|
|
42
|
+
StatusDot_default as default
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=StatusDot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/StatusDot/StatusDot.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport type StatusTone = 'success' | 'warning' | 'danger' | 'neutral'\n\nexport interface StatusDotProps extends HTMLAttributes<HTMLSpanElement> {\n /** 7px / 8px. `md` is the default. */\n size?: 'sm' | 'md'\n tone?: StatusTone\n /** A halo that grows and dissolves, for \"live right now\". Off for a settled state. */\n pulse?: boolean\n}\n\nconst SIZE = { sm: 'size-[7px]', md: 'size-2' } as const\n\nconst TONE: Record<StatusTone, string> = {\n success: 'bg-(--ok)',\n warning: 'bg-(--warn)',\n danger: 'bg-(--danger)',\n neutral: 'bg-(--ink-3-aa)',\n}\n\n/**\n * The dot beside a status word.\n *\n * `aria-hidden` without exception: the dot repeats a state the adjacent label\n * already names, and a screen reader announcing \"available\" twice is worse than\n * not announcing the decoration at all. If a call site has no visible label,\n * the fix is a label, not an `aria-label` on the dot.\n *\n * The halo is a separate absolutely-positioned ring rather than a box-shadow,\n * because Law 2 of this system is that a shadow is never blurred — and it is\n * motion-safe, so a reader who asked for less motion gets a static dot.\n *\n * @example\n * <span className=\"inline-flex items-center gap-2\"><StatusDot /> Available</span>\n */\nexport function StatusDot({\n size = 'md',\n tone = 'success',\n pulse = true,\n className,\n ...rest\n}: StatusDotProps) {\n return (\n <span\n aria-hidden=\"true\"\n className={cn('relative inline-grid shrink-0 place-items-center', SIZE[size], className)}\n {...rest}\n >\n <span className={cn('absolute inset-0 rounded-full', TONE[tone])} />\n {pulse && (\n <span\n data-folio-animated\n className={cn(\n 'absolute inset-0 rounded-full motion-safe:animate-[folio-halo_2.4s_ease-out_infinite]',\n TONE[tone],\n )}\n />\n )}\n </span>\n )\n}\n\nexport default StatusDot\n"],"mappings":"AA6CI,SAKE,KALF;AA5CJ,SAAS,UAAU;AAYnB,MAAM,OAAO,EAAE,IAAI,cAAc,IAAI,SAAS;AAE9C,MAAM,OAAmC;AAAA,EACvC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAiBO,SAAS,UAAU;AAAA,EACxB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAW,GAAG,oDAAoD,KAAK,IAAI,GAAG,SAAS;AAAA,MACtF,GAAG;AAAA,MAEJ;AAAA,4BAAC,UAAK,WAAW,GAAG,iCAAiC,KAAK,IAAI,CAAC,GAAG;AAAA,QACjE,SACC;AAAA,UAAC;AAAA;AAAA,YACC,uBAAmB;AAAA,YACnB,WAAW;AAAA,cACT;AAAA,cACA,KAAK,IAAI;AAAA,YACX;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,oBAAQ;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
import { StatusTone } from '../StatusDot/StatusDot.js';
|
|
4
|
+
|
|
5
|
+
interface StatusPillProps extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
tone?: StatusTone;
|
|
8
|
+
/** Pulsing live dot (default) vs a settled one. */
|
|
9
|
+
pulse?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A live state, named: a dot plus an uppercase mono label in an outlined pill.
|
|
13
|
+
*
|
|
14
|
+
* One component rather than a dot and a pill assembled per call site, which is
|
|
15
|
+
* how the same "available for work" chip ended up with three different dot
|
|
16
|
+
* sizes and two different pulse timings on one site.
|
|
17
|
+
*
|
|
18
|
+
* A warning or danger tone is doubled by a visually-hidden severity word, so
|
|
19
|
+
* the tone survives the dot being hidden. It does not survive monochrome: the
|
|
20
|
+
* pill's own text is `--ink-2` at every tone, and the state itself still
|
|
21
|
+
* belongs in the words the call site writes.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <StatusPill>Available for work</StatusPill>
|
|
25
|
+
* @example
|
|
26
|
+
* <StatusPill tone="warning" pulse={false}>Degraded</StatusPill>
|
|
27
|
+
*/
|
|
28
|
+
declare function StatusPill({ children, tone, pulse, className, ...rest }: StatusPillProps): react.JSX.Element;
|
|
29
|
+
|
|
30
|
+
export { StatusPill, type StatusPillProps, StatusPill as default };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { StatusDot } from "../StatusDot/StatusDot.js";
|
|
4
|
+
const SEVERITY = {
|
|
5
|
+
warning: "Warning",
|
|
6
|
+
danger: "Error"
|
|
7
|
+
};
|
|
8
|
+
function StatusPill({
|
|
9
|
+
children,
|
|
10
|
+
tone = "success",
|
|
11
|
+
pulse = true,
|
|
12
|
+
className,
|
|
13
|
+
...rest
|
|
14
|
+
}) {
|
|
15
|
+
const severity = SEVERITY[tone];
|
|
16
|
+
return /* @__PURE__ */ jsxs(
|
|
17
|
+
"span",
|
|
18
|
+
{
|
|
19
|
+
className: cn(
|
|
20
|
+
"inline-flex items-center gap-2.5 rounded-(--radius-pill) border border-(--rule-2) bg-(--paper) py-1.5 ps-2.5 pe-3 eyebrow tracking-[0.12em] text-(--ink-2)",
|
|
21
|
+
className
|
|
22
|
+
),
|
|
23
|
+
...rest,
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ jsx(StatusDot, { tone, pulse }),
|
|
26
|
+
severity && /* @__PURE__ */ jsx("span", { className: "sr-only", children: severity }),
|
|
27
|
+
children
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
var StatusPill_default = StatusPill;
|
|
33
|
+
export {
|
|
34
|
+
StatusPill,
|
|
35
|
+
StatusPill_default as default
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=StatusPill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/StatusPill/StatusPill.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { StatusDot, type StatusTone } from '../StatusDot/StatusDot'\n\nexport interface StatusPillProps extends HTMLAttributes<HTMLSpanElement> {\n children: ReactNode\n tone?: StatusTone\n /** Pulsing live dot (default) vs a settled one. */\n pulse?: boolean\n}\n\n/**\n * The two tones a reader must not miss, in the words the dot cannot say.\n *\n * `tone` reaches only the StatusDot, and the dot is `aria-hidden` by law — so\n * before this, \"Degraded\" in a warning pill and \"Degraded\" in a neutral one\n * were the same sentence to anyone who could not see the colour.\n *\n * `success` and `neutral` add nothing on purpose. They are the absence of\n * alarm, which is what a reader assumes; announcing it before every settled\n * pill is noise charged to the two tones that are worth interrupting for.\n */\nconst SEVERITY: Partial<Record<StatusTone, string>> = {\n warning: 'Warning',\n danger: 'Error',\n}\n\n/**\n * A live state, named: a dot plus an uppercase mono label in an outlined pill.\n *\n * One component rather than a dot and a pill assembled per call site, which is\n * how the same \"available for work\" chip ended up with three different dot\n * sizes and two different pulse timings on one site.\n *\n * A warning or danger tone is doubled by a visually-hidden severity word, so\n * the tone survives the dot being hidden. It does not survive monochrome: the\n * pill's own text is `--ink-2` at every tone, and the state itself still\n * belongs in the words the call site writes.\n *\n * @example\n * <StatusPill>Available for work</StatusPill>\n * @example\n * <StatusPill tone=\"warning\" pulse={false}>Degraded</StatusPill>\n */\nexport function StatusPill({\n children,\n tone = 'success',\n pulse = true,\n className,\n ...rest\n}: StatusPillProps) {\n const severity = SEVERITY[tone]\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-2.5 rounded-(--radius-pill) border border-(--rule-2) bg-(--paper) py-1.5 ps-2.5 pe-3 eyebrow tracking-[0.12em] text-(--ink-2)',\n className,\n )}\n {...rest}\n >\n <StatusDot tone={tone} pulse={pulse} />\n {/* Absolutely positioned by `sr-only`, so it is out of flow and costs the\n pill neither a gap nor a pixel. */}\n {severity && <span className=\"sr-only\">{severity}</span>}\n {children}\n </span>\n )\n}\n\nexport default StatusPill\n"],"mappings":"AAsDI,SAOE,KAPF;AArDJ,SAAS,UAAU;AACnB,SAAS,iBAAkC;AAoB3C,MAAM,WAAgD;AAAA,EACpD,SAAS;AAAA,EACT,QAAQ;AACV;AAmBO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,WAAW,SAAS,IAAI;AAE9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,aAAU,MAAY,OAAc;AAAA,QAGpC,YAAY,oBAAC,UAAK,WAAU,WAAW,oBAAS;AAAA,QAChD;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
|