@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,189 @@
|
|
|
1
|
+
const clamp = (n, min = 0, max = 1) => Math.max(min, Math.min(max, n));
|
|
2
|
+
const wrapHue = (h) => (h % 360 + 360) % 360;
|
|
3
|
+
const multiply = (m, v) => m.map((row) => row.reduce((n, x, i) => n + x * (v[i] ?? 0), 0));
|
|
4
|
+
const linearize = (v) => Math.abs(v) <= 0.04045 ? v / 12.92 : Math.sign(v) * ((Math.abs(v) + 0.055) / 1.055) ** 2.4;
|
|
5
|
+
const encode = (v) => Math.abs(v) <= 31308e-7 ? 12.92 * v : Math.sign(v) * (1.055 * Math.abs(v) ** (1 / 2.4) - 0.055);
|
|
6
|
+
const RGB_XYZ = [
|
|
7
|
+
[0.4123907993, 0.3575843394, 0.1804807884],
|
|
8
|
+
[0.2126390059, 0.7151686788, 0.0721923154],
|
|
9
|
+
[0.0193308187, 0.1191947798, 0.9505321522]
|
|
10
|
+
];
|
|
11
|
+
const P3_XYZ = [
|
|
12
|
+
[0.4865709486, 0.2656676932, 0.1982172852],
|
|
13
|
+
[0.2289745641, 0.6917385218, 0.0792869141],
|
|
14
|
+
[0, 0.0451133819, 1.0439443689]
|
|
15
|
+
];
|
|
16
|
+
const XYZ_RGB = [
|
|
17
|
+
[3.2409699419, -1.5373831776, -0.4986107603],
|
|
18
|
+
[-0.9692436363, 1.8759675015, 0.0415550574],
|
|
19
|
+
[0.0556300797, -0.2039769589, 1.0569715142]
|
|
20
|
+
];
|
|
21
|
+
const XYZ_P3 = [
|
|
22
|
+
[2.4934969119, -0.9313836179, -0.4027107845],
|
|
23
|
+
[-0.8294889696, 1.7626640603, 0.0236246858],
|
|
24
|
+
[0.0358458302, -0.0761723893, 0.956884524]
|
|
25
|
+
];
|
|
26
|
+
const XYZ_LMS = [
|
|
27
|
+
[0.819022438, 0.3619062601, -0.1288737815],
|
|
28
|
+
[0.0329836539, 0.9292868616, 0.0361446664],
|
|
29
|
+
[0.0481771894, 0.2642395318, 0.6335478285]
|
|
30
|
+
];
|
|
31
|
+
const LMS_XYZ = [
|
|
32
|
+
[1.2268798734, -0.5578149966, 0.2813910502],
|
|
33
|
+
[-0.0405757626, 1.1122868294, -0.0717110667],
|
|
34
|
+
[-0.0763729497, -0.421493324, 1.5869240244]
|
|
35
|
+
];
|
|
36
|
+
function rgbToColor(rgb, a = 1, space = "srgb") {
|
|
37
|
+
const xyz = multiply(space === "p3" ? P3_XYZ : RGB_XYZ, rgb.map(linearize));
|
|
38
|
+
const [l, m, s] = multiply(XYZ_LMS, xyz).map(Math.cbrt);
|
|
39
|
+
const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
|
|
40
|
+
const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
|
|
41
|
+
const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
|
|
42
|
+
const c = Math.hypot(A, B);
|
|
43
|
+
const grey = c < 1e-7;
|
|
44
|
+
return {
|
|
45
|
+
l: clamp(L),
|
|
46
|
+
c: grey ? 0 : c,
|
|
47
|
+
h: grey ? 0 : wrapHue(Math.atan2(B, A) * 180 / Math.PI),
|
|
48
|
+
a: clamp(a)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function colorToRgb(color, space = "srgb") {
|
|
52
|
+
const a = color.c * Math.cos(color.h * Math.PI / 180);
|
|
53
|
+
const b = color.c * Math.sin(color.h * Math.PI / 180);
|
|
54
|
+
const lms = [
|
|
55
|
+
(color.l + 0.3963377774 * a + 0.2158037573 * b) ** 3,
|
|
56
|
+
(color.l - 0.1055613458 * a - 0.0638541728 * b) ** 3,
|
|
57
|
+
(color.l - 0.0894841775 * a - 1.291485548 * b) ** 3
|
|
58
|
+
];
|
|
59
|
+
return multiply(space === "p3" ? XYZ_P3 : XYZ_RGB, multiply(LMS_XYZ, lms)).map(encode);
|
|
60
|
+
}
|
|
61
|
+
function inGamut(color, space = "srgb") {
|
|
62
|
+
return colorToRgb(color, space).every((n) => n >= -1e-5 && n <= 1.00001);
|
|
63
|
+
}
|
|
64
|
+
function fitGamut(color, space = "srgb") {
|
|
65
|
+
if (inGamut(color, space)) return color;
|
|
66
|
+
let lo = 0;
|
|
67
|
+
let hi = color.c;
|
|
68
|
+
for (let i = 0; i < 20; i++) {
|
|
69
|
+
const mid = (lo + hi) / 2;
|
|
70
|
+
if (inGamut({ ...color, c: mid }, space)) lo = mid;
|
|
71
|
+
else hi = mid;
|
|
72
|
+
}
|
|
73
|
+
return { ...color, c: lo };
|
|
74
|
+
}
|
|
75
|
+
function maxChroma(l, h, space = "srgb") {
|
|
76
|
+
if (l <= 0 || l >= 1) return 0;
|
|
77
|
+
return fitGamut({ l, c: 0.5, h, a: 1 }, space).c;
|
|
78
|
+
}
|
|
79
|
+
function colorFormat(value) {
|
|
80
|
+
const text = value.trim();
|
|
81
|
+
if (/^oklch\(/i.test(text)) return "oklch";
|
|
82
|
+
if (/^color\(display-p3\s/i.test(text)) return "p3";
|
|
83
|
+
return "hex";
|
|
84
|
+
}
|
|
85
|
+
const round = (v, digits = 4) => Number(v.toFixed(digits));
|
|
86
|
+
function formatColor(color, format) {
|
|
87
|
+
const alpha = color.a < 1 ? ` / ${round(color.a)}` : "";
|
|
88
|
+
if (format === "oklch") {
|
|
89
|
+
return `oklch(${round(color.l)} ${round(color.c)} ${round(color.h, 2)}${alpha})`;
|
|
90
|
+
}
|
|
91
|
+
const space = format === "p3" ? "p3" : "srgb";
|
|
92
|
+
const rgb = colorToRgb(fitGamut(color, space), space);
|
|
93
|
+
if (format === "p3") {
|
|
94
|
+
return `color(display-p3 ${rgb.map((n) => round(clamp(n), 5)).join(" ")}${alpha})`;
|
|
95
|
+
}
|
|
96
|
+
const bytes = rgb.map((n) => Math.round(clamp(n) * 255));
|
|
97
|
+
if (color.a < 1) bytes.push(Math.round(color.a * 255));
|
|
98
|
+
return `#${bytes.map((n) => n.toString(16).padStart(2, "0")).join("")}`;
|
|
99
|
+
}
|
|
100
|
+
const NUMBER = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(%|deg|grad|rad|turn)?$/i;
|
|
101
|
+
function number(value, percentScale = 1, hue = false) {
|
|
102
|
+
const match = NUMBER.exec(value);
|
|
103
|
+
if (!match) return null;
|
|
104
|
+
const n = parseFloat(value);
|
|
105
|
+
if (!Number.isFinite(n)) return null;
|
|
106
|
+
const unit = match[1]?.toLowerCase();
|
|
107
|
+
if (hue) {
|
|
108
|
+
if (unit === "rad") return n * 180 / Math.PI;
|
|
109
|
+
if (unit === "turn") return n * 360;
|
|
110
|
+
if (unit === "grad") return n * 0.9;
|
|
111
|
+
return !unit || unit === "deg" ? n : null;
|
|
112
|
+
}
|
|
113
|
+
if (unit === "%") return n * percentScale / 100;
|
|
114
|
+
return unit ? null : n;
|
|
115
|
+
}
|
|
116
|
+
function parseColor(value) {
|
|
117
|
+
const text = value.trim().toLowerCase();
|
|
118
|
+
if (text === "transparent") return { l: 0, c: 0, h: 0, a: 0 };
|
|
119
|
+
if (/^#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/.test(text)) {
|
|
120
|
+
const short = text.slice(1);
|
|
121
|
+
const hex = short.length <= 4 ? [...short].map((c) => c + c).join("") : short;
|
|
122
|
+
const bytes = (hex.match(/../g) ?? []).map((c) => parseInt(c, 16) / 255);
|
|
123
|
+
return rgbToColor(bytes.slice(0, 3), bytes[3] ?? 1);
|
|
124
|
+
}
|
|
125
|
+
const match = /^(oklch|rgb|rgba|hsl|hsla|color)\(([^()]*)\)$/.exec(text);
|
|
126
|
+
if (!match) return null;
|
|
127
|
+
const kind = match[1] ?? "";
|
|
128
|
+
let body = (match[2] ?? "").trim();
|
|
129
|
+
const p3 = kind === "color";
|
|
130
|
+
if (p3) {
|
|
131
|
+
if (!body.startsWith("display-p3 ")) return null;
|
|
132
|
+
body = body.slice(11).trim();
|
|
133
|
+
}
|
|
134
|
+
const legacy = body.includes(",");
|
|
135
|
+
if (legacy && (p3 || kind === "oklch" || body.includes("/"))) return null;
|
|
136
|
+
const parts = legacy ? body.split(",").map((x) => x.trim()) : body.split(/\s*\/\s*/);
|
|
137
|
+
if (!legacy && parts.length > 2) return null;
|
|
138
|
+
const channels = legacy ? parts.slice(0, 3) : (parts[0] ?? "").split(/\s+/);
|
|
139
|
+
if (channels.length !== 3) return null;
|
|
140
|
+
if (legacy && parts.length !== 3 && parts.length !== 4) return null;
|
|
141
|
+
if (legacy && kind.startsWith("rgb") && channels.some((c) => c.endsWith("%")) && !channels.every((c) => c.endsWith("%"))) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const alphaText = legacy ? parts[3] : parts[1];
|
|
145
|
+
const alpha = alphaText === void 0 ? 1 : number(alphaText);
|
|
146
|
+
if (alpha === null) return null;
|
|
147
|
+
if (kind === "oklch") {
|
|
148
|
+
const l = number(channels[0] ?? "");
|
|
149
|
+
const c = number(channels[1] ?? "", 0.4);
|
|
150
|
+
const h = number(channels[2] ?? "", 1, true);
|
|
151
|
+
if (l === null || c === null || h === null) return null;
|
|
152
|
+
return { l: clamp(l), c: Math.max(0, c), h: wrapHue(h), a: clamp(alpha) };
|
|
153
|
+
}
|
|
154
|
+
if (kind.startsWith("hsl")) {
|
|
155
|
+
const h = number(channels[0] ?? "", 1, true);
|
|
156
|
+
const s = number(channels[1] ?? "");
|
|
157
|
+
const l = number(channels[2] ?? "");
|
|
158
|
+
if (h === null || s === null || l === null) return null;
|
|
159
|
+
if (!channels[1]?.endsWith("%") || !channels[2]?.endsWith("%")) return null;
|
|
160
|
+
const sat = clamp(s);
|
|
161
|
+
const light = clamp(l);
|
|
162
|
+
const amount = sat * Math.min(light, 1 - light);
|
|
163
|
+
const channel = (n) => {
|
|
164
|
+
const k = (n + wrapHue(h) / 30) % 12;
|
|
165
|
+
return light - amount * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
166
|
+
};
|
|
167
|
+
return rgbToColor([channel(0), channel(8), channel(4)], alpha);
|
|
168
|
+
}
|
|
169
|
+
const values = channels.map((c) => number(c, p3 ? 1 : 255));
|
|
170
|
+
if (values.some((n) => n === null)) return null;
|
|
171
|
+
return rgbToColor(
|
|
172
|
+
values.map((n) => p3 ? n ?? 0 : clamp((n ?? 0) / 255)),
|
|
173
|
+
alpha,
|
|
174
|
+
p3 ? "p3" : "srgb"
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
clamp,
|
|
179
|
+
colorFormat,
|
|
180
|
+
colorToRgb,
|
|
181
|
+
fitGamut,
|
|
182
|
+
formatColor,
|
|
183
|
+
inGamut,
|
|
184
|
+
maxChroma,
|
|
185
|
+
parseColor,
|
|
186
|
+
rgbToColor,
|
|
187
|
+
wrapHue
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/color.ts"],"sourcesContent":["/**\n * CSS colour maths, with no dependency and no DOM.\n *\n * Adapted from DialKit (https://github.com/joshpuckett/dialkit), MIT licensed:\n *\n * Copyright (c) 2026 Josh Puckett\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * The working space is OKLCH, and that is the substantive choice here rather\n * than an implementation detail. A picker built on HSV hands a reader two\n * colours at the same \"lightness\" where one of them is visibly darker, because\n * HSV's lightness is a property of the numbers rather than of the eye. Every\n * decision in `ColorPicker` — where the handle sits, what the hue strip looks\n * like at this lightness, which colours are reachable at all — depends on a\n * space that is perceptually uniform, and OKLCH is the one CSS ships.\n *\n * The matrices are the CSS Color 4 reference implementation's, D65.\n * https://www.w3.org/TR/css-color-4/#color-conversion-code\n */\n\n/** A colour in OKLCH: lightness 0–1, chroma, hue in degrees, alpha 0–1. */\nexport interface Color {\n l: number\n c: number\n h: number\n a: number\n}\n\n/** The notations this module reads and writes. */\nexport type ColorFormat = 'hex' | 'oklch' | 'p3'\n\n/** The two RGB gamuts a colour can be fitted to. */\nexport type ColorSpace = 'srgb' | 'p3'\n\ntype Triple = [number, number, number]\n\nexport const clamp = (n: number, min = 0, max = 1) => Math.max(min, Math.min(max, n))\n\nexport const wrapHue = (h: number) => ((h % 360) + 360) % 360\n\nconst multiply = (m: number[][], v: Triple): Triple =>\n m.map((row) => row.reduce((n, x, i) => n + x * (v[i] ?? 0), 0)) as Triple\n\n/** sRGB transfer function, undone. Signed, so an out-of-gamut channel survives. */\nconst linearize = (v: number) =>\n Math.abs(v) <= 0.04045 ? v / 12.92 : Math.sign(v) * ((Math.abs(v) + 0.055) / 1.055) ** 2.4\n\nconst encode = (v: number) =>\n Math.abs(v) <= 0.0031308 ? 12.92 * v : Math.sign(v) * (1.055 * Math.abs(v) ** (1 / 2.4) - 0.055)\n\nconst RGB_XYZ = [\n [0.4123907993, 0.3575843394, 0.1804807884],\n [0.2126390059, 0.7151686788, 0.0721923154],\n [0.0193308187, 0.1191947798, 0.9505321522],\n]\nconst P3_XYZ = [\n [0.4865709486, 0.2656676932, 0.1982172852],\n [0.2289745641, 0.6917385218, 0.0792869141],\n [0, 0.0451133819, 1.0439443689],\n]\nconst XYZ_RGB = [\n [3.2409699419, -1.5373831776, -0.4986107603],\n [-0.9692436363, 1.8759675015, 0.0415550574],\n [0.0556300797, -0.2039769589, 1.0569715142],\n]\nconst XYZ_P3 = [\n [2.4934969119, -0.9313836179, -0.4027107845],\n [-0.8294889696, 1.7626640603, 0.0236246858],\n [0.0358458302, -0.0761723893, 0.956884524],\n]\nconst XYZ_LMS = [\n [0.819022438, 0.3619062601, -0.1288737815],\n [0.0329836539, 0.9292868616, 0.0361446664],\n [0.0481771894, 0.2642395318, 0.6335478285],\n]\nconst LMS_XYZ = [\n [1.2268798734, -0.5578149966, 0.2813910502],\n [-0.0405757626, 1.1122868294, -0.0717110667],\n [-0.0763729497, -0.421493324, 1.5869240244],\n]\n\n/** Gamma-encoded RGB in 0–1 to OKLCH. */\nexport function rgbToColor(rgb: Triple, a = 1, space: ColorSpace = 'srgb'): Color {\n const xyz = multiply(space === 'p3' ? P3_XYZ : RGB_XYZ, rgb.map(linearize) as Triple)\n const [l, m, s] = multiply(XYZ_LMS, xyz).map(Math.cbrt) as Triple\n const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s\n const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s\n const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s\n const c = Math.hypot(A, B)\n // Below the threshold the hue is the angle of rounding error, not a hue. Left\n // in, a slider dragged to pure white would spin the strip through 360°.\n const grey = c < 1e-7\n return {\n l: clamp(L),\n c: grey ? 0 : c,\n h: grey ? 0 : wrapHue((Math.atan2(B, A) * 180) / Math.PI),\n a: clamp(a),\n }\n}\n\n/** OKLCH to gamma-encoded RGB in 0–1. May fall outside it — see `fitGamut`. */\nexport function colorToRgb(color: Color, space: ColorSpace = 'srgb'): Triple {\n const a = color.c * Math.cos((color.h * Math.PI) / 180)\n const b = color.c * Math.sin((color.h * Math.PI) / 180)\n const lms: Triple = [\n (color.l + 0.3963377774 * a + 0.2158037573 * b) ** 3,\n (color.l - 0.1055613458 * a - 0.0638541728 * b) ** 3,\n (color.l - 0.0894841775 * a - 1.291485548 * b) ** 3,\n ]\n return multiply(space === 'p3' ? XYZ_P3 : XYZ_RGB, multiply(LMS_XYZ, lms)).map(encode) as Triple\n}\n\nexport function inGamut(color: Color, space: ColorSpace = 'srgb'): boolean {\n return colorToRgb(color, space).every((n) => n >= -0.00001 && n <= 1.00001)\n}\n\n/**\n * Brings a colour inside a gamut by giving up CHROMA, and nothing else.\n *\n * The naive fix is to clip each channel at 0 and 1, which changes the hue and\n * the lightness together — a vivid blue clipped that way comes back purple and\n * darker. Bisecting on chroma keeps both, so what a reader loses is only the\n * saturation the display could never have shown them.\n */\nexport function fitGamut(color: Color, space: ColorSpace = 'srgb'): Color {\n if (inGamut(color, space)) return color\n let lo = 0\n let hi = color.c\n // Twenty halvings of a chroma under 0.5 lands well inside a 24-bit step.\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2\n if (inGamut({ ...color, c: mid }, space)) lo = mid\n else hi = mid\n }\n return { ...color, c: lo }\n}\n\n/** The most chroma a gamut holds at this lightness and hue — the plane's edge. */\nexport function maxChroma(l: number, h: number, space: ColorSpace = 'srgb'): number {\n if (l <= 0 || l >= 1) return 0\n return fitGamut({ l, c: 0.5, h, a: 1 }, space).c\n}\n\n/** Which notation a string is written in. Anything unrecognised reads as hex. */\nexport function colorFormat(value: string): ColorFormat {\n const text = value.trim()\n if (/^oklch\\(/i.test(text)) return 'oklch'\n if (/^color\\(display-p3\\s/i.test(text)) return 'p3'\n return 'hex'\n}\n\nconst round = (v: number, digits = 4) => Number(v.toFixed(digits))\n\n/**\n * A colour as a CSS string.\n *\n * Hex and Display P3 are bounded output spaces, so the colour is fitted on the\n * way out; OKLCH is not, and writing an out-of-gamut OKLCH is legitimate — the\n * browser fits it to whatever the display actually has.\n */\nexport function formatColor(color: Color, format: ColorFormat): string {\n const alpha = color.a < 1 ? ` / ${round(color.a)}` : ''\n if (format === 'oklch') {\n return `oklch(${round(color.l)} ${round(color.c)} ${round(color.h, 2)}${alpha})`\n }\n const space: ColorSpace = format === 'p3' ? 'p3' : 'srgb'\n const rgb = colorToRgb(fitGamut(color, space), space)\n if (format === 'p3') {\n return `color(display-p3 ${rgb.map((n) => round(clamp(n), 5)).join(' ')}${alpha})`\n }\n const bytes = rgb.map((n) => Math.round(clamp(n) * 255))\n if (color.a < 1) bytes.push(Math.round(color.a * 255))\n return `#${bytes.map((n) => n.toString(16).padStart(2, '0')).join('')}`\n}\n\nconst NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?(%|deg|grad|rad|turn)?$/i\n\n/** One CSS numeric token, in the unit its channel allows. */\nfunction number(value: string, percentScale = 1, hue = false): number | null {\n const match = NUMBER.exec(value)\n if (!match) return null\n const n = parseFloat(value)\n if (!Number.isFinite(n)) return null\n const unit = match[1]?.toLowerCase()\n if (hue) {\n if (unit === 'rad') return (n * 180) / Math.PI\n if (unit === 'turn') return n * 360\n if (unit === 'grad') return n * 0.9\n return !unit || unit === 'deg' ? n : null\n }\n if (unit === '%') return (n * percentScale) / 100\n return unit ? null : n\n}\n\n/**\n * An absolute CSS colour as OKLCH, or `null` when the string is not one.\n *\n * Hex, `rgb()`, `hsl()`, `oklch()` and `color(display-p3 …)`, in both the\n * comma and the space syntax. Named colours are deliberately absent: resolving\n * them needs a table of a hundred and forty-eight entries or a DOM, and a\n * picker that accepts \"rebeccapurple\" but not \"papayawhip\" is worse than one\n * that accepts neither.\n */\nexport function parseColor(value: string): Color | null {\n const text = value.trim().toLowerCase()\n if (text === 'transparent') return { l: 0, c: 0, h: 0, a: 0 }\n\n if (/^#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/.test(text)) {\n const short = text.slice(1)\n const hex = short.length <= 4 ? [...short].map((c) => c + c).join('') : short\n const bytes = (hex.match(/../g) ?? []).map((c) => parseInt(c, 16) / 255)\n return rgbToColor(bytes.slice(0, 3) as Triple, bytes[3] ?? 1)\n }\n\n const match = /^(oklch|rgb|rgba|hsl|hsla|color)\\(([^()]*)\\)$/.exec(text)\n if (!match) return null\n const kind = match[1] ?? ''\n let body = (match[2] ?? '').trim()\n\n const p3 = kind === 'color'\n if (p3) {\n if (!body.startsWith('display-p3 ')) return null\n body = body.slice(11).trim()\n }\n\n // The comma syntax is the legacy one, and it never applied to `oklch()` or\n // `color()`; mixing it with the modern `/` alpha is not a colour either.\n const legacy = body.includes(',')\n if (legacy && (p3 || kind === 'oklch' || body.includes('/'))) return null\n\n const parts = legacy ? body.split(',').map((x) => x.trim()) : body.split(/\\s*\\/\\s*/)\n if (!legacy && parts.length > 2) return null\n const channels = legacy ? parts.slice(0, 3) : (parts[0] ?? '').split(/\\s+/)\n if (channels.length !== 3) return null\n if (legacy && parts.length !== 3 && parts.length !== 4) return null\n // Legacy rgb() is all percentages or all numbers, never a mixture.\n if (\n legacy &&\n kind.startsWith('rgb') &&\n channels.some((c) => c.endsWith('%')) &&\n !channels.every((c) => c.endsWith('%'))\n ) {\n return null\n }\n\n const alphaText = legacy ? parts[3] : parts[1]\n const alpha = alphaText === undefined ? 1 : number(alphaText)\n if (alpha === null) return null\n\n if (kind === 'oklch') {\n const l = number(channels[0] ?? '')\n // 100% chroma is 0.4 by the specification, not 1.\n const c = number(channels[1] ?? '', 0.4)\n const h = number(channels[2] ?? '', 1, true)\n if (l === null || c === null || h === null) return null\n return { l: clamp(l), c: Math.max(0, c), h: wrapHue(h), a: clamp(alpha) }\n }\n\n if (kind.startsWith('hsl')) {\n const h = number(channels[0] ?? '', 1, true)\n const s = number(channels[1] ?? '')\n const l = number(channels[2] ?? '')\n if (h === null || s === null || l === null) return null\n if (!channels[1]?.endsWith('%') || !channels[2]?.endsWith('%')) return null\n const sat = clamp(s)\n const light = clamp(l)\n const amount = sat * Math.min(light, 1 - light)\n const channel = (n: number) => {\n const k = (n + wrapHue(h) / 30) % 12\n return light - amount * Math.max(-1, Math.min(k - 3, 9 - k, 1))\n }\n return rgbToColor([channel(0), channel(8), channel(4)], alpha)\n }\n\n const values = channels.map((c) => number(c, p3 ? 1 : 255))\n if (values.some((n) => n === null)) return null\n return rgbToColor(\n values.map((n) => (p3 ? (n ?? 0) : clamp((n ?? 0) / 255))) as Triple,\n alpha,\n p3 ? 'p3' : 'srgb',\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three things a numeric control has to do to a typed number, in one place.
|
|
3
|
+
*
|
|
4
|
+
* `Slider` and `NumberField` both take a number from a keyboard and both have
|
|
5
|
+
* to reconcile it with `min`, `max` and `step`. Written twice they drift, and
|
|
6
|
+
* they drift in the direction nobody tests: a slider that snaps 0.1 + 0.2 to
|
|
7
|
+
* `0.30000000000000004` and a field beside it that prints `0.3`.
|
|
8
|
+
*
|
|
9
|
+
* The step base is `min`, not zero, because that is what the HTML step
|
|
10
|
+
* algorithm uses — a range from 5 to 100 stepping by 10 lands on 15, not on 10.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Decimal places implied by a step.
|
|
14
|
+
*
|
|
15
|
+
* Snapping is arithmetic on binary floats, so a value that should be exactly
|
|
16
|
+
* one step from the last one usually is not. Rounding the result to the step's
|
|
17
|
+
* own precision is what stops that reaching a readout — and the step's own
|
|
18
|
+
* precision is the most a caller can have meant.
|
|
19
|
+
*/
|
|
20
|
+
declare function decimalsForStep(step: number): number;
|
|
21
|
+
/** Rounds to the nearest step from `min`, at the step's own precision. */
|
|
22
|
+
declare function snapToStep(value: number, step: number, min?: number): number;
|
|
23
|
+
/** Holds a value inside a range. An inverted range yields its own lower bound. */
|
|
24
|
+
declare function clampToRange(value: number, min: number, max: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* A typed string as a number, or `null` when it is not one yet.
|
|
27
|
+
*
|
|
28
|
+
* `null` rather than `NaN` because the caller has to tell "not a number" from
|
|
29
|
+
* "not finished being typed" and act the same way on both: leave the committed
|
|
30
|
+
* value alone. `Number('')` is `0`, which is the trap this exists for — an
|
|
31
|
+
* emptied box would otherwise commit zero on every keystroke that cleared it.
|
|
32
|
+
*/
|
|
33
|
+
declare function parseNumber(text: string): number | null;
|
|
34
|
+
|
|
35
|
+
export { clampToRange, decimalsForStep, parseNumber, snapToStep };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function decimalsForStep(step) {
|
|
2
|
+
if (!Number.isFinite(step) || step <= 0) return 0;
|
|
3
|
+
const text = String(step);
|
|
4
|
+
const exponential = /e-(\d+)$/i.exec(text);
|
|
5
|
+
if (exponential) return Number(exponential[1]);
|
|
6
|
+
return text.split(".")[1]?.length ?? 0;
|
|
7
|
+
}
|
|
8
|
+
function snapToStep(value, step, min = 0) {
|
|
9
|
+
if (!Number.isFinite(step) || step <= 0) return value;
|
|
10
|
+
const base = Number.isFinite(min) ? min : 0;
|
|
11
|
+
const snapped = base + Math.round((value - base) / step) * step;
|
|
12
|
+
return Number(snapped.toFixed(decimalsForStep(step)));
|
|
13
|
+
}
|
|
14
|
+
function clampToRange(value, min, max) {
|
|
15
|
+
return Math.min(Math.max(value, min), max);
|
|
16
|
+
}
|
|
17
|
+
function parseNumber(text) {
|
|
18
|
+
const trimmed = text.trim();
|
|
19
|
+
if (trimmed === "") return null;
|
|
20
|
+
const value = Number(trimmed);
|
|
21
|
+
return Number.isFinite(value) ? value : null;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
clampToRange,
|
|
25
|
+
decimalsForStep,
|
|
26
|
+
parseNumber,
|
|
27
|
+
snapToStep
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=numeric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/numeric.ts"],"sourcesContent":["/**\n * The three things a numeric control has to do to a typed number, in one place.\n *\n * `Slider` and `NumberField` both take a number from a keyboard and both have\n * to reconcile it with `min`, `max` and `step`. Written twice they drift, and\n * they drift in the direction nobody tests: a slider that snaps 0.1 + 0.2 to\n * `0.30000000000000004` and a field beside it that prints `0.3`.\n *\n * The step base is `min`, not zero, because that is what the HTML step\n * algorithm uses — a range from 5 to 100 stepping by 10 lands on 15, not on 10.\n */\n\n/**\n * Decimal places implied by a step.\n *\n * Snapping is arithmetic on binary floats, so a value that should be exactly\n * one step from the last one usually is not. Rounding the result to the step's\n * own precision is what stops that reaching a readout — and the step's own\n * precision is the most a caller can have meant.\n */\nexport function decimalsForStep(step: number): number {\n if (!Number.isFinite(step) || step <= 0) return 0\n const text = String(step)\n // Exponential notation carries its precision in the exponent, and `1e-7` has\n // no '.' to split on — `String(0.0000001)` is exactly that.\n const exponential = /e-(\\d+)$/i.exec(text)\n if (exponential) return Number(exponential[1])\n return text.split('.')[1]?.length ?? 0\n}\n\n/** Rounds to the nearest step from `min`, at the step's own precision. */\nexport function snapToStep(value: number, step: number, min = 0): number {\n if (!Number.isFinite(step) || step <= 0) return value\n const base = Number.isFinite(min) ? min : 0\n const snapped = base + Math.round((value - base) / step) * step\n return Number(snapped.toFixed(decimalsForStep(step)))\n}\n\n/** Holds a value inside a range. An inverted range yields its own lower bound. */\nexport function clampToRange(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n\n/**\n * A typed string as a number, or `null` when it is not one yet.\n *\n * `null` rather than `NaN` because the caller has to tell \"not a number\" from\n * \"not finished being typed\" and act the same way on both: leave the committed\n * value alone. `Number('')` is `0`, which is the trap this exists for — an\n * emptied box would otherwise commit zero on every keystroke that cleared it.\n */\nexport function parseNumber(text: string): number | null {\n const trimmed = text.trim()\n if (trimmed === '') return null\n const value = Number(trimmed)\n return Number.isFinite(value) ? value : null\n}\n"],"mappings":"AAoBO,SAAS,gBAAgB,MAAsB;AACpD,MAAI,CAAC,OAAO,SAAS,IAAI,KAAK,QAAQ,EAAG,QAAO;AAChD,QAAM,OAAO,OAAO,IAAI;AAGxB,QAAM,cAAc,YAAY,KAAK,IAAI;AACzC,MAAI,YAAa,QAAO,OAAO,YAAY,CAAC,CAAC;AAC7C,SAAO,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,UAAU;AACvC;AAGO,SAAS,WAAW,OAAe,MAAc,MAAM,GAAW;AACvE,MAAI,CAAC,OAAO,SAAS,IAAI,KAAK,QAAQ,EAAG,QAAO;AAChD,QAAM,OAAO,OAAO,SAAS,GAAG,IAAI,MAAM;AAC1C,QAAM,UAAU,OAAO,KAAK,OAAO,QAAQ,QAAQ,IAAI,IAAI;AAC3D,SAAO,OAAO,QAAQ,QAAQ,gBAAgB,IAAI,CAAC,CAAC;AACtD;AAGO,SAAS,aAAa,OAAe,KAAa,KAAqB;AAC5E,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;AAUO,SAAS,YAAY,MAA6B;AACvD,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,GAAI,QAAO;AAC3B,QAAM,QAAQ,OAAO,OAAO;AAC5B,SAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAC1C;","names":[]}
|
|
@@ -7,8 +7,8 @@ interface OverlayContainerProps {
|
|
|
7
7
|
children: ReactNode;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Redirects every overlay in the subtree — popover, select, menu, tooltip
|
|
11
|
-
* a given element instead of `document.body`.
|
|
10
|
+
* Redirects every overlay in the subtree — popover, select, menu, tooltip,
|
|
11
|
+
* dialog, sheet — into a given element instead of `document.body`.
|
|
12
12
|
*
|
|
13
13
|
* Two problems, one cause. An overlay portalled to the body is positioned
|
|
14
14
|
* against the VIEWPORT, so inside a bounded frame (a documentation example, a
|
|
@@ -20,7 +20,11 @@ interface OverlayContainerProps {
|
|
|
20
20
|
* inherits what the frame declares, and collides with the frame's edges.
|
|
21
21
|
*
|
|
22
22
|
* The container must be positioned (`relative` is enough) for the panel to be
|
|
23
|
-
* placed against it rather than against the nearest positioned ancestor.
|
|
23
|
+
* placed against it rather than against the nearest positioned ancestor. The
|
|
24
|
+
* modal surfaces need it for a second reason: they place themselves with
|
|
25
|
+
* `position: fixed`, which resolves against the VIEWPORT whatever element they
|
|
26
|
+
* are portalled into, so a named container switches them to `absolute` — and
|
|
27
|
+
* an unpositioned container would then hand them the wrong box.
|
|
24
28
|
*
|
|
25
29
|
* @example
|
|
26
30
|
* const [frame, setFrame] = useState<HTMLElement | null>(null)
|
|
@@ -31,7 +35,13 @@ interface OverlayContainerProps {
|
|
|
31
35
|
declare function OverlayContainer({ container, children }: OverlayContainerProps): react.JSX.Element;
|
|
32
36
|
/**
|
|
33
37
|
* The element overlays in this subtree should render into, or `null` for the
|
|
34
|
-
* document body.
|
|
38
|
+
* document body.
|
|
39
|
+
*
|
|
40
|
+
* Every portal in the library reads this. That sentence was false for a
|
|
41
|
+
* release: `Dialog` and `Sheet` rendered the Radix portal with no container and
|
|
42
|
+
* never called this hook, and their props derive from `Content`, which has no
|
|
43
|
+
* `container` — so a caller could not pass one either, and every modal example
|
|
44
|
+
* on the documentation site escaped the preview card it was drawn in.
|
|
35
45
|
*/
|
|
36
46
|
declare function useOverlayContainer(): HTMLElement | null;
|
|
37
47
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/overlay-container.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, useContext } from 'react'\nimport type { ReactNode } from 'react'\n\nconst OverlayContainerContext = createContext<HTMLElement | null>(null)\n\nexport interface OverlayContainerProps {\n /** The element overlays should render into. `null` restores the default. */\n container: HTMLElement | null\n children: ReactNode\n}\n\n/**\n * Redirects every overlay in the subtree — popover, select, menu, tooltip — into
|
|
1
|
+
{"version":3,"sources":["../../src/lib/overlay-container.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, useContext } from 'react'\nimport type { ReactNode } from 'react'\n\nconst OverlayContainerContext = createContext<HTMLElement | null>(null)\n\nexport interface OverlayContainerProps {\n /** The element overlays should render into. `null` restores the default. */\n container: HTMLElement | null\n children: ReactNode\n}\n\n/**\n * Redirects every overlay in the subtree — popover, select, menu, tooltip,\n * dialog, sheet — into a given element instead of `document.body`.\n *\n * Two problems, one cause. An overlay portalled to the body is positioned\n * against the VIEWPORT, so inside a bounded frame (a documentation example, a\n * device preview, a canvas) it flips and shifts against edges the reader cannot\n * see, and lands outside the box it belongs to. It also leaves the subtree, so\n * `dir=\"rtl\"` and `data-density` set on that frame stop reaching it.\n *\n * Naming the container fixes both: the panel renders inside the frame,\n * inherits what the frame declares, and collides with the frame's edges.\n *\n * The container must be positioned (`relative` is enough) for the panel to be\n * placed against it rather than against the nearest positioned ancestor. The\n * modal surfaces need it for a second reason: they place themselves with\n * `position: fixed`, which resolves against the VIEWPORT whatever element they\n * are portalled into, so a named container switches them to `absolute` — and\n * an unpositioned container would then hand them the wrong box.\n *\n * @example\n * const [frame, setFrame] = useState<HTMLElement | null>(null)\n * <div ref={setFrame} className=\"relative\" data-density=\"compact\">\n * <OverlayContainer container={frame}>{children}</OverlayContainer>\n * </div>\n */\nexport function OverlayContainer({ container, children }: OverlayContainerProps) {\n return <OverlayContainerContext value={container}>{children}</OverlayContainerContext>\n}\n\n/**\n * The element overlays in this subtree should render into, or `null` for the\n * document body.\n *\n * Every portal in the library reads this. That sentence was false for a\n * release: `Dialog` and `Sheet` rendered the Radix portal with no container and\n * never called this hook, and their props derive from `Content`, which has no\n * `container` — so a caller could not pass one either, and every modal example\n * on the documentation site escaped the preview card it was drawn in.\n */\nexport function useOverlayContainer(): HTMLElement | null {\n return useContext(OverlayContainerContext)\n}\n"],"mappings":";AAwCS;AAtCT,SAAS,eAAe,kBAAkB;AAG1C,MAAM,0BAA0B,cAAkC,IAAI;AAkC/D,SAAS,iBAAiB,EAAE,WAAW,SAAS,GAA0B;AAC/E,SAAO,oBAAC,2BAAwB,OAAO,WAAY,UAAS;AAC9D;AAYO,SAAS,sBAA0C;AACxD,SAAO,WAAW,uBAAuB;AAC3C;","names":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development warnings, written for the reader most likely to hit them.
|
|
3
|
+
*
|
|
4
|
+
* The skill in this package documents a handful of ways to misuse a component
|
|
5
|
+
* that fail SILENTLY — a `Field` whose child is a wrapper wires no label, an
|
|
6
|
+
* icon-only `Button` with no accessible name renders perfectly and is invisible
|
|
7
|
+
* to a screen reader. Documentation is the wrong place for those on its own: it
|
|
8
|
+
* only helps a reader who went looking, and the whole problem is that nothing
|
|
9
|
+
* told them to look.
|
|
10
|
+
*
|
|
11
|
+
* So the component says it, at the moment it happens. The shape follows what an
|
|
12
|
+
* agent needs to repair its own call without asking anyone: a stable `code` it
|
|
13
|
+
* can branch on, the `field` that caused it, an imperative one-line `fix`, and
|
|
14
|
+
* where to get the rest. A message that only says "invalid props" makes an
|
|
15
|
+
* agent guess, and it guesses by trying things.
|
|
16
|
+
*
|
|
17
|
+
* Three constraints this has to keep:
|
|
18
|
+
*
|
|
19
|
+
* - **Dev only.** Every call site is behind `process.env.NODE_ENV`, which the
|
|
20
|
+
* consumer's bundler replaces and then drops. Nothing here reaches a
|
|
21
|
+
* production bundle.
|
|
22
|
+
* - **Once per problem.** React renders twice in StrictMode and again on every
|
|
23
|
+
* state change; a warning printed each time is noise that trains people to
|
|
24
|
+
* ignore it.
|
|
25
|
+
* - **Never throws.** A warning that breaks the render is worse than the bug it
|
|
26
|
+
* describes, and this runs during render.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* True outside a production build, and false when nothing said either way.
|
|
30
|
+
*
|
|
31
|
+
* Every bundler replaces `process.env.NODE_ENV` with a literal, which folds
|
|
32
|
+
* this to `false` and lets the guarded calls below be dropped entirely. Off is
|
|
33
|
+
* the right default for the case where nothing replaced it: a warning that
|
|
34
|
+
* reaches a user's console is worse than one an author never sees.
|
|
35
|
+
*/
|
|
36
|
+
declare const DEV: boolean;
|
|
37
|
+
interface Warning {
|
|
38
|
+
/** Stable identifier. Never reused for a different cause. */
|
|
39
|
+
code: string;
|
|
40
|
+
/** What went wrong, in one declarative sentence. */
|
|
41
|
+
problem: string;
|
|
42
|
+
/** The prop or child that caused it. */
|
|
43
|
+
field: string;
|
|
44
|
+
/** Imperative, and self-sufficient — assume nobody opens the docs. */
|
|
45
|
+
fix: string;
|
|
46
|
+
/** The component to ask about. */
|
|
47
|
+
component: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Print one warning, once.
|
|
51
|
+
*
|
|
52
|
+
* Guarded at the call site too, so a production bundle drops the whole
|
|
53
|
+
* expression rather than the branch inside it.
|
|
54
|
+
*/
|
|
55
|
+
declare function warn({ code, problem, field, fix, component }: Warning): void;
|
|
56
|
+
/** Test seam: the dedupe is global state, and a suite needs it reset. */
|
|
57
|
+
declare function resetWarnings(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Warn when a prop that is required for accessibility holds nothing usable.
|
|
60
|
+
*
|
|
61
|
+
* `Table.caption`, `Progress.label` and their siblings are required in the type
|
|
62
|
+
* precisely because forgetting them ships a control nobody can use without
|
|
63
|
+
* sight — and an empty string satisfies the type while satisfying nothing else.
|
|
64
|
+
* That is exactly the shape a model produces when it knows a prop is mandatory
|
|
65
|
+
* and has nothing to put in it.
|
|
66
|
+
*
|
|
67
|
+
* Not applied to `Avatar.alt`. An empty `alt` is the correct, deliberate markup
|
|
68
|
+
* for a decorative image, so warning on it would be a false positive on a
|
|
69
|
+
* pattern the platform endorses.
|
|
70
|
+
*/
|
|
71
|
+
declare function warnBlankName(component: string, field: string, value: unknown, announces: string): void;
|
|
72
|
+
|
|
73
|
+
export { DEV, resetWarnings, warn, warnBlankName };
|
package/dist/lib/warn.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const DEV = typeof process !== "undefined" && process?.env?.NODE_ENV !== "production";
|
|
2
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3
|
+
function warn({ code, problem, field, fix, component }) {
|
|
4
|
+
if (!DEV) return;
|
|
5
|
+
const key = `${code}:${field}`;
|
|
6
|
+
if (seen.has(key)) return;
|
|
7
|
+
seen.add(key);
|
|
8
|
+
console.warn(
|
|
9
|
+
[
|
|
10
|
+
`[@misoto22/design] ${code}`,
|
|
11
|
+
` ${problem}`,
|
|
12
|
+
` field: ${field}`,
|
|
13
|
+
` fix: ${fix}`,
|
|
14
|
+
` docs: npx misoto22-design docs ${component}`
|
|
15
|
+
].join("\n")
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function resetWarnings() {
|
|
19
|
+
seen.clear();
|
|
20
|
+
}
|
|
21
|
+
function warnBlankName(component, field, value, announces) {
|
|
22
|
+
if (!DEV) return;
|
|
23
|
+
if (typeof value !== "string" || value.trim() !== "") return;
|
|
24
|
+
warn({
|
|
25
|
+
code: "REQUIRED_NAME_BLANK",
|
|
26
|
+
problem: `${component}.${field} is an empty string, so ${announces}. The type is satisfied; nothing else is.`,
|
|
27
|
+
field: `${component}.${field}`,
|
|
28
|
+
fix: `Give ${field} the words a person would need to understand this without seeing it.`,
|
|
29
|
+
component
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
DEV,
|
|
34
|
+
resetWarnings,
|
|
35
|
+
warn,
|
|
36
|
+
warnBlankName
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=warn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/warn.ts"],"sourcesContent":["/**\n * Development warnings, written for the reader most likely to hit them.\n *\n * The skill in this package documents a handful of ways to misuse a component\n * that fail SILENTLY — a `Field` whose child is a wrapper wires no label, an\n * icon-only `Button` with no accessible name renders perfectly and is invisible\n * to a screen reader. Documentation is the wrong place for those on its own: it\n * only helps a reader who went looking, and the whole problem is that nothing\n * told them to look.\n *\n * So the component says it, at the moment it happens. The shape follows what an\n * agent needs to repair its own call without asking anyone: a stable `code` it\n * can branch on, the `field` that caused it, an imperative one-line `fix`, and\n * where to get the rest. A message that only says \"invalid props\" makes an\n * agent guess, and it guesses by trying things.\n *\n * Three constraints this has to keep:\n *\n * - **Dev only.** Every call site is behind `process.env.NODE_ENV`, which the\n * consumer's bundler replaces and then drops. Nothing here reaches a\n * production bundle.\n * - **Once per problem.** React renders twice in StrictMode and again on every\n * state change; a warning printed each time is noise that trains people to\n * ignore it.\n * - **Never throws.** A warning that breaks the render is worse than the bug it\n * describes, and this runs during render.\n */\n\n/**\n * `process.env.NODE_ENV`, without pulling Node's types into a browser library.\n *\n * Declared module-locally rather than in a `.d.ts`: an ambient `process` there\n * would travel into the emitted declarations and collide with a consumer's own\n * Node types. The `typeof` guard is what makes it safe in a bundle that never\n * defines it.\n */\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined\n\n/**\n * True outside a production build, and false when nothing said either way.\n *\n * Every bundler replaces `process.env.NODE_ENV` with a literal, which folds\n * this to `false` and lets the guarded calls below be dropped entirely. Off is\n * the right default for the case where nothing replaced it: a warning that\n * reaches a user's console is worse than one an author never sees.\n */\nexport const DEV =\n typeof process !== 'undefined' && process?.env?.NODE_ENV !== 'production'\n\n/** Warnings already printed, keyed by code + detail, so a re-render is quiet. */\nconst seen = new Set<string>()\n\ninterface Warning {\n /** Stable identifier. Never reused for a different cause. */\n code: string\n /** What went wrong, in one declarative sentence. */\n problem: string\n /** The prop or child that caused it. */\n field: string\n /** Imperative, and self-sufficient — assume nobody opens the docs. */\n fix: string\n /** The component to ask about. */\n component: string\n}\n\n/**\n * Print one warning, once.\n *\n * Guarded at the call site too, so a production bundle drops the whole\n * expression rather than the branch inside it.\n */\nexport function warn({ code, problem, field, fix, component }: Warning): void {\n if (!DEV) return\n\n const key = `${code}:${field}`\n if (seen.has(key)) return\n seen.add(key)\n\n console.warn(\n [\n `[@misoto22/design] ${code}`,\n ` ${problem}`,\n ` field: ${field}`,\n ` fix: ${fix}`,\n ` docs: npx misoto22-design docs ${component}`,\n ].join('\\n'),\n )\n}\n\n/** Test seam: the dedupe is global state, and a suite needs it reset. */\nexport function resetWarnings(): void {\n seen.clear()\n}\n\n/**\n * Warn when a prop that is required for accessibility holds nothing usable.\n *\n * `Table.caption`, `Progress.label` and their siblings are required in the type\n * precisely because forgetting them ships a control nobody can use without\n * sight — and an empty string satisfies the type while satisfying nothing else.\n * That is exactly the shape a model produces when it knows a prop is mandatory\n * and has nothing to put in it.\n *\n * Not applied to `Avatar.alt`. An empty `alt` is the correct, deliberate markup\n * for a decorative image, so warning on it would be a false positive on a\n * pattern the platform endorses.\n */\nexport function warnBlankName(\n component: string,\n field: string,\n value: unknown,\n announces: string,\n): void {\n if (!DEV) return\n if (typeof value !== 'string' || value.trim() !== '') return\n\n warn({\n code: 'REQUIRED_NAME_BLANK',\n problem: `${component}.${field} is an empty string, so ${announces}. The type is satisfied; nothing else is.`,\n field: `${component}.${field}`,\n fix: `Give ${field} the words a person would need to understand this without seeing it.`,\n component,\n })\n}\n"],"mappings":"AA8CO,MAAM,MACX,OAAO,YAAY,eAAe,SAAS,KAAK,aAAa;AAG/D,MAAM,OAAO,oBAAI,IAAY;AAqBtB,SAAS,KAAK,EAAE,MAAM,SAAS,OAAO,KAAK,UAAU,GAAkB;AAC5E,MAAI,CAAC,IAAK;AAEV,QAAM,MAAM,GAAG,IAAI,IAAI,KAAK;AAC5B,MAAI,KAAK,IAAI,GAAG,EAAG;AACnB,OAAK,IAAI,GAAG;AAEZ,UAAQ;AAAA,IACN;AAAA,MACE,sBAAsB,IAAI;AAAA,MAC1B,KAAK,OAAO;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,YAAY,GAAG;AAAA,MACf,qCAAqC,SAAS;AAAA,IAChD,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAGO,SAAS,gBAAsB;AACpC,OAAK,MAAM;AACb;AAeO,SAAS,cACd,WACA,OACA,OACA,WACM;AACN,MAAI,CAAC,IAAK;AACV,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI;AAEtD,OAAK;AAAA,IACH,MAAM;AAAA,IACN,SAAS,GAAG,SAAS,IAAI,KAAK,2BAA2B,SAAS;AAAA,IAClE,OAAO,GAAG,SAAS,IAAI,KAAK;AAAA,IAC5B,KAAK,QAAQ,KAAK;AAAA,IAClB;AAAA,EACF,CAAC;AACH;","names":[]}
|
package/dist/semantic.css
CHANGED
|
@@ -105,14 +105,21 @@
|
|
|
105
105
|
Law 2 — a box-shadow is never blurred. The system has no elevation ramp;
|
|
106
106
|
depth is a hard offset in ink, applied per component. These three resolve
|
|
107
107
|
to nothing on purpose, so a component ported from a shadowed system stays
|
|
108
|
-
flat instead of drawing a blur the White Reset does not have.
|
|
109
|
-
|
|
108
|
+
flat instead of drawing a blur the White Reset does not have. --lift below
|
|
109
|
+
is the sanctioned offset idiom for anything that must read as raised. */
|
|
110
110
|
--shadow-color: transparent;
|
|
111
111
|
--shadow-sm: none;
|
|
112
112
|
--shadow: none;
|
|
113
113
|
--shadow-lg: none;
|
|
114
|
-
/* The one depth cue the system does have: a hard 3px ink offset, no blur
|
|
115
|
-
|
|
114
|
+
/* The one depth cue the system does have: a hard 3px ink offset, no blur,
|
|
115
|
+
in the accent rather than a grey because --shadow-offset points at --clay.
|
|
116
|
+
|
|
117
|
+
PUBLISHED, NOT CONSUMED. No component in this package sets either one —
|
|
118
|
+
there is not a single shadow-(--lift) in src/. What the library actually
|
|
119
|
+
separates with is a hairline, a change of ground, and the reversal that
|
|
120
|
+
Card variant="plate" reaches for. These two exist so a consumer building a
|
|
121
|
+
raised plate of their own has the system's answer instead of inventing a
|
|
122
|
+
blur; do not read them as describing what the library does. */
|
|
116
123
|
--lift: 3px 3px 0 0 var(--shadow-offset);
|
|
117
124
|
--lift-sm: 2px 2px 0 0 var(--shadow-offset);
|
|
118
125
|
|
|
@@ -126,8 +133,12 @@
|
|
|
126
133
|
--overlay: var(--scrim);
|
|
127
134
|
--disabled-opacity: 0.5;
|
|
128
135
|
|
|
129
|
-
/* ─── Stacking ───
|
|
130
|
-
|
|
136
|
+
/* ─── Stacking ─── two component-facing names onto the seven ranks. ──────
|
|
137
|
+
The other five ranks are read by their own names; only these two had a
|
|
138
|
+
component-facing spelling that outlived the rank it pointed at.
|
|
139
|
+
--z-dropdown pointed at --z-drawer, 100, which put every anchored panel
|
|
140
|
+
under the modal at 210 that opened it. */
|
|
141
|
+
--z-dropdown: var(--z-anchored);
|
|
131
142
|
--z-overlay: var(--z-scrim);
|
|
132
143
|
|
|
133
144
|
/* ─── Diagrams ───────────────────────────────────────────────────────────
|