@misoto22/design 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +87 -0
- package/CLAUDE.md +1 -0
- package/README.md +50 -5
- package/bin/misoto22-design.mjs +59 -13
- package/dist/agent/Accordion.md +24 -1
- package/dist/agent/Alert.md +23 -1
- package/dist/agent/AppShell.md +30 -2
- package/dist/agent/ArchitectureFigure.md +25 -2
- package/dist/agent/AreaChart.md +27 -2
- package/dist/agent/Article.md +26 -3
- package/dist/agent/AspectRatio.md +57 -0
- package/dist/agent/Avatar.md +25 -5
- package/dist/agent/Badge.md +22 -1
- package/dist/agent/BarChart.md +29 -2
- package/dist/agent/BarList.md +27 -1
- package/dist/agent/BigNumber.md +26 -2
- package/dist/agent/BoxPlot.md +24 -1
- package/dist/agent/Breadcrumb.md +24 -2
- package/dist/agent/BulletChart.md +23 -1
- package/dist/agent/Button.md +25 -1
- package/dist/agent/Calendar.md +37 -3
- package/dist/agent/Card.md +24 -2
- package/dist/agent/Checkbox.md +23 -2
- package/dist/agent/Code.md +50 -0
- package/dist/agent/CodeBlock.md +74 -0
- package/dist/agent/Collapsible.md +22 -1
- package/dist/agent/ColorPicker.md +75 -0
- package/dist/agent/Combobox.md +29 -3
- package/dist/agent/Command.md +25 -2
- package/dist/agent/ComposedChart.md +26 -2
- package/dist/agent/ContextMenu.md +37 -4
- package/dist/agent/DataflowFigure.md +22 -1
- package/dist/agent/DatePicker.md +34 -6
- package/dist/agent/DescriptionList.md +68 -0
- package/dist/agent/Diagram.md +27 -3
- package/dist/agent/DiagramCanvas.md +24 -1
- package/dist/agent/DiagramExportMenu.md +29 -3
- package/dist/agent/DiagramInspector.md +23 -1
- package/dist/agent/DiagramLegend.md +22 -1
- package/dist/agent/DiagramMinimap.md +24 -4
- package/dist/agent/DiagramToolbar.md +23 -1
- package/dist/agent/Dialog.md +26 -3
- package/dist/agent/DropdownMenu.md +45 -6
- package/dist/agent/EmptyState.md +26 -1
- package/dist/agent/ErrorState.md +27 -2
- package/dist/agent/Facet.md +25 -1
- package/dist/agent/Field.md +45 -4
- package/dist/agent/FigureBand.md +24 -1
- package/dist/agent/FloatingIconButton.md +23 -1
- package/dist/agent/FunnelChart.md +23 -1
- package/dist/agent/Heading.md +64 -0
- package/dist/agent/Heatmap.md +25 -1
- package/dist/agent/Histogram.md +26 -2
- package/dist/agent/Input.md +22 -1
- package/dist/agent/Kbd.md +19 -1
- package/dist/agent/LifecycleFigure.md +22 -1
- package/dist/agent/LineChart.md +26 -2
- package/dist/agent/LinkArrow.md +20 -1
- package/dist/agent/Markdown.md +68 -0
- package/dist/agent/NativeSelect.md +23 -2
- package/dist/agent/NavItem.md +21 -1
- package/dist/agent/NumberField.md +72 -0
- package/dist/agent/Pagination.md +28 -2
- package/dist/agent/PieChart.md +26 -2
- package/dist/agent/Popover.md +23 -1
- package/dist/agent/Progress.md +27 -3
- package/dist/agent/RadarChart.md +26 -2
- package/dist/agent/RadialChart.md +26 -3
- package/dist/agent/RadioGroup.md +23 -2
- package/dist/agent/SankeyChart.md +25 -2
- package/dist/agent/ScatterChart.md +27 -2
- package/dist/agent/ScrollArea.md +24 -3
- package/dist/agent/SearchableMenu.md +23 -1
- package/dist/agent/Select.md +29 -3
- package/dist/agent/Separator.md +28 -4
- package/dist/agent/SequenceFigure.md +23 -1
- package/dist/agent/Sheet.md +25 -2
- package/dist/agent/Sidebar.md +193 -0
- package/dist/agent/Skeleton.md +24 -2
- package/dist/agent/Slider.md +31 -4
- package/dist/agent/Sparkline.md +23 -1
- package/dist/agent/Spinner.md +24 -2
- package/dist/agent/StatusDot.md +20 -1
- package/dist/agent/StatusPill.md +28 -2
- package/dist/agent/Steps.md +24 -1
- package/dist/agent/Switch.md +21 -1
- package/dist/agent/Table.md +28 -3
- package/dist/agent/Tabs.md +24 -2
- package/dist/agent/Tag.md +40 -9
- package/dist/agent/Text.md +65 -0
- package/dist/agent/Textarea.md +20 -1
- package/dist/agent/Timestamp.md +64 -0
- package/dist/agent/Toast.md +26 -2
- package/dist/agent/ToggleGroup.md +24 -2
- package/dist/agent/Toolbar.md +71 -0
- package/dist/agent/Tooltip.md +23 -1
- package/dist/agent/TreemapChart.md +24 -1
- package/dist/agent/WaterfallChart.md +24 -1
- package/dist/agent/WorkflowFigure.md +24 -2
- package/dist/agent/catalog.json +5915 -699
- package/dist/agent/index.md +20 -8
- package/dist/article.css +16 -4
- package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
- package/dist/charts/AreaChart/AreaChart.js +12 -13
- package/dist/charts/AreaChart/AreaChart.js.map +1 -1
- package/dist/charts/BarChart/BarChart.d.ts +14 -3
- package/dist/charts/BarChart/BarChart.js +20 -12
- package/dist/charts/BarChart/BarChart.js.map +1 -1
- package/dist/charts/BarList/BarList.d.ts +9 -1
- package/dist/charts/BarList/BarList.js +9 -1
- package/dist/charts/BarList/BarList.js.map +1 -1
- package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
- package/dist/charts/BigNumber/BigNumber.js +25 -5
- package/dist/charts/BigNumber/BigNumber.js.map +1 -1
- package/dist/charts/BoxPlot/BoxPlot.js +4 -2
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
- package/dist/charts/BulletChart/BulletChart.js +44 -9
- package/dist/charts/BulletChart/BulletChart.js.map +1 -1
- package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
- package/dist/charts/ComposedChart/ComposedChart.js +10 -10
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
- package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
- package/dist/charts/FunnelChart/FunnelChart.js +6 -16
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
- package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
- package/dist/charts/Heatmap/Heatmap.js +20 -11
- package/dist/charts/Heatmap/Heatmap.js.map +1 -1
- package/dist/charts/Histogram/Histogram.d.ts +24 -1
- package/dist/charts/Histogram/Histogram.js +43 -11
- package/dist/charts/Histogram/Histogram.js.map +1 -1
- package/dist/charts/LineChart/LineChart.d.ts +9 -2
- package/dist/charts/LineChart/LineChart.js +11 -12
- package/dist/charts/LineChart/LineChart.js.map +1 -1
- package/dist/charts/PieChart/PieChart.d.ts +15 -3
- package/dist/charts/PieChart/PieChart.js +14 -6
- package/dist/charts/PieChart/PieChart.js.map +1 -1
- package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
- package/dist/charts/RadarChart/RadarChart.js +15 -11
- package/dist/charts/RadarChart/RadarChart.js.map +1 -1
- package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
- package/dist/charts/RadialChart/RadialChart.js +28 -6
- package/dist/charts/RadialChart/RadialChart.js.map +1 -1
- package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
- package/dist/charts/SankeyChart/SankeyChart.js +14 -6
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
- package/dist/charts/ScatterChart/ScatterChart.js +21 -15
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
- package/dist/charts/Sparkline/Sparkline.js +5 -3
- package/dist/charts/Sparkline/Sparkline.js.map +1 -1
- package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
- package/dist/charts/TreemapChart/TreemapChart.js +20 -11
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
- package/dist/charts/lib/export.d.ts +1 -0
- package/dist/charts/lib/figure.d.ts +21 -1
- package/dist/charts/lib/figure.js +5 -2
- package/dist/charts/lib/figure.js.map +1 -1
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +1 -0
- package/dist/components/Accordion/Accordion.js +8 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/AppShell/AppShell.d.ts +6 -0
- package/dist/components/AppShell/AppShell.js +34 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +11 -4
- package/dist/components/Article/Article.js +13 -0
- package/dist/components/Article/Article.js.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +12 -3
- package/dist/components/Avatar/Avatar.js +6 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +14 -0
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +29 -3
- package/dist/components/Calendar/Calendar.js +60 -12
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +5 -2
- package/dist/components/Checkbox/Checkbox.js +12 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +141 -0
- package/dist/components/CodeBlock/CodeBlock.js +123 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +10 -2
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +15 -1
- package/dist/components/Combobox/Combobox.js +25 -5
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.d.ts +4 -2
- package/dist/components/Command/Command.js +14 -2
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
- package/dist/components/ContextMenu/ContextMenu.js +33 -3
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +36 -4
- package/dist/components/DatePicker/DatePicker.js +55 -12
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +8 -3
- package/dist/components/Diagram/Diagram.js +82 -10
- package/dist/components/Diagram/Diagram.js.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +18 -3
- package/dist/components/Dialog/Dialog.js +21 -3
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
- package/dist/components/DropdownMenu/DropdownMenu.js +33 -3
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +25 -1
- package/dist/components/EmptyState/EmptyState.js +3 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.d.ts +22 -1
- package/dist/components/ErrorState/ErrorState.js +12 -3
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +70 -3
- package/dist/components/Field/Field.js +53 -12
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +2 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +6 -0
- package/dist/components/NativeSelect/NativeSelect.js +2 -3
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/NavItem/NavItem.js +1 -1
- package/dist/components/NavItem/NavItem.js.map +1 -1
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +24 -1
- package/dist/components/Pagination/Pagination.js +6 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Progress/Progress.d.ts +17 -5
- package/dist/components/Progress/Progress.js +18 -6
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroup.js +11 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
- package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
- package/dist/components/Select/Select.d.ts +18 -2
- package/dist/components/Select/Select.js +21 -4
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +21 -3
- package/dist/components/Separator/Separator.js +9 -1
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +3 -0
- package/dist/components/Sheet/Sheet.js +12 -3
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.d.ts +349 -0
- package/dist/components/Sidebar/Sidebar.js +455 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +8 -1
- package/dist/components/Skeleton/Skeleton.js +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +42 -3
- package/dist/components/Slider/Slider.js +121 -30
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +8 -0
- package/dist/components/Spinner/Spinner.js +3 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/StatusPill/StatusPill.d.ts +5 -0
- package/dist/components/StatusPill/StatusPill.js +6 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -1
- package/dist/components/Table/Table.d.ts +20 -0
- package/dist/components/Table/Table.js +3 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tabs/Tabs.js +7 -1
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tag/Tag.d.ts +68 -9
- package/dist/components/Tag/Tag.js +50 -10
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +9 -1
- package/dist/components/Toast/Toast.js +27 -4
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +6 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +48 -8
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -1
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +21 -2
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -1
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +14 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +14 -7
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -1
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +38 -4
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +14 -16
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -1
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +2 -2
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -1
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +23 -7
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +45 -18
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -1
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +44 -12
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -1
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +35 -5
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +3 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +76 -28
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -1
- package/dist/diagrams/index.d.ts +1 -0
- package/dist/diagrams/index.js +10 -0
- package/dist/diagrams/index.js.map +1 -1
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +48 -7
- package/dist/diagrams/lib/frame.js +17 -2
- package/dist/diagrams/lib/frame.js.map +1 -1
- package/dist/diagrams/lib/route.d.ts +22 -1
- package/dist/diagrams/lib/route.js +24 -1
- package/dist/diagrams/lib/route.js.map +1 -1
- package/dist/diagrams/lib/wires.js +9 -5
- package/dist/diagrams/lib/wires.js.map +1 -1
- package/dist/diagrams/spec.d.ts +64 -12
- package/dist/index.d.ts +19 -4
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/keyframes.css +57 -3
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +14 -4
- package/dist/lib/overlay-container.js.map +1 -1
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +17 -6
- package/dist/styles.css +1 -1
- package/dist/themes.css +8 -0
- package/dist/tokens.css +86 -5
- package/dist/tokens.d.ts +4 -1
- package/dist/tokens.js +56 -36
- package/dist/tokens.json +56 -36
- package/llms.txt +35 -0
- package/package.json +5 -2
- package/skills/misoto22-design/evals/evals.json +84 -0
- package/skills/misoto22-design/rules/a11y.md +55 -3
- package/skills/misoto22-design/rules/forms.md +8 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Check, Copy } from "lucide-react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { Button } from "../Button/Button.js";
|
|
7
|
+
const LANGUAGE_LABEL = {
|
|
8
|
+
bash: "Shell",
|
|
9
|
+
css: "CSS",
|
|
10
|
+
html: "HTML",
|
|
11
|
+
js: "JavaScript",
|
|
12
|
+
json: "JSON",
|
|
13
|
+
jsx: "JSX",
|
|
14
|
+
md: "Markdown",
|
|
15
|
+
sh: "Shell",
|
|
16
|
+
ts: "TypeScript",
|
|
17
|
+
tsx: "TSX"
|
|
18
|
+
};
|
|
19
|
+
const HIGHLIGHTED = "[&_pre]:m-0 [&_pre]:min-w-max [&_pre]:bg-transparent [&_pre]:p-0 [&_pre]:font-mono [&_pre]:text-[13px] [&_pre]:leading-[1.7] [&_code]:bg-transparent";
|
|
20
|
+
function CodeBlock({
|
|
21
|
+
code,
|
|
22
|
+
html,
|
|
23
|
+
title,
|
|
24
|
+
lang,
|
|
25
|
+
maxHeight,
|
|
26
|
+
copyable = true,
|
|
27
|
+
label,
|
|
28
|
+
className,
|
|
29
|
+
lineNumbers = false,
|
|
30
|
+
highlightLines
|
|
31
|
+
}) {
|
|
32
|
+
const [copied, setCopied] = useState(false);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!copied) return;
|
|
35
|
+
const timer = setTimeout(() => setCopied(false), 1600);
|
|
36
|
+
return () => clearTimeout(timer);
|
|
37
|
+
}, [copied]);
|
|
38
|
+
const copy = async () => {
|
|
39
|
+
try {
|
|
40
|
+
await navigator.clipboard.writeText(code);
|
|
41
|
+
setCopied(true);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const languageLabel = lang ? LANGUAGE_LABEL[lang] ?? lang.toUpperCase() : void 0;
|
|
46
|
+
const banded = new Set(highlightLines ?? []);
|
|
47
|
+
return /* @__PURE__ */ jsxs(
|
|
48
|
+
"div",
|
|
49
|
+
{
|
|
50
|
+
className: cn(
|
|
51
|
+
// `min-w-0` is what lets the body below actually scroll: a grid or flex
|
|
52
|
+
// item defaults to `min-width: auto`, so without it the block grows to
|
|
53
|
+
// the min-content width of its longest line — an unbroken install
|
|
54
|
+
// command — and pushes the whole page sideways on a phone.
|
|
55
|
+
"flex min-w-0 flex-col overflow-hidden rounded-(--radius-lg) border border-(--rule) bg-(--paper-2)",
|
|
56
|
+
className
|
|
57
|
+
),
|
|
58
|
+
children: [
|
|
59
|
+
title || languageLabel || copyable ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 border-b border-(--rule) py-1.5 ps-4 pe-1.5", children: [
|
|
60
|
+
title ? /* @__PURE__ */ jsx("span", { className: "mono-meta truncate text-(--ink-2)", children: title }) : null,
|
|
61
|
+
languageLabel ? /* @__PURE__ */ jsx("span", { className: "mono-meta shrink-0 text-(--ink-3-aa)", children: languageLabel }) : null,
|
|
62
|
+
copyable ? /* @__PURE__ */ jsx(
|
|
63
|
+
Button,
|
|
64
|
+
{
|
|
65
|
+
iconOnly: true,
|
|
66
|
+
size: "sm",
|
|
67
|
+
variant: "ghost",
|
|
68
|
+
onClick: copy,
|
|
69
|
+
"aria-label": copied ? "Copied" : "Copy the snippet",
|
|
70
|
+
className: "ms-auto shrink-0 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
71
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { size: 14, strokeWidth: 1.5, "aria-hidden": true }) : /* @__PURE__ */ jsx(Copy, { size: 14, strokeWidth: 1.5, "aria-hidden": true })
|
|
72
|
+
}
|
|
73
|
+
) : null
|
|
74
|
+
] }) : null,
|
|
75
|
+
/* @__PURE__ */ jsx(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
tabIndex: 0,
|
|
79
|
+
role: "group",
|
|
80
|
+
"aria-label": label ?? title ?? "Code",
|
|
81
|
+
style: maxHeight === void 0 ? void 0 : { maxHeight },
|
|
82
|
+
className: "overflow-auto px-4 py-3.5 scroll-slim",
|
|
83
|
+
children: html === void 0 ? /* @__PURE__ */ jsx("pre", { className: "m-0 min-w-max bg-transparent p-0 font-mono text-[13px] leading-[1.7]", children: /* @__PURE__ */ jsx("code", { className: "block", children: code.split("\n").map((line, index) => /* @__PURE__ */ jsxs(
|
|
84
|
+
"span",
|
|
85
|
+
{
|
|
86
|
+
"data-line": index + 1,
|
|
87
|
+
"data-highlighted": banded.has(index + 1) ? "" : void 0,
|
|
88
|
+
className: cn(
|
|
89
|
+
"block min-h-[1.7em] border-s-2 border-transparent ps-2",
|
|
90
|
+
banded.has(index + 1) && "border-(--accent) bg-(--stone)"
|
|
91
|
+
),
|
|
92
|
+
children: [
|
|
93
|
+
lineNumbers ? /* @__PURE__ */ jsx(
|
|
94
|
+
"span",
|
|
95
|
+
{
|
|
96
|
+
"aria-hidden": true,
|
|
97
|
+
className: "inline-block w-8 shrink-0 select-none pe-3 text-end tabular-nums text-(--ink-3-aa)",
|
|
98
|
+
children: index + 1
|
|
99
|
+
}
|
|
100
|
+
) : null,
|
|
101
|
+
line
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
index
|
|
105
|
+
)) }) }) : (
|
|
106
|
+
// Trusted markup only: the output of the caller's own highlighter, run
|
|
107
|
+
// over the caller's own `code`. It is not a place to put anything a
|
|
108
|
+
// reader wrote — hand that to `code` and let the block render it as
|
|
109
|
+
// text, which it cannot mis-execute.
|
|
110
|
+
/* @__PURE__ */ jsx("div", { className: HIGHLIGHTED, dangerouslySetInnerHTML: { __html: html } })
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
var CodeBlock_default = CodeBlock;
|
|
119
|
+
export {
|
|
120
|
+
CodeBlock,
|
|
121
|
+
CodeBlock_default as default
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=CodeBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/CodeBlock/CodeBlock.tsx"],"sourcesContent":["'use client'\n\nimport { Check, Copy } from 'lucide-react'\nimport { useEffect, useState } from 'react'\nimport { cn } from '../../lib/cn'\nimport { Button } from '../Button/Button'\n\n/**\n * What a language id is CALLED, for the handful where the id is not a label.\n *\n * Shiki's ids are identifiers, not words: `tsx` and `bash` read fine in upper\n * case, `md` and `ts` do not, and nobody reads `sh` as \"shell\". Anything absent\n * falls through to the id upper-cased, which is right far more often than it is\n * wrong — and a wrong label here is a label, not a crash.\n */\nconst LANGUAGE_LABEL: Record<string, string> = {\n bash: 'Shell',\n css: 'CSS',\n html: 'HTML',\n js: 'JavaScript',\n json: 'JSON',\n jsx: 'JSX',\n md: 'Markdown',\n sh: 'Shell',\n ts: 'TypeScript',\n tsx: 'TSX',\n}\n\ninterface CommonProps {\n /**\n * The snippet, verbatim.\n *\n * Required even when `html` is supplied, and that is the point: this is what\n * the copy button puts on the clipboard. A block that copies its own rendered\n * markup hands the reader a wall of `<span>`s, and one that copies\n * `textContent` scraped back out of the DOM is a single non-breaking space\n * away from pasting something that does not run.\n */\n code: string\n /** A filename or a caption, printed at the start of the strip. */\n title?: string\n /**\n * The language, printed at the end of the strip.\n *\n * Optional, and the omission is visible rather than silent: a block with no\n * language gets no label instead of claiming a wrong one. A code block that\n * does not say what it is written in makes the reader infer it from the\n * syntax, which is the one thing they came to the block to learn.\n */\n lang?: string\n /**\n * Caps the block's height and scrolls past it.\n *\n * A number is pixels; a string is any CSS length (`'24rem'`, `'50vh'`). The\n * body scrolls in both axes and is focusable, so what is past the fold stays\n * reachable with a keyboard rather than merely present in the DOM.\n */\n maxHeight?: number | string\n /** Drops the copy button, for a block nobody is meant to run. */\n copyable?: boolean\n /**\n * Names the scrollable body for a screen reader. Defaults to `title`, and to\n * \"Code\" when there is not one.\n */\n label?: string\n className?: string\n}\n\n/**\n * The two forms, and why they are two.\n *\n * `html` is pre-highlighted markup for the SAME snippet. The package does not\n * highlight, and will not: a highlighter is a few hundred kilobytes of grammar\n * and a build-time job. The documentation site runs Shiki inside its generator\n * and hands the result here, which is the shape that half exists for. Without\n * `html` the block renders `code` as text, which is what a template, a README\n * or an agent's answer has and all it needs.\n *\n * `lineNumbers` and `highlightLines` belong to the plain form only, and that is\n * enforced in the TYPE rather than left to a note. They are a per-LINE\n * structure, and `html` is one opaque string this component is not going to\n * start parsing. Typed apart, passing both is a compile error at the call site;\n * typed together it is a prop that renders nothing and says nothing.\n *\n * The plain form is written first because the emitted prop table reads the\n * first arm of a union: this way `lineNumbers` documents as `boolean` rather\n * than as the `never` the other arm gives it.\n */\ntype WithPlainSource = CommonProps & {\n /**\n * Absent on this form; `string` on the other.\n *\n * Pass pre-highlighted markup — Shiki's output, run at build time over this\n * same `code` — and the block renders that instead of the plain text. Doing\n * so takes `lineNumbers` and `highlightLines` away with it.\n */\n html?: undefined\n /** Numbers every line, counting from one. */\n lineNumbers?: boolean\n /**\n * Lines to band, counting from one. A number past the end of the snippet is\n * ignored rather than throwing — the usual cause is a snippet that got\n * shorter while the annotation did not.\n */\n highlightLines?: number[]\n}\n\ntype WithHighlightedHtml = CommonProps & {\n html: string\n /** Not available alongside `html`, which the component does not parse. */\n lineNumbers?: never\n /** Not available alongside `html`, which the component does not parse. */\n highlightLines?: never\n}\n\nexport type CodeBlockProps = WithPlainSource | WithHighlightedHtml\n\n/**\n * The caller's `<pre>`, normalised to ours.\n *\n * Shiki emits a `<pre>` of its own with a background and padding baked in, so\n * the highlighted path would otherwise draw a second plate a shade off the one\n * it is sitting on, at a size that does not match the plain path.\n */\nconst HIGHLIGHTED =\n '[&_pre]:m-0 [&_pre]:min-w-max [&_pre]:bg-transparent [&_pre]:p-0 [&_pre]:font-mono [&_pre]:text-[13px] [&_pre]:leading-[1.7] [&_code]:bg-transparent'\n\n/**\n * A multi-line snippet, on a plate, with a way to take it away.\n *\n * The strip along the top carries the title, the language and the copy button,\n * and it is there whenever there is anything to put in it. It is deliberately\n * not a hover affordance: a control that appears on hover does not exist on a\n * touch screen, which is where a reader is most likely to want the snippet and\n * least able to select it by hand.\n *\n * Line numbers live INSIDE their own line's row rather than in a parallel gutter\n * column. Two columns sharing a line-height align right up until one of them\n * wraps, ships a different font, or scrolls on its own; a number that is a child\n * of the line it numbers cannot come apart from it. The cost is that a number\n * scrolls away with its line: it is inside the scrolling box, not in a gutter\n * beside it. A gutter that stayed put would be a second column to keep in sync,\n * which is the failure this avoids.\n *\n * The body is a focusable, named `role=\"group\"`, and both halves of that are\n * load-bearing. Focusable, because a scrollable box whose contents are not\n * themselves focusable is unreachable by keyboard — there is nothing to Tab to\n * and therefore no way to press an arrow key at it, so the right-hand half of a\n * long line does not exist for anyone not using a mouse. Named, because a tab\n * stop that announces nothing lands the reader in an anonymous box and leaves\n * them to work out what they have arrived in.\n *\n * `group` rather than `region`, and that is the deliberate half. A region is a\n * LANDMARK — one of the handful of major sections a reader navigates a whole\n * page by — and a snippet is not one of those. Three fenced blocks in one\n * article would put three landmarks called \"Code\" into that map, which is\n * exactly the noise the `landmark-unique` rule exists to catch, and it would\n * push the page's real landmarks down a list nobody can now skim. `group`\n * carries the same accessible name to the same reader on the way in, and\n * carries it nowhere else.\n *\n * For a function name inside a sentence, reach for `Code`.\n *\n * @example\n * <CodeBlock code=\"pnpm add @misoto22/design\" lang=\"bash\" />\n * @example\n * <CodeBlock\n * title=\"cn.ts\"\n * lang=\"ts\"\n * lineNumbers\n * highlightLines={[2]}\n * maxHeight=\"24rem\"\n * code={source}\n * />\n * @example\n * // Highlighted at build time by the site's own Shiki pass.\n * <CodeBlock code={source} html={highlighted} lang=\"tsx\" />\n */\nexport function CodeBlock({\n code,\n html,\n title,\n lang,\n maxHeight,\n copyable = true,\n label,\n className,\n lineNumbers = false,\n highlightLines,\n}: CodeBlockProps) {\n const [copied, setCopied] = useState(false)\n\n useEffect(() => {\n if (!copied) return\n const timer = setTimeout(() => setCopied(false), 1600)\n return () => clearTimeout(timer)\n }, [copied])\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(code)\n setCopied(true)\n } catch {\n // Clipboard access is denied in an insecure context and inside some\n // embeds. The snippet is still selectable, so there is nothing to\n // recover — and an unhandled rejection here would take the page with it.\n }\n }\n\n const languageLabel = lang ? (LANGUAGE_LABEL[lang] ?? lang.toUpperCase()) : undefined\n const banded = new Set(highlightLines ?? [])\n\n return (\n <div\n className={cn(\n // `min-w-0` is what lets the body below actually scroll: a grid or flex\n // item defaults to `min-width: auto`, so without it the block grows to\n // the min-content width of its longest line — an unbroken install\n // command — and pushes the whole page sideways on a phone.\n 'flex min-w-0 flex-col overflow-hidden rounded-(--radius-lg) border border-(--rule) bg-(--paper-2)',\n className,\n )}\n >\n {title || languageLabel || copyable ? (\n <div className=\"flex items-center gap-3 border-b border-(--rule) py-1.5 ps-4 pe-1.5\">\n {title ? <span className=\"mono-meta truncate text-(--ink-2)\">{title}</span> : null}\n {languageLabel ? (\n <span className=\"mono-meta shrink-0 text-(--ink-3-aa)\">{languageLabel}</span>\n ) : null}\n {copyable ? (\n <Button\n iconOnly\n size=\"sm\"\n variant=\"ghost\"\n onClick={copy}\n aria-label={copied ? 'Copied' : 'Copy the snippet'}\n // `sm` is 36px, under the 44px a finger needs. The bump is gated\n // on a coarse pointer so a mouse-driven page keeps the compact\n // strip (WCAG 2.5.5).\n className=\"ms-auto shrink-0 pointer-coarse:min-h-11 pointer-coarse:min-w-11\"\n >\n {copied ? (\n <Check size={14} strokeWidth={1.5} aria-hidden />\n ) : (\n <Copy size={14} strokeWidth={1.5} aria-hidden />\n )}\n </Button>\n ) : null}\n </div>\n ) : null}\n\n <div\n tabIndex={0}\n // A named group, not a landmark: see the note above the component.\n role=\"group\"\n aria-label={label ?? title ?? 'Code'}\n style={maxHeight === undefined ? undefined : { maxHeight }}\n className=\"overflow-auto px-4 py-3.5 scroll-slim\"\n >\n {html === undefined ? (\n <pre className=\"m-0 min-w-max bg-transparent p-0 font-mono text-[13px] leading-[1.7]\">\n <code className=\"block\">\n {code.split('\\n').map((line, index) => (\n <span\n key={index}\n data-line={index + 1}\n data-highlighted={banded.has(index + 1) ? '' : undefined}\n // The transparent border is carried by EVERY row, banded or\n // not. On the banded ones alone it would shift them two pixels\n // along the inline axis — which is the exact misalignment a\n // highlight is there to help the reader see past.\n //\n // `min-h` is what keeps a blank line a line: an empty block\n // has no line box and would otherwise collapse to nothing,\n // taking every number below it out of step with its code.\n className={cn(\n 'block min-h-[1.7em] border-s-2 border-transparent ps-2',\n banded.has(index + 1) && 'border-(--accent) bg-(--stone)',\n )}\n >\n {lineNumbers ? (\n <span\n aria-hidden\n className=\"inline-block w-8 shrink-0 select-none pe-3 text-end tabular-nums text-(--ink-3-aa)\"\n >\n {index + 1}\n </span>\n ) : null}\n {line}\n </span>\n ))}\n </code>\n </pre>\n ) : (\n // Trusted markup only: the output of the caller's own highlighter, run\n // over the caller's own `code`. It is not a place to put anything a\n // reader wrote — hand that to `code` and let the block render it as\n // text, which it cannot mis-execute.\n <div className={HIGHLIGHTED} dangerouslySetInnerHTML={{ __html: html }} />\n )}\n </div>\n </div>\n )\n}\n\nexport default CodeBlock\n"],"mappings":";AAgOQ,SACW,KADX;AA9NR,SAAS,OAAO,YAAY;AAC5B,SAAS,WAAW,gBAAgB;AACpC,SAAS,UAAU;AACnB,SAAS,cAAc;AAUvB,MAAM,iBAAyC;AAAA,EAC7C,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,KAAK;AACP;AAkGA,MAAM,cACJ;AAqDK,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAmB;AACjB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,WAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AACrD,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,IAAI;AACxC,gBAAU,IAAI;AAAA,IAChB,QAAQ;AAAA,IAIR;AAAA,EACF;AAEA,QAAM,gBAAgB,OAAQ,eAAe,IAAI,KAAK,KAAK,YAAY,IAAK;AAC5E,QAAM,SAAS,IAAI,IAAI,kBAAkB,CAAC,CAAC;AAE3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA,iBAAS,iBAAiB,WACzB,qBAAC,SAAI,WAAU,uEACZ;AAAA,kBAAQ,oBAAC,UAAK,WAAU,qCAAqC,iBAAM,IAAU;AAAA,UAC7E,gBACC,oBAAC,UAAK,WAAU,wCAAwC,yBAAc,IACpE;AAAA,UACH,WACC;AAAA,YAAC;AAAA;AAAA,cACC,UAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,SAAS;AAAA,cACT,cAAY,SAAS,WAAW;AAAA,cAIhC,WAAU;AAAA,cAET,mBACC,oBAAC,SAAM,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC,IAE/C,oBAAC,QAAK,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC;AAAA;AAAA,UAElD,IACE;AAAA,WACN,IACE;AAAA,QAEJ;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YAEV,MAAK;AAAA,YACL,cAAY,SAAS,SAAS;AAAA,YAC9B,OAAO,cAAc,SAAY,SAAY,EAAE,UAAU;AAAA,YACzD,WAAU;AAAA,YAET,mBAAS,SACR,oBAAC,SAAI,WAAU,wEACb,8BAAC,UAAK,WAAU,SACb,eAAK,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,UAC3B;AAAA,cAAC;AAAA;AAAA,gBAEC,aAAW,QAAQ;AAAA,gBACnB,oBAAkB,OAAO,IAAI,QAAQ,CAAC,IAAI,KAAK;AAAA,gBAS/C,WAAW;AAAA,kBACT;AAAA,kBACA,OAAO,IAAI,QAAQ,CAAC,KAAK;AAAA,gBAC3B;AAAA,gBAEC;AAAA,gCACC;AAAA,oBAAC;AAAA;AAAA,sBACC,eAAW;AAAA,sBACX,WAAU;AAAA,sBAET,kBAAQ;AAAA;AAAA,kBACX,IACE;AAAA,kBACH;AAAA;AAAA;AAAA,cAxBI;AAAA,YAyBP,CACD,GACH,GACF;AAAA;AAAA;AAAA;AAAA;AAAA,cAMA,oBAAC,SAAI,WAAW,aAAa,yBAAyB,EAAE,QAAQ,KAAK,GAAG;AAAA;AAAA;AAAA,QAE5E;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,oBAAQ;","names":[]}
|
|
@@ -12,8 +12,9 @@ function CollapsibleContent({
|
|
|
12
12
|
return /* @__PURE__ */ jsx(
|
|
13
13
|
CollapsiblePrimitive.Content,
|
|
14
14
|
{
|
|
15
|
+
"data-m22-animated": true,
|
|
15
16
|
className: cn(
|
|
16
|
-
"overflow-hidden data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]
|
|
17
|
+
"overflow-hidden data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]",
|
|
17
18
|
className
|
|
18
19
|
),
|
|
19
20
|
...props
|
|
@@ -39,7 +40,14 @@ function CollapsibleSection({
|
|
|
39
40
|
}
|
|
40
41
|
)
|
|
41
42
|
] }),
|
|
42
|
-
/* @__PURE__ */ jsx(
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
CollapsiblePrimitive.Content,
|
|
45
|
+
{
|
|
46
|
+
"data-m22-animated": true,
|
|
47
|
+
className: "overflow-hidden text-sm leading-relaxed text-(--ink-2) data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]",
|
|
48
|
+
children: /* @__PURE__ */ jsx("div", { className: "pb-3", children })
|
|
49
|
+
}
|
|
50
|
+
)
|
|
43
51
|
] });
|
|
44
52
|
}
|
|
45
53
|
var Collapsible_default = Collapsible;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Collapsible/Collapsible.tsx"],"sourcesContent":["'use client'\n\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\nimport { ChevronDown } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Collapsible root, as a typed passthrough. */\nexport const Collapsible = CollapsiblePrimitive.Root\n\n/**\n * The trigger and the panel, unstyled, for a disclosure that needs its own\n * layout — a sidebar group whose header carries a count and a chevron on\n * opposite sides, say. `CollapsibleSection` is the composed version and is what\n * most call sites want; these two exist so the ones that do not have to reach\n * for Radix directly and re-derive the keyboard and `aria-expanded` wiring.\n *\n * The panel animates on `--radix-collapsible-content-height`, which Radix\n * measures — so it opens to its real height rather than to a guessed\n * `max-height`, which is what makes a long group and a short one take the same\n * time instead of the long one appearing to stall.\n */\nexport const CollapsibleTrigger = CollapsiblePrimitive.Trigger\n\nexport function CollapsibleContent({\n className,\n ...props\n}: ComponentProps<typeof CollapsiblePrimitive.Content>) {\n return (\n <CollapsiblePrimitive.Content\n className={cn(\n 'overflow-hidden data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Collapsible/Collapsible.tsx"],"sourcesContent":["'use client'\n\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\nimport { ChevronDown } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Collapsible root, as a typed passthrough. */\nexport const Collapsible = CollapsiblePrimitive.Root\n\n/**\n * The trigger and the panel, unstyled, for a disclosure that needs its own\n * layout — a sidebar group whose header carries a count and a chevron on\n * opposite sides, say. `CollapsibleSection` is the composed version and is what\n * most call sites want; these two exist so the ones that do not have to reach\n * for Radix directly and re-derive the keyboard and `aria-expanded` wiring.\n *\n * The panel animates on `--radix-collapsible-content-height`, which Radix\n * measures — so it opens to its real height rather than to a guessed\n * `max-height`, which is what makes a long group and a short one take the same\n * time instead of the long one appearing to stall.\n */\nexport const CollapsibleTrigger = CollapsiblePrimitive.Trigger\n\nexport function CollapsibleContent({\n className,\n ...props\n}: ComponentProps<typeof CollapsiblePrimitive.Content>) {\n return (\n <CollapsiblePrimitive.Content\n data-m22-animated\n className={cn(\n 'overflow-hidden data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport interface CollapsibleSectionProps\n extends Omit<ComponentProps<typeof CollapsiblePrimitive.Root>, 'children' | 'title'> {\n /** What the trigger says. */\n title: ReactNode\n children: ReactNode\n}\n\n/**\n * One thing that opens, on its own.\n *\n * The difference from `Accordion` is arithmetic: an accordion is a SET, and a\n * set can coordinate — opening one closes another. A collapsible is one\n * disclosure with nothing to coordinate with. Reaching for an accordion of one\n * gets you a component managing a value you never read.\n *\n * The marker here is a chevron rather than the accordion's plus, and\n * deliberately: this reveals more of the same thing, where an accordion row\n * opens a distinct answer.\n *\n * @example\n * <CollapsibleSection title=\"Advanced settings\">\n * <Field label=\"Retries\"><Input type=\"number\" /></Field>\n * </CollapsibleSection>\n */\nexport function CollapsibleSection({\n title,\n children,\n className,\n ...props\n}: CollapsibleSectionProps) {\n return (\n <CollapsiblePrimitive.Root className={cn('w-full', className)} {...props}>\n <CollapsiblePrimitive.Trigger className=\"group flex w-full items-center justify-between gap-4 py-3 text-start text-sm text-(--ink) transition-colors duration-(--duration-fast) hover:text-(--ink-2)\">\n {title}\n <ChevronDown\n size={16}\n strokeWidth={1.5}\n aria-hidden\n className=\"shrink-0 text-(--ink-3-aa) transition-transform duration-(--duration-base) ease-(--ease-out-expo) group-data-[state=open]:rotate-180\"\n />\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content\n data-m22-animated\n className=\"overflow-hidden text-sm leading-relaxed text-(--ink-2) data-[state=closed]:animate-[m22-collapsible-up_var(--duration-base)_var(--ease)] data-[state=open]:animate-[m22-collapsible-down_var(--duration-base)_var(--ease)]\"\n >\n <div className=\"pb-3\">{children}</div>\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n )\n}\n\nexport default Collapsible\n"],"mappings":";AA6BI,cA2CE,YA3CF;AA3BJ,YAAY,0BAA0B;AACtC,SAAS,mBAAmB;AAE5B,SAAS,UAAU;AAGZ,MAAM,cAAc,qBAAqB;AAczC,MAAM,qBAAqB,qBAAqB;AAEhD,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,SACE;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC,qBAAiB;AAAA,MACjB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AA0BO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA4B;AAC1B,SACE,qBAAC,qBAAqB,MAArB,EAA0B,WAAW,GAAG,UAAU,SAAS,GAAI,GAAG,OACjE;AAAA,yBAAC,qBAAqB,SAArB,EAA6B,WAAU,+JACrC;AAAA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,aAAa;AAAA,UACb,eAAW;AAAA,UACX,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACA;AAAA,MAAC,qBAAqB;AAAA,MAArB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAU;AAAA,QAEV,8BAAC,SAAI,WAAU,QAAQ,UAAS;AAAA;AAAA,IAClC;AAAA,KACF;AAEJ;AAEA,IAAO,sBAAQ;","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface ColorPickerProps {
|
|
4
|
+
/**
|
|
5
|
+
* Names the control. Required — the trigger shows a colour, and a colour is
|
|
6
|
+
* not a name.
|
|
7
|
+
*
|
|
8
|
+
* Announced together with the value, the way `Select`'s is: a reader hears
|
|
9
|
+
* "Brand colour, #a78bfa". Inside a `Field` with a label, that label is used
|
|
10
|
+
* and this one is not repeated.
|
|
11
|
+
*/
|
|
12
|
+
label: string;
|
|
13
|
+
/** The colour, as any absolute CSS colour string. */
|
|
14
|
+
value?: string;
|
|
15
|
+
defaultValue?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Fires with a CSS colour string in whichever notation the panel is set to —
|
|
18
|
+
* so the notation a caller passes in is the notation they get back until
|
|
19
|
+
* somebody changes it in the panel.
|
|
20
|
+
*/
|
|
21
|
+
onValueChange?: (value: string) => void;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
/** Paints the resting border with `--danger` and reflects `aria-invalid`. */
|
|
24
|
+
invalid?: boolean;
|
|
25
|
+
className?: string;
|
|
26
|
+
/** The TRIGGER's id — the element a label points at. A `Field` sets it. */
|
|
27
|
+
id?: string;
|
|
28
|
+
/** Ids of the copy describing the control. A `Field` sets it from hint, error and description. */
|
|
29
|
+
'aria-describedby'?: string;
|
|
30
|
+
/** The spelling a form library sets; read together with `invalid`. */
|
|
31
|
+
'aria-invalid'?: boolean | 'true' | 'false';
|
|
32
|
+
/** Announced on the trigger. A `Field` sets it from `required`. */
|
|
33
|
+
'aria-required'?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A colour, chosen or typed.
|
|
37
|
+
*
|
|
38
|
+
* The panel works in OKLCH, and that is the reason to reach for this rather
|
|
39
|
+
* than `<input type="color">`. In HSV — which is what the native picker and
|
|
40
|
+
* most libraries use — dragging along a row of constant "lightness" walks
|
|
41
|
+
* through colours the eye reads as getting darker, so a reader tuning a palette
|
|
42
|
+
* is fighting the instrument. OKLCH's lightness is the one a person sees, so
|
|
43
|
+
* two colours at the same height on the plane genuinely match, and the hue
|
|
44
|
+
* strip stays at the lightness already chosen instead of showing a rainbow that
|
|
45
|
+
* belongs to some other colour.
|
|
46
|
+
*
|
|
47
|
+
* The plane is normalised to the gamut ROW BY ROW: its right edge is the most
|
|
48
|
+
* chroma that exists at that lightness and hue, so the whole surface is
|
|
49
|
+
* reachable rather than a lens of colour inside a field of clipped duplicates.
|
|
50
|
+
*
|
|
51
|
+
* **What it accepts.** Hex, `rgb()`, `hsl()`, `oklch()` and
|
|
52
|
+
* `color(display-p3 …)`, in both syntaxes. Named colours are not accepted:
|
|
53
|
+
* resolving them needs a table of every CSS name or a live DOM, and a box that
|
|
54
|
+
* takes "rebeccapurple" but not "papayawhip" is worse than one that takes
|
|
55
|
+
* neither.
|
|
56
|
+
*
|
|
57
|
+
* **Keyboard.** The plane is a group of two real sliders — chroma across,
|
|
58
|
+
* lightness up — so the arrows move it and a screen reader announces where it
|
|
59
|
+
* is. That is the part a 2D canvas usually leaves out, and leaving it out makes
|
|
60
|
+
* the control unusable rather than merely awkward.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* <Field label="Brand colour"><ColorPicker label="Brand colour" defaultValue="#a78bfa" /></Field>
|
|
64
|
+
*/
|
|
65
|
+
declare function ColorPicker({ label, value: controlled, defaultValue, onValueChange, disabled, invalid, className, id, 'aria-describedby': describedBy, 'aria-invalid': ariaInvalid, 'aria-required': ariaRequired, }: ColorPickerProps): react.JSX.Element;
|
|
66
|
+
|
|
67
|
+
export { ColorPicker, type ColorPickerProps, ColorPicker as default };
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import {
|
|
6
|
+
clamp,
|
|
7
|
+
colorFormat,
|
|
8
|
+
colorToRgb,
|
|
9
|
+
fitGamut,
|
|
10
|
+
formatColor,
|
|
11
|
+
maxChroma,
|
|
12
|
+
parseColor
|
|
13
|
+
} from "../../lib/color.js";
|
|
14
|
+
import { CONTROL_BASE, CONTROL_BORDER, isInvalid } from "../../lib/control.js";
|
|
15
|
+
import { warnBlankName } from "../../lib/warn.js";
|
|
16
|
+
import { useFieldControl } from "../Field/field-control.js";
|
|
17
|
+
import { Input } from "../Input/Input.js";
|
|
18
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../Popover/Popover.js";
|
|
19
|
+
import { ToggleGroup, ToggleGroupItem } from "../ToggleGroup/ToggleGroup.js";
|
|
20
|
+
const PLANE_W = 256;
|
|
21
|
+
const PLANE_H = 160;
|
|
22
|
+
const HUE_STOPS = 73;
|
|
23
|
+
const BLACK = { l: 0, c: 0, h: 0, a: 1 };
|
|
24
|
+
const FORMAT_LABELS = {
|
|
25
|
+
hex: "Hex",
|
|
26
|
+
oklch: "OKLCH",
|
|
27
|
+
// Not "Display P3": the three segments share the strip evenly, and the long
|
|
28
|
+
// name wraps to two lines inside its third and makes the whole row twice as
|
|
29
|
+
// tall as the two beside it.
|
|
30
|
+
p3: "P3"
|
|
31
|
+
};
|
|
32
|
+
const checkerboard = (square) => `repeating-conic-gradient(var(--stone) 0% 25%, var(--paper) 0% 50%) 0 0 / ${square} ${square}`;
|
|
33
|
+
function ColorPicker({
|
|
34
|
+
label,
|
|
35
|
+
value: controlled,
|
|
36
|
+
defaultValue = "#000000",
|
|
37
|
+
onValueChange,
|
|
38
|
+
disabled,
|
|
39
|
+
invalid,
|
|
40
|
+
className,
|
|
41
|
+
id,
|
|
42
|
+
"aria-describedby": describedBy,
|
|
43
|
+
"aria-invalid": ariaInvalid,
|
|
44
|
+
"aria-required": ariaRequired
|
|
45
|
+
}) {
|
|
46
|
+
warnBlankName("ColorPicker", "label", label, "the trigger is announced with no name");
|
|
47
|
+
const bad = isInvalid(invalid, ariaInvalid);
|
|
48
|
+
const field = useFieldControl();
|
|
49
|
+
const generated = useId();
|
|
50
|
+
const triggerId = id ?? generated;
|
|
51
|
+
const valueId = `${triggerId}-value`;
|
|
52
|
+
const nameId = field?.labelId ?? `${triggerId}-name`;
|
|
53
|
+
const [uncontrolled, setUncontrolled] = useState(defaultValue);
|
|
54
|
+
const value = controlled ?? uncontrolled;
|
|
55
|
+
const [color, setColor] = useState(() => parseColor(defaultValue) ?? BLACK);
|
|
56
|
+
const [format, setFormat] = useState(() => colorFormat(defaultValue));
|
|
57
|
+
const emitted = useRef(null);
|
|
58
|
+
const saturationRef = useRef(0);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (value === emitted.current) return;
|
|
61
|
+
const parsed = parseColor(value);
|
|
62
|
+
if (!parsed) return;
|
|
63
|
+
setColor((prev) => ({ ...parsed, h: parsed.c < 1e-7 ? prev.h : parsed.h }));
|
|
64
|
+
setFormat(colorFormat(value));
|
|
65
|
+
}, [value]);
|
|
66
|
+
const space = format === "hex" ? "srgb" : "p3";
|
|
67
|
+
const ceiling = maxChroma(color.l, color.h, space);
|
|
68
|
+
const saturation = ceiling > 0 ? clamp(color.c / ceiling) : saturationRef.current;
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (ceiling > 0) saturationRef.current = saturation;
|
|
71
|
+
}, [ceiling, saturation]);
|
|
72
|
+
const commit = (next, nextFormat = format) => {
|
|
73
|
+
const fitted = nextFormat === "oklch" ? next : fitGamut(next, nextFormat === "p3" ? "p3" : "srgb");
|
|
74
|
+
setColor(fitted);
|
|
75
|
+
setFormat(nextFormat);
|
|
76
|
+
const text = formatColor(fitted, nextFormat);
|
|
77
|
+
emitted.current = text;
|
|
78
|
+
if (controlled === void 0) setUncontrolled(text);
|
|
79
|
+
onValueChange?.(text);
|
|
80
|
+
};
|
|
81
|
+
const setPlane = (nextSaturation, lightness) => {
|
|
82
|
+
saturationRef.current = nextSaturation;
|
|
83
|
+
commit({ ...color, l: lightness, c: nextSaturation * maxChroma(lightness, color.h, space) });
|
|
84
|
+
};
|
|
85
|
+
const planeRef = useRef(null);
|
|
86
|
+
const canvasRef = useRef(null);
|
|
87
|
+
const painted = useRef("");
|
|
88
|
+
const trackPointer = (event) => {
|
|
89
|
+
const rect = planeRef.current?.getBoundingClientRect();
|
|
90
|
+
if (!rect || rect.width === 0 || rect.height === 0) return;
|
|
91
|
+
setPlane(
|
|
92
|
+
clamp((event.clientX - rect.left) / rect.width),
|
|
93
|
+
clamp(1 - (event.clientY - rect.top) / rect.height)
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
const paint = (canvas) => {
|
|
97
|
+
if (!canvas) return;
|
|
98
|
+
const key = `${color.h.toFixed(3)}:${space}`;
|
|
99
|
+
if (painted.current === key) return;
|
|
100
|
+
const context = canvas.getContext("2d");
|
|
101
|
+
if (!context || typeof context.createImageData !== "function") return;
|
|
102
|
+
painted.current = key;
|
|
103
|
+
const pixels = context.createImageData(PLANE_W, PLANE_H);
|
|
104
|
+
for (let y = 0; y < PLANE_H; y++) {
|
|
105
|
+
const l = 1 - y / (PLANE_H - 1);
|
|
106
|
+
const rowMax = maxChroma(l, color.h, space);
|
|
107
|
+
for (let x = 0; x < PLANE_W; x++) {
|
|
108
|
+
const rgb = colorToRgb({ l, c: x / (PLANE_W - 1) * rowMax, h: color.h, a: 1 }, "srgb");
|
|
109
|
+
const at = (y * PLANE_W + x) * 4;
|
|
110
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
111
|
+
pixels.data[at + channel] = Math.round(clamp(rgb[channel] ?? 0) * 255);
|
|
112
|
+
}
|
|
113
|
+
pixels.data[at + 3] = 255;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
context.putImageData(pixels, 0, 0);
|
|
117
|
+
};
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
paint(canvasRef.current);
|
|
120
|
+
});
|
|
121
|
+
const opaque = formatColor({ ...color, a: 1 }, "oklch");
|
|
122
|
+
const hueTrack = Array.from({ length: HUE_STOPS }, (_, i) => {
|
|
123
|
+
const h = i * (360 / (HUE_STOPS - 1));
|
|
124
|
+
return formatColor({ l: color.l, c: saturation * maxChroma(color.l, h, space), h, a: 1 }, "oklch");
|
|
125
|
+
}).join(", ");
|
|
126
|
+
const typed = parseColor(value);
|
|
127
|
+
return /* @__PURE__ */ jsxs(Popover, { children: [
|
|
128
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
id: triggerId,
|
|
133
|
+
disabled,
|
|
134
|
+
"aria-labelledby": `${nameId} ${valueId}`,
|
|
135
|
+
"aria-describedby": describedBy,
|
|
136
|
+
"aria-required": ariaRequired,
|
|
137
|
+
"aria-invalid": bad || void 0,
|
|
138
|
+
className: cn(
|
|
139
|
+
CONTROL_BASE,
|
|
140
|
+
bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,
|
|
141
|
+
"flex cursor-pointer items-center gap-2.5 text-start",
|
|
142
|
+
className
|
|
143
|
+
),
|
|
144
|
+
children: [
|
|
145
|
+
field?.labelId == null && /* @__PURE__ */ jsx("span", { id: nameId, className: "sr-only", children: label }),
|
|
146
|
+
/* @__PURE__ */ jsx(
|
|
147
|
+
"span",
|
|
148
|
+
{
|
|
149
|
+
"aria-hidden": "true",
|
|
150
|
+
className: "size-4 shrink-0 rounded-(--radius-xs) border border-(--rule-2)",
|
|
151
|
+
style: { background: `linear-gradient(${value}, ${value}), ${checkerboard("4px")}` }
|
|
152
|
+
}
|
|
153
|
+
),
|
|
154
|
+
/* @__PURE__ */ jsx("span", { id: valueId, className: "mono-meta truncate", children: value })
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
) }),
|
|
158
|
+
/* @__PURE__ */ jsxs(PopoverContent, { label: `${label} picker`, className: "flex w-72 flex-col gap-3", children: [
|
|
159
|
+
/* @__PURE__ */ jsx(
|
|
160
|
+
ToggleGroup,
|
|
161
|
+
{
|
|
162
|
+
type: "single",
|
|
163
|
+
value: format,
|
|
164
|
+
onValueChange: (next) => next && commit(color, next),
|
|
165
|
+
"aria-label": "Colour notation",
|
|
166
|
+
className: "w-full",
|
|
167
|
+
children: Object.keys(FORMAT_LABELS).map((option) => /* @__PURE__ */ jsx(ToggleGroupItem, { value: option, className: "flex-1", children: FORMAT_LABELS[option] }, option))
|
|
168
|
+
}
|
|
169
|
+
),
|
|
170
|
+
/* @__PURE__ */ jsxs(
|
|
171
|
+
"div",
|
|
172
|
+
{
|
|
173
|
+
ref: planeRef,
|
|
174
|
+
role: "group",
|
|
175
|
+
"aria-label": `${label} field`,
|
|
176
|
+
onPointerDown: (event) => {
|
|
177
|
+
if (event.button !== 0) return;
|
|
178
|
+
event.preventDefault();
|
|
179
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
180
|
+
trackPointer(event);
|
|
181
|
+
},
|
|
182
|
+
onPointerMove: (event) => {
|
|
183
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) trackPointer(event);
|
|
184
|
+
},
|
|
185
|
+
onPointerUp: (event) => {
|
|
186
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
187
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
className: "relative h-40 w-full cursor-crosshair touch-none select-none rounded-(--radius) focus-within:[outline:var(--focus-w)_solid_var(--focus)] focus-within:[outline-offset:var(--focus-off)]",
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ jsx(
|
|
193
|
+
"canvas",
|
|
194
|
+
{
|
|
195
|
+
ref: (node) => {
|
|
196
|
+
canvasRef.current = node;
|
|
197
|
+
if (!node) painted.current = "";
|
|
198
|
+
paint(node);
|
|
199
|
+
},
|
|
200
|
+
width: PLANE_W,
|
|
201
|
+
height: PLANE_H,
|
|
202
|
+
"aria-hidden": "true",
|
|
203
|
+
className: "block size-full rounded-(--radius)"
|
|
204
|
+
}
|
|
205
|
+
),
|
|
206
|
+
/* @__PURE__ */ jsx(
|
|
207
|
+
"span",
|
|
208
|
+
{
|
|
209
|
+
"aria-hidden": "true",
|
|
210
|
+
className: "pointer-events-none absolute inset-0 rounded-(--radius) shadow-[inset_0_0_0_1px_var(--rule)]"
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
/* @__PURE__ */ jsx(
|
|
214
|
+
"span",
|
|
215
|
+
{
|
|
216
|
+
"aria-hidden": "true",
|
|
217
|
+
className: "pointer-events-none absolute -m-1.5 size-3 rounded-(--radius-pill) border-2 border-(--paper) shadow-[0_0_0_1px_var(--rule-hard)]",
|
|
218
|
+
style: { left: `${saturation * 100}%`, top: `${(1 - color.l) * 100}%`, background: opaque }
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
/* @__PURE__ */ jsx(
|
|
222
|
+
"input",
|
|
223
|
+
{
|
|
224
|
+
type: "range",
|
|
225
|
+
min: 0,
|
|
226
|
+
max: 100,
|
|
227
|
+
step: 1,
|
|
228
|
+
value: Math.round(saturation * 100),
|
|
229
|
+
"aria-label": "Chroma",
|
|
230
|
+
"aria-valuetext": `${Math.round(saturation * 100)} percent chroma`,
|
|
231
|
+
onChange: (event) => setPlane(Number(event.target.value) / 100, color.l),
|
|
232
|
+
className: "sr-only"
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ jsx(
|
|
236
|
+
"input",
|
|
237
|
+
{
|
|
238
|
+
type: "range",
|
|
239
|
+
min: 0,
|
|
240
|
+
max: 100,
|
|
241
|
+
step: 1,
|
|
242
|
+
value: Math.round(color.l * 100),
|
|
243
|
+
"aria-label": "Lightness",
|
|
244
|
+
"aria-valuetext": `${Math.round(color.l * 100)} percent lightness`,
|
|
245
|
+
onChange: (event) => setPlane(saturation, Number(event.target.value) / 100),
|
|
246
|
+
className: "sr-only"
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ jsx(
|
|
253
|
+
ColorTrack,
|
|
254
|
+
{
|
|
255
|
+
name: "Hue",
|
|
256
|
+
max: 360,
|
|
257
|
+
step: 1,
|
|
258
|
+
value: color.h,
|
|
259
|
+
announce: `${Math.round(color.h)} degrees`,
|
|
260
|
+
thumb: opaque,
|
|
261
|
+
track: `linear-gradient(to right in oklab, ${hueTrack})`,
|
|
262
|
+
onChange: (h) => commit({ ...color, h, c: saturation * maxChroma(color.l, h, space) })
|
|
263
|
+
}
|
|
264
|
+
),
|
|
265
|
+
/* @__PURE__ */ jsx(
|
|
266
|
+
ColorTrack,
|
|
267
|
+
{
|
|
268
|
+
name: "Opacity",
|
|
269
|
+
max: 100,
|
|
270
|
+
step: 1,
|
|
271
|
+
value: color.a * 100,
|
|
272
|
+
announce: `${Math.round(color.a * 100)} percent`,
|
|
273
|
+
thumb: formatColor(color, "oklch"),
|
|
274
|
+
track: `linear-gradient(to right, transparent, ${opaque}), ${checkerboard("8px")}`,
|
|
275
|
+
onChange: (percent) => commit({ ...color, a: percent / 100 })
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
/* @__PURE__ */ jsx(
|
|
279
|
+
Input,
|
|
280
|
+
{
|
|
281
|
+
value,
|
|
282
|
+
spellCheck: false,
|
|
283
|
+
autoComplete: "off",
|
|
284
|
+
"aria-label": `${label} as CSS`,
|
|
285
|
+
invalid: typed === null,
|
|
286
|
+
onChange: (event) => {
|
|
287
|
+
const next = event.target.value;
|
|
288
|
+
emitted.current = next;
|
|
289
|
+
if (controlled === void 0) setUncontrolled(next);
|
|
290
|
+
const parsed = parseColor(next);
|
|
291
|
+
if (parsed) {
|
|
292
|
+
setColor(parsed);
|
|
293
|
+
setFormat(colorFormat(next));
|
|
294
|
+
}
|
|
295
|
+
onValueChange?.(next);
|
|
296
|
+
},
|
|
297
|
+
className: "mono-meta"
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
] })
|
|
301
|
+
] });
|
|
302
|
+
}
|
|
303
|
+
function ColorTrack({ name, max, step, value, announce, track, thumb, onChange }) {
|
|
304
|
+
return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-3 text-sm text-(--ink-2)", children: [
|
|
305
|
+
/* @__PURE__ */ jsx("span", { className: "w-14 shrink-0", children: name }),
|
|
306
|
+
/* @__PURE__ */ jsx(
|
|
307
|
+
"input",
|
|
308
|
+
{
|
|
309
|
+
type: "range",
|
|
310
|
+
min: 0,
|
|
311
|
+
max,
|
|
312
|
+
step,
|
|
313
|
+
value,
|
|
314
|
+
"aria-valuetext": announce,
|
|
315
|
+
onChange: (event) => onChange(Number(event.target.value)),
|
|
316
|
+
style: { background: track },
|
|
317
|
+
className: cn(
|
|
318
|
+
"h-4 w-full cursor-pointer appearance-none rounded-(--radius-xs) shadow-[inset_0_0_0_1px_var(--rule)]",
|
|
319
|
+
"[&::-webkit-slider-thumb]:h-6 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-(--radius-xs) [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-(--paper) [&::-webkit-slider-thumb]:bg-(--thumb) [&::-webkit-slider-thumb]:bg-clip-padding [&::-webkit-slider-thumb]:shadow-[0_0_0_1px_var(--rule-hard)]",
|
|
320
|
+
"[&::-moz-range-thumb]:h-6 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-(--radius-xs) [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-(--paper) [&::-moz-range-thumb]:bg-(--thumb) [&::-moz-range-thumb]:bg-clip-padding [&::-moz-range-thumb]:shadow-[0_0_0_1px_var(--rule-hard)]"
|
|
321
|
+
),
|
|
322
|
+
ref: (node) => {
|
|
323
|
+
node?.style.setProperty("--thumb", thumb);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
] });
|
|
328
|
+
}
|
|
329
|
+
var ColorPicker_default = ColorPicker;
|
|
330
|
+
export {
|
|
331
|
+
ColorPicker,
|
|
332
|
+
ColorPicker_default as default
|
|
333
|
+
};
|
|
334
|
+
//# sourceMappingURL=ColorPicker.js.map
|