@misoto22/design 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +87 -0
- package/CLAUDE.md +1 -0
- package/README.md +62 -5
- package/bin/misoto22-design.mjs +59 -13
- package/dist/agent/Accordion.md +24 -1
- package/dist/agent/Alert.md +23 -1
- package/dist/agent/AppShell.md +30 -2
- package/dist/agent/ArchitectureFigure.md +71 -0
- package/dist/agent/AreaChart.md +27 -2
- package/dist/agent/Article.md +26 -3
- package/dist/agent/AspectRatio.md +57 -0
- package/dist/agent/Avatar.md +25 -5
- package/dist/agent/Badge.md +22 -1
- package/dist/agent/BarChart.md +29 -2
- package/dist/agent/BarList.md +27 -1
- package/dist/agent/BigNumber.md +26 -2
- package/dist/agent/BoxPlot.md +24 -1
- package/dist/agent/Breadcrumb.md +24 -2
- package/dist/agent/BulletChart.md +23 -1
- package/dist/agent/Button.md +25 -1
- package/dist/agent/Calendar.md +37 -3
- package/dist/agent/Card.md +24 -2
- package/dist/agent/Checkbox.md +23 -2
- package/dist/agent/Code.md +50 -0
- package/dist/agent/CodeBlock.md +74 -0
- package/dist/agent/Collapsible.md +22 -1
- package/dist/agent/Combobox.md +29 -3
- package/dist/agent/Command.md +25 -2
- package/dist/agent/ComposedChart.md +26 -2
- package/dist/agent/ContextMenu.md +37 -4
- package/dist/agent/DataflowFigure.md +48 -0
- package/dist/agent/DatePicker.md +34 -6
- package/dist/agent/DescriptionList.md +68 -0
- package/dist/agent/Diagram.md +27 -3
- package/dist/agent/DiagramCanvas.md +70 -0
- package/dist/agent/DiagramExportMenu.md +64 -0
- package/dist/agent/DiagramInspector.md +72 -0
- package/dist/agent/DiagramLegend.md +55 -0
- package/dist/agent/DiagramMinimap.md +68 -0
- package/dist/agent/DiagramToolbar.md +69 -0
- package/dist/agent/Dialog.md +26 -3
- package/dist/agent/DropdownMenu.md +45 -6
- package/dist/agent/EmptyState.md +26 -1
- package/dist/agent/ErrorState.md +27 -2
- package/dist/agent/Facet.md +25 -1
- package/dist/agent/Field.md +45 -4
- package/dist/agent/FigureBand.md +24 -1
- package/dist/agent/FloatingIconButton.md +23 -1
- package/dist/agent/FunnelChart.md +23 -1
- package/dist/agent/Heading.md +64 -0
- package/dist/agent/Heatmap.md +25 -1
- package/dist/agent/Histogram.md +26 -2
- package/dist/agent/Input.md +22 -1
- package/dist/agent/Kbd.md +19 -1
- package/dist/agent/LifecycleFigure.md +49 -0
- package/dist/agent/LineChart.md +26 -2
- package/dist/agent/LinkArrow.md +20 -1
- package/dist/agent/Markdown.md +68 -0
- package/dist/agent/NativeSelect.md +23 -2
- package/dist/agent/NavItem.md +21 -1
- package/dist/agent/Pagination.md +28 -2
- package/dist/agent/PieChart.md +26 -2
- package/dist/agent/Popover.md +23 -1
- package/dist/agent/Progress.md +27 -3
- package/dist/agent/RadarChart.md +26 -2
- package/dist/agent/RadialChart.md +26 -3
- package/dist/agent/RadioGroup.md +23 -2
- package/dist/agent/SankeyChart.md +25 -2
- package/dist/agent/ScatterChart.md +27 -2
- package/dist/agent/ScrollArea.md +24 -3
- package/dist/agent/SearchableMenu.md +23 -1
- package/dist/agent/Select.md +29 -3
- package/dist/agent/Separator.md +28 -4
- package/dist/agent/SequenceFigure.md +50 -0
- package/dist/agent/Sheet.md +25 -2
- package/dist/agent/Skeleton.md +24 -2
- package/dist/agent/Slider.md +27 -4
- package/dist/agent/Sparkline.md +23 -1
- package/dist/agent/Spinner.md +24 -2
- package/dist/agent/StatusDot.md +20 -1
- package/dist/agent/StatusPill.md +28 -2
- package/dist/agent/Steps.md +24 -1
- package/dist/agent/Switch.md +21 -1
- package/dist/agent/Table.md +26 -3
- package/dist/agent/Tabs.md +24 -2
- package/dist/agent/Tag.md +40 -9
- package/dist/agent/Text.md +65 -0
- package/dist/agent/Textarea.md +20 -1
- package/dist/agent/Timestamp.md +64 -0
- package/dist/agent/Toast.md +26 -2
- package/dist/agent/ToggleGroup.md +24 -2
- package/dist/agent/Toolbar.md +71 -0
- package/dist/agent/Tooltip.md +23 -1
- package/dist/agent/TreemapChart.md +24 -1
- package/dist/agent/WaterfallChart.md +24 -1
- package/dist/agent/WorkflowFigure.md +50 -0
- package/dist/agent/catalog.json +6086 -1009
- package/dist/agent/index.md +27 -4
- package/dist/article.css +16 -4
- package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
- package/dist/charts/AreaChart/AreaChart.js +12 -13
- package/dist/charts/AreaChart/AreaChart.js.map +1 -1
- package/dist/charts/BarChart/BarChart.d.ts +14 -3
- package/dist/charts/BarChart/BarChart.js +20 -12
- package/dist/charts/BarChart/BarChart.js.map +1 -1
- package/dist/charts/BarList/BarList.d.ts +9 -1
- package/dist/charts/BarList/BarList.js +9 -1
- package/dist/charts/BarList/BarList.js.map +1 -1
- package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
- package/dist/charts/BigNumber/BigNumber.js +25 -5
- package/dist/charts/BigNumber/BigNumber.js.map +1 -1
- package/dist/charts/BoxPlot/BoxPlot.js +4 -2
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
- package/dist/charts/BulletChart/BulletChart.js +28 -7
- package/dist/charts/BulletChart/BulletChart.js.map +1 -1
- package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
- package/dist/charts/ComposedChart/ComposedChart.js +10 -10
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
- package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
- package/dist/charts/FunnelChart/FunnelChart.js +6 -16
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
- package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
- package/dist/charts/Heatmap/Heatmap.js +20 -11
- package/dist/charts/Heatmap/Heatmap.js.map +1 -1
- package/dist/charts/Histogram/Histogram.d.ts +24 -1
- package/dist/charts/Histogram/Histogram.js +43 -11
- package/dist/charts/Histogram/Histogram.js.map +1 -1
- package/dist/charts/LineChart/LineChart.d.ts +9 -2
- package/dist/charts/LineChart/LineChart.js +11 -12
- package/dist/charts/LineChart/LineChart.js.map +1 -1
- package/dist/charts/PieChart/PieChart.d.ts +15 -3
- package/dist/charts/PieChart/PieChart.js +14 -6
- package/dist/charts/PieChart/PieChart.js.map +1 -1
- package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
- package/dist/charts/RadarChart/RadarChart.js +11 -9
- package/dist/charts/RadarChart/RadarChart.js.map +1 -1
- package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
- package/dist/charts/RadialChart/RadialChart.js +28 -6
- package/dist/charts/RadialChart/RadialChart.js.map +1 -1
- package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
- package/dist/charts/SankeyChart/SankeyChart.js +14 -6
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
- package/dist/charts/ScatterChart/ScatterChart.js +21 -15
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
- package/dist/charts/Sparkline/Sparkline.js +5 -3
- package/dist/charts/Sparkline/Sparkline.js.map +1 -1
- package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
- package/dist/charts/TreemapChart/TreemapChart.js +20 -11
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
- package/dist/charts/index.d.ts +2 -1
- package/dist/charts/lib/export.d.ts +34 -43
- package/dist/charts/lib/export.js +16 -158
- package/dist/charts/lib/export.js.map +1 -1
- package/dist/charts/lib/figure.d.ts +21 -1
- package/dist/charts/lib/figure.js +5 -2
- package/dist/charts/lib/figure.js.map +1 -1
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +1 -0
- package/dist/components/Accordion/Accordion.js +8 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/AppShell/AppShell.d.ts +6 -0
- package/dist/components/AppShell/AppShell.js +34 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +11 -4
- package/dist/components/Article/Article.js +13 -0
- package/dist/components/Article/Article.js.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +12 -3
- package/dist/components/Avatar/Avatar.js +6 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +14 -0
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +29 -3
- package/dist/components/Calendar/Calendar.js +60 -12
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +5 -2
- package/dist/components/Checkbox/Checkbox.js +12 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +141 -0
- package/dist/components/CodeBlock/CodeBlock.js +123 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +10 -2
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.d.ts +15 -1
- package/dist/components/Combobox/Combobox.js +25 -5
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.d.ts +4 -2
- package/dist/components/Command/Command.js +13 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
- package/dist/components/ContextMenu/ContextMenu.js +32 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +36 -4
- package/dist/components/DatePicker/DatePicker.js +55 -12
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +8 -3
- package/dist/components/Diagram/Diagram.js +82 -10
- package/dist/components/Diagram/Diagram.js.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +18 -3
- package/dist/components/Dialog/Dialog.js +20 -2
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
- package/dist/components/DropdownMenu/DropdownMenu.js +32 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +25 -1
- package/dist/components/EmptyState/EmptyState.js +3 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.d.ts +22 -1
- package/dist/components/ErrorState/ErrorState.js +11 -2
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +70 -3
- package/dist/components/Field/Field.js +53 -12
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +2 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +6 -0
- package/dist/components/NativeSelect/NativeSelect.js +2 -3
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +24 -1
- package/dist/components/Pagination/Pagination.js +6 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Progress/Progress.d.ts +17 -5
- package/dist/components/Progress/Progress.js +18 -6
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroup.js +11 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
- package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
- package/dist/components/Select/Select.d.ts +18 -2
- package/dist/components/Select/Select.js +20 -3
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +21 -3
- package/dist/components/Separator/Separator.js +9 -1
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +3 -0
- package/dist/components/Sheet/Sheet.js +11 -2
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +8 -1
- package/dist/components/Skeleton/Skeleton.js +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +21 -3
- package/dist/components/Slider/Slider.js +54 -27
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +8 -0
- package/dist/components/Spinner/Spinner.js +3 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/StatusPill/StatusPill.d.ts +5 -0
- package/dist/components/StatusPill/StatusPill.js +6 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -1
- package/dist/components/Table/Table.d.ts +6 -0
- package/dist/components/Table/Table.js +3 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tag/Tag.d.ts +68 -9
- package/dist/components/Tag/Tag.js +50 -10
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +9 -1
- package/dist/components/Toast/Toast.js +27 -4
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +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 +85 -0
- package/dist/diagrams/lib/route.js +178 -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 +90 -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/index.d.ts +16 -4
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/keyframes.css +57 -3
- package/dist/lib/overlay-container.d.ts +14 -4
- package/dist/lib/overlay-container.js.map +1 -1
- 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/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +51 -6
- package/dist/styles.css +1 -1
- package/dist/tokens.css +20 -2
- package/dist/tokens.d.ts +17 -1
- package/dist/tokens.js +121 -36
- package/dist/tokens.json +121 -36
- package/llms.txt +35 -0
- package/package.json +9 -2
- package/skills/misoto22-design/SKILL.md +21 -7
- package/skills/misoto22-design/evals/evals.json +84 -0
- package/skills/misoto22-design/rules/a11y.md +55 -3
- package/skills/misoto22-design/rules/forms.md +5 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A rung of the type scale, named for what it is FOR rather than for a pixel
|
|
6
|
+
* value. `base` is body copy; `lead` is the standfirst that carries a piece and
|
|
7
|
+
* is the only step here that touches the heading ladder (`--fs-item`, its
|
|
8
|
+
* bottom rung). Nothing above that: a paragraph larger than a record title is a
|
|
9
|
+
* heading that forgot to be one.
|
|
10
|
+
*/
|
|
11
|
+
type TextSize = 'xs' | 'sm' | 'base' | 'lead';
|
|
12
|
+
/**
|
|
13
|
+
* A rung of the ink ladder. Three, because the ladder has three.
|
|
14
|
+
*
|
|
15
|
+
* `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper
|
|
16
|
+
* and are not the same token: `--ink-3` is a translucent tint that inherits
|
|
17
|
+
* whatever is under it, so it clears AA on the page ground and quietly fails on
|
|
18
|
+
* a card, a plate, or a code block.
|
|
19
|
+
*/
|
|
20
|
+
type TextTone = 'body' | 'strong' | 'muted';
|
|
21
|
+
type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption';
|
|
22
|
+
interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
/** Which rung of the type scale. See {@link TextSize}. */
|
|
25
|
+
size?: TextSize;
|
|
26
|
+
/** Which rung of the ink ladder. See {@link TextTone}. */
|
|
27
|
+
tone?: TextTone;
|
|
28
|
+
/**
|
|
29
|
+
* The element, and ONLY the element.
|
|
30
|
+
*
|
|
31
|
+
* Changing it changes what the markup means — a `span` inside a sentence, an
|
|
32
|
+
* `li` inside a list someone else opened — and changes nothing about the
|
|
33
|
+
* look. That separation is the whole point: the alternative is a `<p>` nested
|
|
34
|
+
* inside a `<p>`, which the HTML parser silently splits into two, or a
|
|
35
|
+
* paragraph faked out of a `<div>` because the real element brought a size
|
|
36
|
+
* with it.
|
|
37
|
+
*/
|
|
38
|
+
as?: TextElement;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A paragraph, or a run of text that wants the system's voice.
|
|
42
|
+
*
|
|
43
|
+
* The step between `Article` and raw JSX. `Article` styles a whole reading
|
|
44
|
+
* column from element selectors and is the right answer for a post; this is for
|
|
45
|
+
* the single paragraph that is NOT in a column — a card's description, a
|
|
46
|
+
* dialog's explanation, the line under an empty state.
|
|
47
|
+
*
|
|
48
|
+
* The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs
|
|
49
|
+
* are all full-strength ink has spent the top of the ladder on its body copy
|
|
50
|
+
* and has nothing left for the headings, which is the single most common way a
|
|
51
|
+
* monochrome page loses its hierarchy.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* <Text>Twelve releases this quarter, none rolled back.</Text>
|
|
55
|
+
* @example
|
|
56
|
+
* <Text size="lead" tone="strong">A monochrome system for software and writing.</Text>
|
|
57
|
+
* @example
|
|
58
|
+
* <Text as="span" size="sm" tone="muted">Updated just now</Text>
|
|
59
|
+
*/
|
|
60
|
+
declare function Text({ children, size, tone, as, className, ...rest }: TextProps): react.JSX.Element;
|
|
61
|
+
|
|
62
|
+
export { Text, type TextElement, type TextProps, type TextSize, type TextTone, Text as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
const SIZE = {
|
|
4
|
+
xs: "text-xs leading-[1.6]",
|
|
5
|
+
sm: "text-sm leading-[1.65]",
|
|
6
|
+
base: "text-base font-light leading-[1.75]",
|
|
7
|
+
lead: "text-[length:var(--fs-item)] font-light leading-[1.6]"
|
|
8
|
+
};
|
|
9
|
+
const TONE = {
|
|
10
|
+
body: "text-(--ink-2)",
|
|
11
|
+
strong: "text-(--ink)",
|
|
12
|
+
muted: "text-(--ink-3-aa)"
|
|
13
|
+
};
|
|
14
|
+
function Text({
|
|
15
|
+
children,
|
|
16
|
+
size = "base",
|
|
17
|
+
tone = "body",
|
|
18
|
+
as = "p",
|
|
19
|
+
className,
|
|
20
|
+
...rest
|
|
21
|
+
}) {
|
|
22
|
+
const Comp = as;
|
|
23
|
+
return /* @__PURE__ */ jsx(Comp, { className: cn("m-0", SIZE[size], TONE[tone], className), ...rest, children });
|
|
24
|
+
}
|
|
25
|
+
var Text_default = Text;
|
|
26
|
+
export {
|
|
27
|
+
Text,
|
|
28
|
+
Text_default as default
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=Text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Text/Text.tsx"],"sourcesContent":["import type { ElementType, HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * A rung of the type scale, named for what it is FOR rather than for a pixel\n * value. `base` is body copy; `lead` is the standfirst that carries a piece and\n * is the only step here that touches the heading ladder (`--fs-item`, its\n * bottom rung). Nothing above that: a paragraph larger than a record title is a\n * heading that forgot to be one.\n */\nexport type TextSize = 'xs' | 'sm' | 'base' | 'lead'\n\n/**\n * A rung of the ink ladder. Three, because the ladder has three.\n *\n * `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper\n * and are not the same token: `--ink-3` is a translucent tint that inherits\n * whatever is under it, so it clears AA on the page ground and quietly fails on\n * a card, a plate, or a code block.\n */\nexport type TextTone = 'body' | 'strong' | 'muted'\n\nexport type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption'\n\n/**\n * Weight travels with the size, deliberately.\n *\n * The system sets long-form copy at 300 — it is what gives a page of prose its\n * air. At 12 and 14px that same weight is a hairline: the strokes thin out\n * below the point where a light face is a choice and turn into a legibility\n * bug. So the two small steps step back up to 400, and a caller never has to\n * know that the trade exists.\n */\nconst SIZE: Record<TextSize, string> = {\n xs: 'text-xs leading-[1.6]',\n sm: 'text-sm leading-[1.65]',\n base: 'text-base font-light leading-[1.75]',\n lead: 'text-[length:var(--fs-item)] font-light leading-[1.6]',\n}\n\nconst TONE: Record<TextTone, string> = {\n body: 'text-(--ink-2)',\n strong: 'text-(--ink)',\n muted: 'text-(--ink-3-aa)',\n}\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n children?: ReactNode\n /** Which rung of the type scale. See {@link TextSize}. */\n size?: TextSize\n /** Which rung of the ink ladder. See {@link TextTone}. */\n tone?: TextTone\n /**\n * The element, and ONLY the element.\n *\n * Changing it changes what the markup means — a `span` inside a sentence, an\n * `li` inside a list someone else opened — and changes nothing about the\n * look. That separation is the whole point: the alternative is a `<p>` nested\n * inside a `<p>`, which the HTML parser silently splits into two, or a\n * paragraph faked out of a `<div>` because the real element brought a size\n * with it.\n */\n as?: TextElement\n}\n\n/**\n * A paragraph, or a run of text that wants the system's voice.\n *\n * The step between `Article` and raw JSX. `Article` styles a whole reading\n * column from element selectors and is the right answer for a post; this is for\n * the single paragraph that is NOT in a column — a card's description, a\n * dialog's explanation, the line under an empty state.\n *\n * The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs\n * are all full-strength ink has spent the top of the ladder on its body copy\n * and has nothing left for the headings, which is the single most common way a\n * monochrome page loses its hierarchy.\n *\n * @example\n * <Text>Twelve releases this quarter, none rolled back.</Text>\n * @example\n * <Text size=\"lead\" tone=\"strong\">A monochrome system for software and writing.</Text>\n * @example\n * <Text as=\"span\" size=\"sm\" tone=\"muted\">Updated just now</Text>\n */\nexport function Text({\n children,\n size = 'base',\n tone = 'body',\n as = 'p',\n className,\n ...rest\n}: TextProps) {\n const Comp = as as ElementType\n\n return (\n <Comp className={cn('m-0', SIZE[size], TONE[tone], className)} {...rest}>\n {children}\n </Comp>\n )\n}\n\nexport default Text\n"],"mappings":"AAgGI;AA/FJ,SAAS,UAAU;AAgCnB,MAAM,OAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,OAAiC;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAyCO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AAAA,EACL;AAAA,EACA,GAAG;AACL,GAAc;AACZ,QAAM,OAAO;AAEb,SACE,oBAAC,QAAK,WAAW,GAAG,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,GAAI,GAAG,MAChE,UACH;AAEJ;AAEA,IAAO,eAAQ;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { TimeHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How the instant reads.
|
|
6
|
+
*
|
|
7
|
+
* `auto` is relative while the gap is small enough to be useful and absolute
|
|
8
|
+
* once it is not — "3 hours ago" answers the question a reader is actually
|
|
9
|
+
* asking about a recent record, and "2 years ago" does not.
|
|
10
|
+
*/
|
|
11
|
+
type TimestampFormat = 'auto' | 'relative' | 'absolute';
|
|
12
|
+
interface TimestampProps extends Omit<TimeHTMLAttributes<HTMLTimeElement>, 'dateTime' | 'children'> {
|
|
13
|
+
/** The instant. A `Date`, an ISO string, or epoch milliseconds. */
|
|
14
|
+
value: Date | string | number;
|
|
15
|
+
/** How the instant reads. See {@link TimestampFormat}. */
|
|
16
|
+
format?: TimestampFormat;
|
|
17
|
+
/**
|
|
18
|
+
* How far from now `auto` still prints a relative time, in milliseconds.
|
|
19
|
+
* Seven days by default — past a week the calendar date is the more useful
|
|
20
|
+
* fact, and it is also the one that stops changing.
|
|
21
|
+
*/
|
|
22
|
+
relativeWithin?: number;
|
|
23
|
+
/** Adds the clock time to the absolute form. */
|
|
24
|
+
showTime?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A date or a time, rendered the one way the system renders them.
|
|
28
|
+
*
|
|
29
|
+
* Every list of records needs this, and `new Date().toLocaleString()` at the
|
|
30
|
+
* call site is precisely how a product ends up with four date formats on one
|
|
31
|
+
* screen.
|
|
32
|
+
*
|
|
33
|
+
* **On hydration.** Both halves of a formatted date are environment-dependent:
|
|
34
|
+
* a relative time depends on when it is read, and even an absolute one depends
|
|
35
|
+
* on the reader's locale and time zone, none of which a static build knows. So
|
|
36
|
+
* the first paint — the one the server produces and the one the client must
|
|
37
|
+
* reproduce exactly — is the ISO calendar date in UTC, sliced straight out of
|
|
38
|
+
* the ISO string with no `Intl` anywhere near it. Both sides compute it from
|
|
39
|
+
* the same characters, so they cannot disagree. The locale-aware and relative
|
|
40
|
+
* forms are applied after mount, in an effect, where there is a reader to be
|
|
41
|
+
* local to. This package statically exports every page, so the alternative is a
|
|
42
|
+
* hydration mismatch on any page with a date on it.
|
|
43
|
+
*
|
|
44
|
+
* The `datetime` attribute is the full ISO instant from the first render
|
|
45
|
+
* onwards and never changes, so a screen reader, a crawler, or anything else
|
|
46
|
+
* parsing the markup gets the exact moment whether or not the effect has run.
|
|
47
|
+
*
|
|
48
|
+
* It formats once per mount. A hundred rows each holding a ticking interval to
|
|
49
|
+
* keep "3 minutes ago" honest is a cost nobody asked for; a list that must tick
|
|
50
|
+
* should re-key or re-render from above.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* <Timestamp value={deploy.finishedAt} />
|
|
54
|
+
* @example
|
|
55
|
+
* <Timestamp value="2026-01-14T09:30:00Z" format="absolute" showTime />
|
|
56
|
+
*/
|
|
57
|
+
declare function Timestamp({ value, format, relativeWithin, showTime, className, ...rest }: TimestampProps): react.JSX.Element;
|
|
58
|
+
|
|
59
|
+
export { Timestamp, type TimestampFormat, type TimestampProps, Timestamp as default };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
const UNITS = [
|
|
6
|
+
["year", 31556952e3],
|
|
7
|
+
["month", 2629746e3],
|
|
8
|
+
["week", 6048e5],
|
|
9
|
+
["day", 864e5],
|
|
10
|
+
["hour", 36e5],
|
|
11
|
+
["minute", 6e4]
|
|
12
|
+
];
|
|
13
|
+
function relative(deltaMs) {
|
|
14
|
+
const format = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
|
|
15
|
+
const gap = Math.abs(deltaMs);
|
|
16
|
+
for (const [unit, size] of UNITS) {
|
|
17
|
+
if (gap >= size) return format.format(Math.trunc(deltaMs / size), unit);
|
|
18
|
+
}
|
|
19
|
+
return format.format(0, "second");
|
|
20
|
+
}
|
|
21
|
+
function absolute(date, showTime) {
|
|
22
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
23
|
+
dateStyle: "medium",
|
|
24
|
+
...showTime ? { timeStyle: "short" } : {}
|
|
25
|
+
}).format(date);
|
|
26
|
+
}
|
|
27
|
+
function Timestamp({
|
|
28
|
+
value,
|
|
29
|
+
format = "auto",
|
|
30
|
+
relativeWithin = 6048e5,
|
|
31
|
+
showTime = false,
|
|
32
|
+
className,
|
|
33
|
+
...rest
|
|
34
|
+
}) {
|
|
35
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
36
|
+
const time = date.getTime();
|
|
37
|
+
const valid = !Number.isNaN(time);
|
|
38
|
+
const [local, setLocal] = useState(false);
|
|
39
|
+
useEffect(() => setLocal(true), []);
|
|
40
|
+
if (!valid) {
|
|
41
|
+
return /* @__PURE__ */ jsx("span", { className: cn("text-(--ink-3-aa)", className), ...rest, children: "\u2014" });
|
|
42
|
+
}
|
|
43
|
+
const iso = date.toISOString();
|
|
44
|
+
return /* @__PURE__ */ jsx("time", { dateTime: iso, className: cn("tabular-nums", className), ...rest, children: local ? read(date, format, relativeWithin, showTime) : iso.slice(0, 10) });
|
|
45
|
+
}
|
|
46
|
+
function read(date, format, relativeWithin, showTime) {
|
|
47
|
+
const delta = date.getTime() - Date.now();
|
|
48
|
+
const asRelative = format === "relative" || format === "auto" && Math.abs(delta) < relativeWithin;
|
|
49
|
+
return asRelative ? relative(delta) : absolute(date, showTime);
|
|
50
|
+
}
|
|
51
|
+
var Timestamp_default = Timestamp;
|
|
52
|
+
export {
|
|
53
|
+
Timestamp,
|
|
54
|
+
Timestamp_default as default
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=Timestamp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Timestamp/Timestamp.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport type { TimeHTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * How the instant reads.\n *\n * `auto` is relative while the gap is small enough to be useful and absolute\n * once it is not — \"3 hours ago\" answers the question a reader is actually\n * asking about a recent record, and \"2 years ago\" does not.\n */\nexport type TimestampFormat = 'auto' | 'relative' | 'absolute'\n\nexport interface TimestampProps\n extends Omit<TimeHTMLAttributes<HTMLTimeElement>, 'dateTime' | 'children'> {\n /** The instant. A `Date`, an ISO string, or epoch milliseconds. */\n value: Date | string | number\n /** How the instant reads. See {@link TimestampFormat}. */\n format?: TimestampFormat\n /**\n * How far from now `auto` still prints a relative time, in milliseconds.\n * Seven days by default — past a week the calendar date is the more useful\n * fact, and it is also the one that stops changing.\n */\n relativeWithin?: number\n /** Adds the clock time to the absolute form. */\n showTime?: boolean\n}\n\n/**\n * The units, largest first, with the milliseconds in one of each.\n *\n * The month and year lengths are the average ones — 30.44 and 365.24 days —\n * because a relative time is a rounded statement about a gap, not a calendar\n * calculation, and \"2 months ago\" must not become \"1 month ago\" because\n * February was short.\n */\nconst UNITS = [\n ['year', 31_556_952_000],\n ['month', 2_629_746_000],\n ['week', 604_800_000],\n ['day', 86_400_000],\n ['hour', 3_600_000],\n ['minute', 60_000],\n] as const\n\n/**\n * The gap in words, in the reader's own language.\n *\n * `Intl.RelativeTimeFormat` rather than a table of English strings: it is in\n * every runtime this package targets, costs nothing to ship, and `numeric:\n * 'auto'` is what turns \"1 day ago\" into \"yesterday\".\n *\n * Truncated, not rounded — ninety seconds is \"1 minute ago\", because a reader\n * who has just watched something happen is not helped by being told it was two\n * minutes. Anything under a minute is \"now\": the seconds are noise, and they\n * are also the only part that would be wrong a moment later.\n */\nfunction relative(deltaMs: number): string {\n const format = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })\n const gap = Math.abs(deltaMs)\n\n for (const [unit, size] of UNITS) {\n if (gap >= size) return format.format(Math.trunc(deltaMs / size), unit)\n }\n return format.format(0, 'second')\n}\n\n/** The calendar date, in the reader's own locale and time zone. */\nfunction absolute(date: Date, showTime: boolean): string {\n return new Intl.DateTimeFormat(undefined, {\n dateStyle: 'medium',\n ...(showTime ? { timeStyle: 'short' as const } : {}),\n }).format(date)\n}\n\n/**\n * A date or a time, rendered the one way the system renders them.\n *\n * Every list of records needs this, and `new Date().toLocaleString()` at the\n * call site is precisely how a product ends up with four date formats on one\n * screen.\n *\n * **On hydration.** Both halves of a formatted date are environment-dependent:\n * a relative time depends on when it is read, and even an absolute one depends\n * on the reader's locale and time zone, none of which a static build knows. So\n * the first paint — the one the server produces and the one the client must\n * reproduce exactly — is the ISO calendar date in UTC, sliced straight out of\n * the ISO string with no `Intl` anywhere near it. Both sides compute it from\n * the same characters, so they cannot disagree. The locale-aware and relative\n * forms are applied after mount, in an effect, where there is a reader to be\n * local to. This package statically exports every page, so the alternative is a\n * hydration mismatch on any page with a date on it.\n *\n * The `datetime` attribute is the full ISO instant from the first render\n * onwards and never changes, so a screen reader, a crawler, or anything else\n * parsing the markup gets the exact moment whether or not the effect has run.\n *\n * It formats once per mount. A hundred rows each holding a ticking interval to\n * keep \"3 minutes ago\" honest is a cost nobody asked for; a list that must tick\n * should re-key or re-render from above.\n *\n * @example\n * <Timestamp value={deploy.finishedAt} />\n * @example\n * <Timestamp value=\"2026-01-14T09:30:00Z\" format=\"absolute\" showTime />\n */\nexport function Timestamp({\n value,\n format = 'auto',\n relativeWithin = 604_800_000,\n showTime = false,\n className,\n ...rest\n}: TimestampProps) {\n const date = value instanceof Date ? value : new Date(value)\n const time = date.getTime()\n const valid = !Number.isNaN(time)\n\n // False through the server render and the hydrating render, true from the\n // first effect on. That is the whole hydration contract in one flag.\n const [local, setLocal] = useState(false)\n useEffect(() => setLocal(true), [])\n\n if (!valid) {\n // Not \"Invalid Date\" — that is the browser's internal string and an\n // engineering artefact in front of a reader. A value nothing can parse is a\n // missing value, and a record UI already has a glyph for one. There is no\n // <time> here either: an element whose datetime cannot be written is not a\n // time.\n return (\n <span className={cn('text-(--ink-3-aa)', className)} {...rest}>\n —\n </span>\n )\n }\n\n const iso = date.toISOString()\n\n return (\n <time dateTime={iso} className={cn('tabular-nums', className)} {...rest}>\n {local ? read(date, format, relativeWithin, showTime) : iso.slice(0, 10)}\n </time>\n )\n}\n\n/**\n * The text a reader who has a clock and a locale gets. Only ever called after\n * mount — everything in here reads `Date.now()` or the ambient locale, which is\n * exactly what the server cannot know.\n */\nfunction read(\n date: Date,\n format: TimestampFormat,\n relativeWithin: number,\n showTime: boolean,\n): string {\n const delta = date.getTime() - Date.now()\n const asRelative = format === 'relative' || (format === 'auto' && Math.abs(delta) < relativeWithin)\n return asRelative ? relative(delta) : absolute(date, showTime)\n}\n\nexport default Timestamp\n"],"mappings":";AAqIM;AAnIN,SAAS,WAAW,gBAAgB;AAEpC,SAAS,UAAU;AAmCnB,MAAM,QAAQ;AAAA,EACZ,CAAC,QAAQ,UAAc;AAAA,EACvB,CAAC,SAAS,SAAa;AAAA,EACvB,CAAC,QAAQ,MAAW;AAAA,EACpB,CAAC,OAAO,KAAU;AAAA,EAClB,CAAC,QAAQ,IAAS;AAAA,EAClB,CAAC,UAAU,GAAM;AACnB;AAcA,SAAS,SAAS,SAAyB;AACzC,QAAM,SAAS,IAAI,KAAK,mBAAmB,QAAW,EAAE,SAAS,OAAO,CAAC;AACzE,QAAM,MAAM,KAAK,IAAI,OAAO;AAE5B,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO;AAChC,QAAI,OAAO,KAAM,QAAO,OAAO,OAAO,KAAK,MAAM,UAAU,IAAI,GAAG,IAAI;AAAA,EACxE;AACA,SAAO,OAAO,OAAO,GAAG,QAAQ;AAClC;AAGA,SAAS,SAAS,MAAY,UAA2B;AACvD,SAAO,IAAI,KAAK,eAAe,QAAW;AAAA,IACxC,WAAW;AAAA,IACX,GAAI,WAAW,EAAE,WAAW,QAAiB,IAAI,CAAC;AAAA,EACpD,CAAC,EAAE,OAAO,IAAI;AAChB;AAiCO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,QAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAC3D,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,QAAQ,CAAC,OAAO,MAAM,IAAI;AAIhC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AACxC,YAAU,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AAElC,MAAI,CAAC,OAAO;AAMV,WACE,oBAAC,UAAK,WAAW,GAAG,qBAAqB,SAAS,GAAI,GAAG,MAAM,oBAE/D;AAAA,EAEJ;AAEA,QAAM,MAAM,KAAK,YAAY;AAE7B,SACE,oBAAC,UAAK,UAAU,KAAK,WAAW,GAAG,gBAAgB,SAAS,GAAI,GAAG,MAChE,kBAAQ,KAAK,MAAM,QAAQ,gBAAgB,QAAQ,IAAI,IAAI,MAAM,GAAG,EAAE,GACzE;AAEJ;AAOA,SAAS,KACP,MACA,QACA,gBACA,UACQ;AACR,QAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,IAAI;AACxC,QAAM,aAAa,WAAW,cAAe,WAAW,UAAU,KAAK,IAAI,KAAK,IAAI;AACpF,SAAO,aAAa,SAAS,KAAK,IAAI,SAAS,MAAM,QAAQ;AAC/D;AAEA,IAAO,oBAAQ;","names":[]}
|
|
@@ -9,6 +9,14 @@ export { toast } from 'sonner';
|
|
|
9
9
|
* reader must act on belongs in the page — a toast is dismissed by time, and
|
|
10
10
|
* time is not an acknowledgement.
|
|
11
11
|
*
|
|
12
|
+
* `theme` follows `data-mode`. sonner defaults to `light` and hard-codes the
|
|
13
|
+
* description's colour per theme — `#3f3f3f`, overridden only under
|
|
14
|
+
* `[data-sonner-theme=dark]` — so a Toaster that never passed `theme` put dark
|
|
15
|
+
* grey text on this system's `--paper: #0d0d0d` and every
|
|
16
|
+
* `toast(title, { description })` lost its second half. Pass `theme` yourself
|
|
17
|
+
* and that wins; sonner's own `system` is the one value not to reach for, since
|
|
18
|
+
* it reads the OS rather than the attribute the page is actually painted from.
|
|
19
|
+
*
|
|
12
20
|
* `richColors` stays off by default: sonner's rich palette is not this system's
|
|
13
21
|
* status scale, and turning it on reintroduces chroma the White Reset spends
|
|
14
22
|
* only on state.
|
|
@@ -19,6 +27,6 @@ export { toast } from 'sonner';
|
|
|
19
27
|
* // anywhere
|
|
20
28
|
* toast.success('Saved')
|
|
21
29
|
*/
|
|
22
|
-
declare function Toaster({ position, closeButton, richColors, style, ...rest }: ToasterProps): react.JSX.Element;
|
|
30
|
+
declare function Toaster({ position, closeButton, richColors, theme, style, ...rest }: ToasterProps): react.JSX.Element;
|
|
23
31
|
|
|
24
32
|
export { Toaster, Toaster as default };
|
|
@@ -1,33 +1,56 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useSyncExternalStore } from "react";
|
|
3
4
|
import { Toaster as SonnerToaster, toast } from "sonner";
|
|
4
5
|
const TOKEN_STYLE = {
|
|
5
6
|
"--normal-bg": "var(--paper)",
|
|
6
7
|
"--normal-text": "var(--ink)",
|
|
7
8
|
"--normal-border": "var(--rule-2)",
|
|
9
|
+
"--border-radius": "var(--radius)",
|
|
10
|
+
fontFamily: "var(--sans)"
|
|
11
|
+
};
|
|
12
|
+
const RICH_STYLE = {
|
|
8
13
|
"--success-bg": "var(--paper)",
|
|
9
14
|
"--success-text": "var(--ok)",
|
|
10
15
|
"--success-border": "var(--rule-2)",
|
|
11
16
|
"--error-bg": "var(--paper)",
|
|
12
17
|
"--error-text": "var(--danger)",
|
|
13
|
-
"--error-border": "var(--rule-2)"
|
|
14
|
-
"--border-radius": "var(--radius)",
|
|
15
|
-
fontFamily: "var(--sans)"
|
|
18
|
+
"--error-border": "var(--rule-2)"
|
|
16
19
|
};
|
|
20
|
+
function readMode() {
|
|
21
|
+
if (typeof document === "undefined") return "light";
|
|
22
|
+
return document.documentElement.dataset.mode === "dark" ? "dark" : "light";
|
|
23
|
+
}
|
|
24
|
+
function readModeOnServer() {
|
|
25
|
+
return "light";
|
|
26
|
+
}
|
|
27
|
+
function subscribeToMode(onChange) {
|
|
28
|
+
if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {
|
|
29
|
+
};
|
|
30
|
+
const observer = new MutationObserver(onChange);
|
|
31
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-mode"] });
|
|
32
|
+
return () => observer.disconnect();
|
|
33
|
+
}
|
|
34
|
+
function useMode() {
|
|
35
|
+
return useSyncExternalStore(subscribeToMode, readMode, readModeOnServer);
|
|
36
|
+
}
|
|
17
37
|
function Toaster({
|
|
18
38
|
position = "bottom-right",
|
|
19
39
|
closeButton = true,
|
|
20
40
|
richColors = false,
|
|
41
|
+
theme,
|
|
21
42
|
style,
|
|
22
43
|
...rest
|
|
23
44
|
}) {
|
|
45
|
+
const mode = useMode();
|
|
24
46
|
return /* @__PURE__ */ jsx(
|
|
25
47
|
SonnerToaster,
|
|
26
48
|
{
|
|
27
49
|
position,
|
|
28
50
|
closeButton,
|
|
29
51
|
richColors,
|
|
30
|
-
|
|
52
|
+
theme: theme ?? mode,
|
|
53
|
+
style: { ...TOKEN_STYLE, ...richColors ? RICH_STYLE : null, ...style },
|
|
31
54
|
...rest
|
|
32
55
|
}
|
|
33
56
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["'use client'\n\nimport { Toaster as SonnerToaster, toast } from 'sonner'\nimport type { ToasterProps } from 'sonner'\nimport type { CSSProperties } from 'react'\n\n/**\n * Sonner's own custom properties, pointed at this system's tokens.\n *\n * Set as inline style on the Toaster rather than in a stylesheet: sonner\n * renders its list into a portal at the end of `<body>`, outside whatever\n * element a consumer's CSS is scoped to, and the inline style is the one place\n * guaranteed to reach it.\n *\n * Cast because this `@types/react` `CSSProperties` has no custom-property index\n * signature.\n */\nconst TOKEN_STYLE = {\n '--normal-bg': 'var(--paper)',\n '--normal-text': 'var(--ink)',\n '--normal-border': 'var(--rule-2)',\n '--success-bg': 'var(--paper)',\n '--success-text': 'var(--ok)',\n '--success-border': 'var(--rule-2)',\n '--error-bg': 'var(--paper)',\n '--error-text': 'var(--danger)',\n '--error-border': 'var(--rule-2)',\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["'use client'\n\nimport { useSyncExternalStore } from 'react'\nimport { Toaster as SonnerToaster, toast } from 'sonner'\nimport type { ToasterProps } from 'sonner'\nimport type { CSSProperties } from 'react'\n\n/**\n * Sonner's own custom properties, pointed at this system's tokens.\n *\n * Set as inline style on the Toaster rather than in a stylesheet: sonner\n * renders its list into a portal at the end of `<body>`, outside whatever\n * element a consumer's CSS is scoped to, and the inline style is the one place\n * guaranteed to reach it.\n *\n * These four are the ones sonner reads unconditionally. The status pairs are\n * separate, below, because sonner does not.\n *\n * Cast because this `@types/react` `CSSProperties` has no custom-property index\n * signature.\n */\nconst TOKEN_STYLE = {\n '--normal-bg': 'var(--paper)',\n '--normal-text': 'var(--ink)',\n '--normal-border': 'var(--rule-2)',\n '--border-radius': 'var(--radius)',\n fontFamily: 'var(--sans)',\n} as CSSProperties\n\n/**\n * The status pairs, emitted only when something will read them.\n *\n * sonner scopes `--success-*` and `--error-*` to `[data-rich-colors=true]`, so\n * at this package's default they are four declarations that do nothing while\n * sitting in the element's style attribute looking like the source of a success\n * toast's colour. Conditional rather than deleted: a consumer who turns\n * `richColors` on should still get this system's status scale rather than\n * sonner's.\n */\nconst RICH_STYLE = {\n '--success-bg': 'var(--paper)',\n '--success-text': 'var(--ok)',\n '--success-border': 'var(--rule-2)',\n '--error-bg': 'var(--paper)',\n '--error-text': 'var(--danger)',\n '--error-border': 'var(--rule-2)',\n} as CSSProperties\n\n/**\n * The mode the APP is in, which is not the mode the operating system is in.\n *\n * `data-mode` on `<html>` is this system's switch: a pre-paint script resolves\n * it from storage, falling back to `prefers-color-scheme`, and a reader can\n * override the OS from the page. sonner's own `theme=\"system\"` reads\n * `prefers-color-scheme` directly, so a reader on a dark machine reading a\n * light page would get a dark toast over a white page — the same defect as the\n * one this exists to fix, pointing the other way.\n */\ntype Mode = 'light' | 'dark'\n\nfunction readMode(): Mode {\n if (typeof document === 'undefined') return 'light'\n return document.documentElement.dataset.mode === 'dark' ? 'dark' : 'light'\n}\n\n/** Light on a server, which is what the pre-paint script also assumes. */\nfunction readModeOnServer(): Mode {\n return 'light'\n}\n\nfunction subscribeToMode(onChange: () => void): () => void {\n if (typeof document === 'undefined' || typeof MutationObserver === 'undefined') return () => {}\n const observer = new MutationObserver(onChange)\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-mode'] })\n return () => observer.disconnect()\n}\n\n/**\n * Observed rather than read once: the Toaster is mounted at the app root and\n * outlives every theme switch a reader makes under it.\n */\nfunction useMode(): Mode {\n return useSyncExternalStore(subscribeToMode, readMode, readModeOnServer)\n}\n\n/**\n * Transient confirmations, mounted once near the app root.\n *\n * A toast is for something that succeeded and needs no response. Anything the\n * reader must act on belongs in the page — a toast is dismissed by time, and\n * time is not an acknowledgement.\n *\n * `theme` follows `data-mode`. sonner defaults to `light` and hard-codes the\n * description's colour per theme — `#3f3f3f`, overridden only under\n * `[data-sonner-theme=dark]` — so a Toaster that never passed `theme` put dark\n * grey text on this system's `--paper: #0d0d0d` and every\n * `toast(title, { description })` lost its second half. Pass `theme` yourself\n * and that wins; sonner's own `system` is the one value not to reach for, since\n * it reads the OS rather than the attribute the page is actually painted from.\n *\n * `richColors` stays off by default: sonner's rich palette is not this system's\n * status scale, and turning it on reintroduces chroma the White Reset spends\n * only on state.\n *\n * @example\n * // app root\n * <Toaster />\n * // anywhere\n * toast.success('Saved')\n */\nexport function Toaster({\n position = 'bottom-right',\n closeButton = true,\n richColors = false,\n theme,\n style,\n ...rest\n}: ToasterProps) {\n const mode = useMode()\n\n return (\n <SonnerToaster\n position={position}\n closeButton={closeButton}\n richColors={richColors}\n theme={theme ?? mode}\n style={{ ...TOKEN_STYLE, ...(richColors ? RICH_STYLE : null), ...style }}\n {...rest}\n />\n )\n}\n\nexport { toast }\nexport default Toaster\n"],"mappings":";AAyHI;AAvHJ,SAAS,4BAA4B;AACrC,SAAS,WAAW,eAAe,aAAa;AAkBhD,MAAM,cAAc;AAAA,EAClB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,YAAY;AACd;AAYA,MAAM,aAAa;AAAA,EACjB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AACpB;AAcA,SAAS,WAAiB;AACxB,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,SAAS,gBAAgB,QAAQ,SAAS,SAAS,SAAS;AACrE;AAGA,SAAS,mBAAyB;AAChC,SAAO;AACT;AAEA,SAAS,gBAAgB,UAAkC;AACzD,MAAI,OAAO,aAAa,eAAe,OAAO,qBAAqB,YAAa,QAAO,MAAM;AAAA,EAAC;AAC9F,QAAM,WAAW,IAAI,iBAAiB,QAAQ;AAC9C,WAAS,QAAQ,SAAS,iBAAiB,EAAE,YAAY,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC;AAC/F,SAAO,MAAM,SAAS,WAAW;AACnC;AAMA,SAAS,UAAgB;AACvB,SAAO,qBAAqB,iBAAiB,UAAU,gBAAgB;AACzE;AA2BO,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiB;AACf,QAAM,OAAO,QAAQ;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,OAAO,EAAE,GAAG,aAAa,GAAI,aAAa,aAAa,MAAO,GAAG,MAAM;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,IAAO,gBAAQ;","names":[]}
|
|
@@ -21,13 +21,18 @@ type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>;
|
|
|
21
21
|
* Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.
|
|
22
22
|
* A toggle group changes a value.
|
|
23
23
|
*
|
|
24
|
+
* Inside a `Field` the strip takes its name from that label, by pointing back at
|
|
25
|
+
* it — the root is a div, and `<label for>` does not bind to one, so the words
|
|
26
|
+
* above it do not click through. Standing alone it still needs its own
|
|
27
|
+
* `aria-label`.
|
|
28
|
+
*
|
|
24
29
|
* @example
|
|
25
30
|
* <ToggleGroup type="single" defaultValue="grid" aria-label="Layout">
|
|
26
31
|
* <ToggleGroupItem value="grid">Grid</ToggleGroupItem>
|
|
27
32
|
* <ToggleGroupItem value="list">List</ToggleGroupItem>
|
|
28
33
|
* </ToggleGroup>
|
|
29
34
|
*/
|
|
30
|
-
declare function ToggleGroup({ className, children, ...props }: ToggleGroupProps): react.JSX.Element;
|
|
35
|
+
declare function ToggleGroup({ className, children, 'aria-required': ariaRequired, ...props }: ToggleGroupProps): react.JSX.Element;
|
|
31
36
|
type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>;
|
|
32
37
|
/**
|
|
33
38
|
* One segment.
|
|
@@ -3,9 +3,17 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
4
4
|
import { createContext, useContext, useState } from "react";
|
|
5
5
|
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { useFieldControl } from "../Field/field-control.js";
|
|
6
7
|
import { useSelectionIndicator } from "../../lib/useSelectionIndicator.js";
|
|
7
8
|
const SingleValueContext = createContext(null);
|
|
8
|
-
function ToggleGroup({
|
|
9
|
+
function ToggleGroup({
|
|
10
|
+
className,
|
|
11
|
+
children,
|
|
12
|
+
"aria-required": ariaRequired,
|
|
13
|
+
...props
|
|
14
|
+
}) {
|
|
15
|
+
const field = useFieldControl();
|
|
16
|
+
const named = props["aria-label"] != null || props["aria-labelledby"] != null;
|
|
9
17
|
const single = props.type === "single";
|
|
10
18
|
const [uncontrolled, setUncontrolled] = useState(
|
|
11
19
|
(single ? props.defaultValue : void 0) ?? ""
|
|
@@ -16,6 +24,8 @@ function ToggleGroup({ className, children, ...props }) {
|
|
|
16
24
|
ToggleGroupPrimitive.Root,
|
|
17
25
|
{
|
|
18
26
|
ref,
|
|
27
|
+
"aria-labelledby": named ? void 0 : field?.labelId,
|
|
28
|
+
"aria-required": props.type === "single" ? ariaRequired : void 0,
|
|
19
29
|
className: cn(
|
|
20
30
|
// `w-fit` as well as `inline-flex`: a flex or grid parent stretches its
|
|
21
31
|
// children to the track by default, and `inline-flex` does not opt out
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["'use client'\n\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useSelectionIndicator } from '../../lib/useSelectionIndicator'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>\n\n/** Lets an item know whether the group tracks one value or several. */\nconst SingleValueContext = createContext<string | null>(null)\n\n/**\n * A segmented control: several options, one strip.\n *\n * `type=\"single\"` is a choice — Radix gives it radio semantics, and it is the\n * right shape for a view switcher or a density setting. `type=\"multiple\"` is a\n * set of independent toggles, which is a different thing announced differently;\n * choosing the wrong one is how a \"filter by tag\" control ends up telling a\n * screen reader that picking one tag unpicks the others.\n *\n * The two look different on purpose. A single-value strip moves ONE filled pill\n * between its options, so the eye follows a thing travelling; a multiple-value\n * strip fills each pressed option separately, because there is no single\n * selection to travel. Two people looking at a screenshot should be able to\n * tell which kind they are looking at, and before this they could not.\n *\n * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.\n * A toggle group changes a value.\n *\n * @example\n * <ToggleGroup type=\"single\" defaultValue=\"grid\" aria-label=\"Layout\">\n * <ToggleGroupItem value=\"grid\">Grid</ToggleGroupItem>\n * <ToggleGroupItem value=\"list\">List</ToggleGroupItem>\n * </ToggleGroup>\n */\nexport function ToggleGroup({
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["'use client'\n\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useFieldControl } from '../Field/field-control'\nimport { useSelectionIndicator } from '../../lib/useSelectionIndicator'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>\n\n/** Lets an item know whether the group tracks one value or several. */\nconst SingleValueContext = createContext<string | null>(null)\n\n/**\n * A segmented control: several options, one strip.\n *\n * `type=\"single\"` is a choice — Radix gives it radio semantics, and it is the\n * right shape for a view switcher or a density setting. `type=\"multiple\"` is a\n * set of independent toggles, which is a different thing announced differently;\n * choosing the wrong one is how a \"filter by tag\" control ends up telling a\n * screen reader that picking one tag unpicks the others.\n *\n * The two look different on purpose. A single-value strip moves ONE filled pill\n * between its options, so the eye follows a thing travelling; a multiple-value\n * strip fills each pressed option separately, because there is no single\n * selection to travel. Two people looking at a screenshot should be able to\n * tell which kind they are looking at, and before this they could not.\n *\n * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.\n * A toggle group changes a value.\n *\n * Inside a `Field` the strip takes its name from that label, by pointing back at\n * it — the root is a div, and `<label for>` does not bind to one, so the words\n * above it do not click through. Standing alone it still needs its own\n * `aria-label`.\n *\n * @example\n * <ToggleGroup type=\"single\" defaultValue=\"grid\" aria-label=\"Layout\">\n * <ToggleGroupItem value=\"grid\">Grid</ToggleGroupItem>\n * <ToggleGroupItem value=\"list\">List</ToggleGroupItem>\n * </ToggleGroup>\n */\nexport function ToggleGroup({\n className,\n children,\n 'aria-required': ariaRequired,\n ...props\n}: ToggleGroupProps) {\n const field = useFieldControl()\n const named = props['aria-label'] != null || props['aria-labelledby'] != null\n\n // Tracked here rather than left to Radix alone, because the sliding pill has\n // to know which item to measure — and an uncontrolled group never tells\n // anyone what it picked.\n const single = props.type === 'single'\n const [uncontrolled, setUncontrolled] = useState<string>(\n (single ? (props.defaultValue as string | undefined) : undefined) ?? '',\n )\n const value = single ? ((props.value as string | undefined) ?? uncontrolled) : null\n const [ref, indicator] = useSelectionIndicator<HTMLDivElement>(value)\n\n const root = (\n <ToggleGroupPrimitive.Root\n ref={ref}\n aria-labelledby={named ? undefined : field?.labelId}\n // Only on the single-value strip. Radix gives that one role=\"radiogroup\",\n // which takes aria-required; a multiple-value strip is a role=\"toolbar\",\n // where the attribute is not allowed at all — so a Field's `required`\n // reaches one shape of this control and not the other.\n aria-required={props.type === 'single' ? ariaRequired : undefined}\n className={cn(\n // `w-fit` as well as `inline-flex`: a flex or grid parent stretches its\n // children to the track by default, and `inline-flex` does not opt out\n // of that. Without it the strip grew to whatever the widest sibling was\n // — a label above it — and left dead space after the last segment.\n 'relative inline-flex w-fit items-center gap-1 rounded-(--radius-pill) border border-(--rule-2) p-1',\n className,\n )}\n {...props}\n onValueChange={(next: never) => {\n if (single) setUncontrolled((next as string) ?? '')\n ;(props.onValueChange as ((v: never) => void) | undefined)?.(next)\n }}\n >\n {single && indicator.ready && (\n <span\n aria-hidden\n data-m22-animated\n className=\"absolute rounded-(--radius-pill) bg-(--accent) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) motion-reduce:transition-none\"\n style={{\n transform: `translate(${indicator.offset}px, ${indicator.top}px)`,\n width: indicator.width,\n height: indicator.height,\n insetInlineStart: 0,\n top: 0,\n }}\n />\n )}\n {children}\n </ToggleGroupPrimitive.Root>\n )\n\n return single ? (\n <SingleValueContext.Provider value={value}>{root}</SingleValueContext.Provider>\n ) : (\n root\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>\n\n/**\n * One segment.\n *\n * In a single-value group the item draws no background of its own — the\n * travelling pill behind it does — so it only changes ink. In a multiple-value\n * group it fills, because there is nothing travelling.\n */\nexport function ToggleGroupItem({ className, value, ...props }: ToggleGroupItemProps) {\n const selected = useContext(SingleValueContext)\n const isSingle = selected !== null\n const active = isSingle && selected === value\n\n return (\n <ToggleGroupPrimitive.Item\n value={value}\n data-indicator-active={active ? 'true' : undefined}\n className={cn(\n 'relative z-1 inline-flex min-h-(--control-h-sm) items-center justify-center gap-2 rounded-(--radius-pill) px-3.5 text-sm transition-colors duration-(--duration-fast) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n isSingle\n ? active\n ? 'text-(--accent-foreground)'\n : 'text-(--ink-3-aa) hover:text-(--ink)'\n : 'text-(--ink-3-aa) hover:text-(--ink) data-[state=on]:bg-(--accent) data-[state=on]:text-(--accent-foreground)',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport default ToggleGroup\n"],"mappings":";AA8DI,SAuBI,KAvBJ;AA5DJ,YAAY,0BAA0B;AACtC,SAAS,eAAe,YAAY,gBAAqC;AACzE,SAAS,UAAU;AACnB,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AAKtC,MAAM,qBAAqB,cAA6B,IAAI;AA+BrD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,GAAG;AACL,GAAqB;AACnB,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,QAAQ,MAAM,YAAY,KAAK,QAAQ,MAAM,iBAAiB,KAAK;AAKzE,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,CAAC,cAAc,eAAe,IAAI;AAAA,KACrC,SAAU,MAAM,eAAsC,WAAc;AAAA,EACvE;AACA,QAAM,QAAQ,SAAW,MAAM,SAAgC,eAAgB;AAC/E,QAAM,CAAC,KAAK,SAAS,IAAI,sBAAsC,KAAK;AAEpE,QAAM,OACJ;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,mBAAiB,QAAQ,SAAY,OAAO;AAAA,MAK5C,iBAAe,MAAM,SAAS,WAAW,eAAe;AAAA,MACxD,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MACJ,eAAe,CAAC,SAAgB;AAC9B,YAAI,OAAQ,iBAAiB,QAAmB,EAAE;AACjD,QAAC,MAAM,gBAAqD,IAAI;AAAA,MACnE;AAAA,MAEC;AAAA,kBAAU,UAAU,SACnB;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,qBAAiB;AAAA,YACjB,WAAU;AAAA,YACV,OAAO;AAAA,cACL,WAAW,aAAa,UAAU,MAAM,OAAO,UAAU,GAAG;AAAA,cAC5D,OAAO,UAAU;AAAA,cACjB,QAAQ,UAAU;AAAA,cAClB,kBAAkB;AAAA,cAClB,KAAK;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QAED;AAAA;AAAA;AAAA,EACH;AAGF,SAAO,SACL,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,gBAAK,IAEjD;AAEJ;AAWO,SAAS,gBAAgB,EAAE,WAAW,OAAO,GAAG,MAAM,GAAyB;AACpF,QAAM,WAAW,WAAW,kBAAkB;AAC9C,QAAM,WAAW,aAAa;AAC9B,QAAM,SAAS,YAAY,aAAa;AAExC,SACE;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,yBAAuB,SAAS,SAAS;AAAA,MACzC,WAAW;AAAA,QACT;AAAA,QACA,WACI,SACE,+BACA,yCACF;AAAA,QACJ;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,sBAAQ;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Which edge the bar sticks to, or neither.
|
|
6
|
+
*
|
|
7
|
+
* `bottom` is the form footer — the actions stay in reach while a long form
|
|
8
|
+
* scrolls under them. `top` is the filter bar over a list. `static` is the same
|
|
9
|
+
* bar with no stickiness, for a short page or a bar inside a dialog that is
|
|
10
|
+
* already the height of its content.
|
|
11
|
+
*/
|
|
12
|
+
type ToolbarPosition = 'bottom' | 'top' | 'static';
|
|
13
|
+
type ToolbarAlign = 'start' | 'center' | 'end' | 'between';
|
|
14
|
+
interface ToolbarProps extends HTMLAttributes<HTMLDivElement> {
|
|
15
|
+
/**
|
|
16
|
+
* Names the bar for a screen reader — "Form actions", "List filters".
|
|
17
|
+
* Required, because a group with no name is announced as "group" and a page
|
|
18
|
+
* with two of them is a page with two identical announcements.
|
|
19
|
+
*/
|
|
20
|
+
label: string;
|
|
21
|
+
/** Which edge the bar sticks to. See {@link ToolbarPosition}. */
|
|
22
|
+
position?: ToolbarPosition;
|
|
23
|
+
/** Where the contents sit along the inline axis. */
|
|
24
|
+
align?: ToolbarAlign;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The bar of actions at the edge of a working surface.
|
|
29
|
+
*
|
|
30
|
+
* Two page templates built the same thing independently — a sticky strip on
|
|
31
|
+
* `--paper` with a rule along the edge it sticks to — which is the signal that
|
|
32
|
+
* it belongs here rather than in each of them.
|
|
33
|
+
*
|
|
34
|
+
* The ground is opaque `--paper` and not a blur. Content scrolls UNDER this
|
|
35
|
+
* bar, so anything translucent puts the last row of a table behind the submit
|
|
36
|
+
* button and makes both unreadable; `FloatingIconButton` blurs because it
|
|
37
|
+
* floats over a gap, which is a different problem.
|
|
38
|
+
*
|
|
39
|
+
* It is not `role="toolbar"`. That role's contract is a single tab stop with
|
|
40
|
+
* arrow keys moving between the controls inside it, and this implements no such
|
|
41
|
+
* thing — declaring the role without the behaviour tells a screen-reader user
|
|
42
|
+
* to press arrow keys that do nothing. It is a named `group`, so the controls
|
|
43
|
+
* keep their own places in the tab order and the bar is still announced.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <Toolbar label="Form actions">
|
|
47
|
+
* <Button variant="secondary">Cancel</Button>
|
|
48
|
+
* <Button type="submit">Save changes</Button>
|
|
49
|
+
* </Toolbar>
|
|
50
|
+
* @example
|
|
51
|
+
* <Toolbar label="List filters" position="top" align="between">…</Toolbar>
|
|
52
|
+
*/
|
|
53
|
+
declare function Toolbar({ label, position, align, className, children, ...rest }: ToolbarProps): react.JSX.Element;
|
|
54
|
+
|
|
55
|
+
export { Toolbar, type ToolbarAlign, type ToolbarPosition, type ToolbarProps, Toolbar as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
const POSITION = {
|
|
4
|
+
bottom: "sticky bottom-0 z-(--z-sticky) border-t border-(--rule-2)",
|
|
5
|
+
top: "sticky top-0 z-(--z-sticky) border-b border-(--rule-2)",
|
|
6
|
+
static: "border-t border-(--rule-2)"
|
|
7
|
+
};
|
|
8
|
+
const ALIGN = {
|
|
9
|
+
start: "justify-start",
|
|
10
|
+
center: "justify-center",
|
|
11
|
+
end: "justify-end",
|
|
12
|
+
between: "justify-between"
|
|
13
|
+
};
|
|
14
|
+
function Toolbar({
|
|
15
|
+
label,
|
|
16
|
+
position = "bottom",
|
|
17
|
+
align = "end",
|
|
18
|
+
className,
|
|
19
|
+
children,
|
|
20
|
+
...rest
|
|
21
|
+
}) {
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
"div",
|
|
24
|
+
{
|
|
25
|
+
role: "group",
|
|
26
|
+
"aria-label": label,
|
|
27
|
+
className: cn(
|
|
28
|
+
"flex flex-wrap items-center gap-3 bg-(--paper) px-4 py-3",
|
|
29
|
+
POSITION[position],
|
|
30
|
+
ALIGN[align],
|
|
31
|
+
className
|
|
32
|
+
),
|
|
33
|
+
...rest,
|
|
34
|
+
children
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
var Toolbar_default = Toolbar;
|
|
39
|
+
export {
|
|
40
|
+
Toolbar,
|
|
41
|
+
Toolbar_default as default
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=Toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Toolbar/Toolbar.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * Which edge the bar sticks to, or neither.\n *\n * `bottom` is the form footer — the actions stay in reach while a long form\n * scrolls under them. `top` is the filter bar over a list. `static` is the same\n * bar with no stickiness, for a short page or a bar inside a dialog that is\n * already the height of its content.\n */\nexport type ToolbarPosition = 'bottom' | 'top' | 'static'\n\nexport type ToolbarAlign = 'start' | 'center' | 'end' | 'between'\n\nexport interface ToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Names the bar for a screen reader — \"Form actions\", \"List filters\".\n * Required, because a group with no name is announced as \"group\" and a page\n * with two of them is a page with two identical announcements.\n */\n label: string\n /** Which edge the bar sticks to. See {@link ToolbarPosition}. */\n position?: ToolbarPosition\n /** Where the contents sit along the inline axis. */\n align?: ToolbarAlign\n children: ReactNode\n}\n\nconst POSITION: Record<ToolbarPosition, string> = {\n bottom: 'sticky bottom-0 z-(--z-sticky) border-t border-(--rule-2)',\n top: 'sticky top-0 z-(--z-sticky) border-b border-(--rule-2)',\n static: 'border-t border-(--rule-2)',\n}\n\nconst ALIGN: Record<ToolbarAlign, string> = {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n between: 'justify-between',\n}\n\n/**\n * The bar of actions at the edge of a working surface.\n *\n * Two page templates built the same thing independently — a sticky strip on\n * `--paper` with a rule along the edge it sticks to — which is the signal that\n * it belongs here rather than in each of them.\n *\n * The ground is opaque `--paper` and not a blur. Content scrolls UNDER this\n * bar, so anything translucent puts the last row of a table behind the submit\n * button and makes both unreadable; `FloatingIconButton` blurs because it\n * floats over a gap, which is a different problem.\n *\n * It is not `role=\"toolbar\"`. That role's contract is a single tab stop with\n * arrow keys moving between the controls inside it, and this implements no such\n * thing — declaring the role without the behaviour tells a screen-reader user\n * to press arrow keys that do nothing. It is a named `group`, so the controls\n * keep their own places in the tab order and the bar is still announced.\n *\n * @example\n * <Toolbar label=\"Form actions\">\n * <Button variant=\"secondary\">Cancel</Button>\n * <Button type=\"submit\">Save changes</Button>\n * </Toolbar>\n * @example\n * <Toolbar label=\"List filters\" position=\"top\" align=\"between\">…</Toolbar>\n */\nexport function Toolbar({\n label,\n position = 'bottom',\n align = 'end',\n className,\n children,\n ...rest\n}: ToolbarProps) {\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={cn(\n 'flex flex-wrap items-center gap-3 bg-(--paper) px-4 py-3',\n POSITION[position],\n ALIGN[align],\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nexport default Toolbar\n"],"mappings":"AA6EI;AA5EJ,SAAS,UAAU;AA4BnB,MAAM,WAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,QAAQ;AACV;AAEA,MAAM,QAAsC;AAAA,EAC1C,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,SAAS;AACX;AA4BO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA,WAAW;AAAA,EACX,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiB;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB,MAAM,KAAK;AAAA,QACX;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,kBAAQ;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { FigureChrome } from '../lib/frame.js';
|
|
3
|
+
import { ArchitectureSpec } from '../spec.js';
|
|
4
|
+
import '../lib/geometry.js';
|
|
5
|
+
|
|
6
|
+
interface ArchitectureFigureProps extends FigureChrome {
|
|
7
|
+
spec: ArchitectureSpec;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A component map: services, datastores, boundaries, and what talks to what.
|
|
11
|
+
*
|
|
12
|
+
* Takes the same JSON an archify `architecture` specification carries —
|
|
13
|
+
* `components`, `boundaries`, `connections` — and draws it in this system's own
|
|
14
|
+
* terms: paper plates on a hairline, one reversed plate for the component the
|
|
15
|
+
* diagram is about, and seven drawn sigils where archify uses seven hues.
|
|
16
|
+
*
|
|
17
|
+
* IT RENDERS ON A SERVER because every position is already in the
|
|
18
|
+
* specification. A component gives a `row` and a `col` into a grid whose cell
|
|
19
|
+
* size is either declared or defaulted, or it gives an absolute `pos` — nothing
|
|
20
|
+
* here is solved for, relaxed, or measured. So the markup is a pure function of
|
|
21
|
+
* the input, it is identical on the server and in the browser, and there is no
|
|
22
|
+
* layout shift on hydration because there is no layout to do.
|
|
23
|
+
*
|
|
24
|
+
* A component that declares NEITHER flows: it takes the next free cell in
|
|
25
|
+
* declaration order, wrapping at `layout.cols`. That is still arithmetic on
|
|
26
|
+
* numbers the specification carries rather than a solver — and the alternative
|
|
27
|
+
* was every unplaced component defaulting to row 0, column 0 and stacking into
|
|
28
|
+
* one plate.
|
|
29
|
+
*
|
|
30
|
+
* BOUNDARIES ARE DRAWN FIRST, AND DRAWN DIFFERENTLY. A `region` is where
|
|
31
|
+
* something RUNS — a VPC, a zone, a cluster — and is a solid frame. A
|
|
32
|
+
* `security-group` is what may REACH it, and is dashed. That is not decoration:
|
|
33
|
+
* an infrastructure diagram is very often read for exactly one of those two
|
|
34
|
+
* questions, and a reader should be able to tell which line answers which
|
|
35
|
+
* without reading either label.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* <ArchitectureFigure
|
|
39
|
+
* spec={{
|
|
40
|
+
* meta: { title: 'Request path' },
|
|
41
|
+
* components: [
|
|
42
|
+
* { id: 'cdn', type: 'cloud', label: 'CloudFront', row: 0, col: 0 },
|
|
43
|
+
* { id: 'api', type: 'backend', label: 'FastAPI', sublabel: 'ECS', row: 0, col: 1 },
|
|
44
|
+
* { id: 'db', type: 'database', label: 'Postgres', row: 0, col: 2 },
|
|
45
|
+
* ],
|
|
46
|
+
* connections: [
|
|
47
|
+
* { from: 'cdn', to: 'api', label: 'HTTPS' },
|
|
48
|
+
* { from: 'api', to: 'db', label: 'SQL' },
|
|
49
|
+
* ],
|
|
50
|
+
* }}
|
|
51
|
+
* />
|
|
52
|
+
*/
|
|
53
|
+
declare function ArchitectureFigure({ spec, className, legend, cards, heading, activeIds, onSelectNode, }: ArchitectureFigureProps): react.JSX.Element;
|
|
54
|
+
|
|
55
|
+
export { ArchitectureFigure, type ArchitectureFigureProps, ArchitectureFigure as default };
|