@misoto22/folio 0.0.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/bin/folio-design.mjs +277 -0
- package/bin/migrate-legacy.mjs +81 -0
- package/dist/agent/Accordion.md +65 -0
- package/dist/agent/Actions.md +49 -0
- package/dist/agent/Alert.md +65 -0
- package/dist/agent/AppShell.md +69 -0
- package/dist/agent/ArchitectureFigure.md +72 -0
- package/dist/agent/AreaChart.md +94 -0
- package/dist/agent/Article.md +65 -0
- package/dist/agent/AspectRatio.md +58 -0
- package/dist/agent/Avatar.md +53 -0
- package/dist/agent/Badge.md +62 -0
- package/dist/agent/BarChart.md +93 -0
- package/dist/agent/BarList.md +67 -0
- package/dist/agent/BigNumber.md +70 -0
- package/dist/agent/BoxPlot.md +82 -0
- package/dist/agent/Breadcrumb.md +55 -0
- package/dist/agent/BulletChart.md +71 -0
- package/dist/agent/Button.md +81 -0
- package/dist/agent/Calendar.md +77 -0
- package/dist/agent/CalendarHeatmap.md +75 -0
- package/dist/agent/Card.md +72 -0
- package/dist/agent/Checkbox.md +57 -0
- package/dist/agent/Code.md +51 -0
- package/dist/agent/CodeBlock.md +77 -0
- package/dist/agent/Collapsible.md +68 -0
- package/dist/agent/Collection.md +169 -0
- package/dist/agent/ColorPicker.md +76 -0
- package/dist/agent/Combobox.md +77 -0
- package/dist/agent/Command.md +122 -0
- package/dist/agent/ComposedChart.md +82 -0
- package/dist/agent/Contact.md +90 -0
- package/dist/agent/Content.md +70 -0
- package/dist/agent/ContextMenu.md +93 -0
- package/dist/agent/Conversation.md +247 -0
- package/dist/agent/DataflowFigure.md +49 -0
- package/dist/agent/DatePicker.md +104 -0
- package/dist/agent/DescriptionList.md +69 -0
- package/dist/agent/Diagram.md +71 -0
- package/dist/agent/DiagramCanvas.md +71 -0
- package/dist/agent/DiagramExportMenu.md +65 -0
- package/dist/agent/DiagramInspector.md +73 -0
- package/dist/agent/DiagramLegend.md +56 -0
- package/dist/agent/DiagramMinimap.md +69 -0
- package/dist/agent/DiagramToolbar.md +70 -0
- package/dist/agent/Dialog.md +76 -0
- package/dist/agent/DropdownMenu.md +110 -0
- package/dist/agent/EmptyState.md +63 -0
- package/dist/agent/ErrorState.md +67 -0
- package/dist/agent/Evidence.md +165 -0
- package/dist/agent/Facet.md +107 -0
- package/dist/agent/Field.md +79 -0
- package/dist/agent/FigureBand.md +49 -0
- package/dist/agent/FloatingIconButton.md +61 -0
- package/dist/agent/FunnelChart.md +75 -0
- package/dist/agent/Heading.md +65 -0
- package/dist/agent/Heatmap.md +78 -0
- package/dist/agent/Histogram.md +88 -0
- package/dist/agent/Input.md +52 -0
- package/dist/agent/Kbd.md +48 -0
- package/dist/agent/LifecycleFigure.md +50 -0
- package/dist/agent/LineChart.md +85 -0
- package/dist/agent/LinkArrow.md +49 -0
- package/dist/agent/Markdown.md +69 -0
- package/dist/agent/Media.md +261 -0
- package/dist/agent/Metric.md +70 -0
- package/dist/agent/Metrics.md +114 -0
- package/dist/agent/Music.md +86 -0
- package/dist/agent/NativeSelect.md +62 -0
- package/dist/agent/NavItem.md +56 -0
- package/dist/agent/NumberField.md +73 -0
- package/dist/agent/PageHeader.md +69 -0
- package/dist/agent/Pagination.md +70 -0
- package/dist/agent/PieChart.md +80 -0
- package/dist/agent/Popover.md +80 -0
- package/dist/agent/Portfolio.md +93 -0
- package/dist/agent/PortfolioIndex.md +34 -0
- package/dist/agent/Progress.md +58 -0
- package/dist/agent/RadarChart.md +79 -0
- package/dist/agent/RadialChart.md +81 -0
- package/dist/agent/RadioGroup.md +66 -0
- package/dist/agent/Reading.md +233 -0
- package/dist/agent/Recovery.md +72 -0
- package/dist/agent/SankeyChart.md +85 -0
- package/dist/agent/ScatterChart.md +80 -0
- package/dist/agent/ScrollArea.md +62 -0
- package/dist/agent/SearchPalette.md +51 -0
- package/dist/agent/SearchableMenu.md +69 -0
- package/dist/agent/Select.md +102 -0
- package/dist/agent/Separator.md +60 -0
- package/dist/agent/SequenceFigure.md +51 -0
- package/dist/agent/Sheet.md +82 -0
- package/dist/agent/Sidebar.md +194 -0
- package/dist/agent/SiteNavigation.md +62 -0
- package/dist/agent/SiteShell.md +67 -0
- package/dist/agent/Skeleton.md +96 -0
- package/dist/agent/Slider.md +67 -0
- package/dist/agent/Sparkline.md +68 -0
- package/dist/agent/Spinner.md +62 -0
- package/dist/agent/StatusDot.md +56 -0
- package/dist/agent/StatusPill.md +55 -0
- package/dist/agent/Steps.md +68 -0
- package/dist/agent/Switch.md +50 -0
- package/dist/agent/Table.md +111 -0
- package/dist/agent/Tabs.md +71 -0
- package/dist/agent/Tag.md +67 -0
- package/dist/agent/Text.md +66 -0
- package/dist/agent/Textarea.md +46 -0
- package/dist/agent/Timeline.md +114 -0
- package/dist/agent/Timestamp.md +65 -0
- package/dist/agent/Toast.md +51 -0
- package/dist/agent/ToggleGroup.md +67 -0
- package/dist/agent/Toolbar.md +72 -0
- package/dist/agent/Tooltip.md +74 -0
- package/dist/agent/TreemapChart.md +76 -0
- package/dist/agent/WaterfallChart.md +86 -0
- package/dist/agent/WorkflowFigure.md +51 -0
- package/dist/agent/catalog.json +8006 -0
- package/dist/agent/index.md +182 -0
- package/dist/article.css +407 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +198 -0
- package/dist/charts/AreaChart/AreaChart.js +479 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +190 -0
- package/dist/charts/BarChart/BarChart.js +599 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +65 -0
- package/dist/charts/BarList/BarList.js +79 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +72 -0
- package/dist/charts/BigNumber/BigNumber.js +51 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +497 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +197 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.d.ts +106 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js +103 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +178 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +106 -0
- package/dist/charts/FunnelChart/FunnelChart.js +137 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +101 -0
- package/dist/charts/Heatmap/Heatmap.js +125 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +188 -0
- package/dist/charts/Histogram/Histogram.js +382 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +174 -0
- package/dist/charts/LineChart/LineChart.js +485 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +140 -0
- package/dist/charts/PieChart/PieChart.js +317 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +135 -0
- package/dist/charts/RadarChart/RadarChart.js +303 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +142 -0
- package/dist/charts/RadialChart/RadialChart.js +279 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +149 -0
- package/dist/charts/SankeyChart/SankeyChart.js +509 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +149 -0
- package/dist/charts/ScatterChart/ScatterChart.js +275 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +95 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +98 -0
- package/dist/charts/TreemapChart/TreemapChart.js +127 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +321 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +43 -0
- package/dist/charts/index.js +130 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +149 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +24 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +94 -0
- package/dist/charts/lib/export.js +62 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +81 -0
- package/dist/charts/lib/figure.js +62 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +144 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +43 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +58 -0
- package/dist/components/AppShell/AppShell.js +126 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Article/Article.d.ts +58 -0
- package/dist/components/Article/Article.js +34 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +38 -0
- package/dist/components/Avatar/Avatar.js +44 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +37 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +46 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +95 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +54 -0
- package/dist/components/Calendar/Calendar.js +369 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +55 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +26 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +145 -0
- package/dist/components/CodeBlock/CodeBlock.js +114 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +45 -0
- package/dist/components/Collapsible/Collapsible.js +60 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +77 -0
- package/dist/components/Combobox/Combobox.js +170 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +125 -0
- package/dist/components/Command/Command.js +204 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +63 -0
- package/dist/components/ContextMenu/ContextMenu.js +109 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +130 -0
- package/dist/components/DatePicker/DatePicker.js +257 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +86 -0
- package/dist/components/Diagram/Diagram.js +211 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +63 -0
- package/dist/components/Dialog/Dialog.js +90 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +87 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +120 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +55 -0
- package/dist/components/EmptyState/EmptyState.js +32 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +55 -0
- package/dist/components/ErrorState/ErrorState.js +41 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +111 -0
- package/dist/components/Field/Field.js +95 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +31 -0
- package/dist/components/FigureBand/FigureBand.js +51 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +34 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +27 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/Metric/Metric.d.ts +61 -0
- package/dist/components/Metric/Metric.js +51 -0
- package/dist/components/Metric/Metric.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +33 -0
- package/dist/components/NativeSelect/NativeSelect.js +44 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +92 -0
- package/dist/components/PageHeader/PageHeader.js +37 -0
- package/dist/components/PageHeader/PageHeader.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +67 -0
- package/dist/components/Pagination/Pagination.js +112 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +43 -0
- package/dist/components/Progress/Progress.js +57 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +49 -0
- package/dist/components/RadioGroup/RadioGroup.js +53 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +46 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +68 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +101 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +87 -0
- package/dist/components/Select/Select.js +130 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +48 -0
- package/dist/components/Separator/Separator.js +43 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +43 -0
- package/dist/components/Sheet/Sheet.js +79 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.d.ts +357 -0
- package/dist/components/Sidebar/Sidebar.js +447 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +74 -0
- package/dist/components/Slider/Slider.js +143 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +58 -0
- package/dist/components/Spinner/Spinner.js +49 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +30 -0
- package/dist/components/StatusPill/StatusPill.js +37 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +25 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +137 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +37 -0
- package/dist/components/Tabs/Tabs.js +205 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +87 -0
- package/dist/components/Tag/Tag.js +62 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +32 -0
- package/dist/components/Toast/Toast.js +64 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +46 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +88 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
- package/dist/diagrams/index.d.ts +17 -0
- package/dist/diagrams/index.js +29 -0
- package/dist/diagrams/index.js.map +1 -0
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +138 -0
- package/dist/diagrams/lib/frame.js +131 -0
- package/dist/diagrams/lib/frame.js.map +1 -0
- package/dist/diagrams/lib/geometry.d.ts +114 -0
- package/dist/diagrams/lib/geometry.js +113 -0
- package/dist/diagrams/lib/geometry.js.map +1 -0
- package/dist/diagrams/lib/legend.d.ts +32 -0
- package/dist/diagrams/lib/legend.js +84 -0
- package/dist/diagrams/lib/legend.js.map +1 -0
- package/dist/diagrams/lib/marks.d.ts +207 -0
- package/dist/diagrams/lib/marks.js +480 -0
- package/dist/diagrams/lib/marks.js.map +1 -0
- package/dist/diagrams/lib/route.d.ts +106 -0
- package/dist/diagrams/lib/route.js +201 -0
- package/dist/diagrams/lib/route.js.map +1 -0
- package/dist/diagrams/lib/wires.d.ts +59 -0
- package/dist/diagrams/lib/wires.js +94 -0
- package/dist/diagrams/lib/wires.js.map +1 -0
- package/dist/diagrams/spec.d.ts +405 -0
- package/dist/diagrams/spec.js +1 -0
- package/dist/diagrams/spec.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +300 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/control.d.ts +32 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +48 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/slot-content.d.ts +8 -0
- package/dist/lib/slot-content.js +17 -0
- package/dist/lib/slot-content.js.map +1 -0
- package/dist/lib/step-rail.d.ts +45 -0
- package/dist/lib/step-rail.js +47 -0
- package/dist/lib/step-rail.js.map +1 -0
- package/dist/lib/svg-export.d.ts +138 -0
- package/dist/lib/svg-export.js +198 -0
- package/dist/lib/svg-export.js.map +1 -0
- package/dist/lib/useClipboardCopy.d.ts +30 -0
- package/dist/lib/useClipboardCopy.js +37 -0
- package/dist/lib/useClipboardCopy.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +49 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +193 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +514 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +652 -0
- package/dist/tokens.d.ts +198 -0
- package/dist/tokens.js +1020 -0
- package/dist/tokens.json +1019 -0
- package/dist/website/Actions/Actions.d.ts +34 -0
- package/dist/website/Actions/Actions.js +29 -0
- package/dist/website/Actions/Actions.js.map +1 -0
- package/dist/website/Collection/Collection.d.ts +128 -0
- package/dist/website/Collection/Collection.js +162 -0
- package/dist/website/Collection/Collection.js.map +1 -0
- package/dist/website/Contact/Contact.d.ts +87 -0
- package/dist/website/Contact/Contact.js +94 -0
- package/dist/website/Contact/Contact.js.map +1 -0
- package/dist/website/Content/CodePanel.d.ts +27 -0
- package/dist/website/Content/CodePanel.js +30 -0
- package/dist/website/Content/CodePanel.js.map +1 -0
- package/dist/website/Content/Content.d.ts +29 -0
- package/dist/website/Content/Content.js +38 -0
- package/dist/website/Content/Content.js.map +1 -0
- package/dist/website/Conversation/Conversation.d.ts +193 -0
- package/dist/website/Conversation/Conversation.js +252 -0
- package/dist/website/Conversation/Conversation.js.map +1 -0
- package/dist/website/Evidence/Evidence.d.ts +116 -0
- package/dist/website/Evidence/Evidence.js +142 -0
- package/dist/website/Evidence/Evidence.js.map +1 -0
- package/dist/website/Media/Media.d.ts +173 -0
- package/dist/website/Media/Media.js +225 -0
- package/dist/website/Media/Media.js.map +1 -0
- package/dist/website/Media/MediaLightbox.d.ts +18 -0
- package/dist/website/Media/MediaLightbox.js +38 -0
- package/dist/website/Media/MediaLightbox.js.map +1 -0
- package/dist/website/Metrics/Metrics.d.ts +74 -0
- package/dist/website/Metrics/Metrics.js +96 -0
- package/dist/website/Metrics/Metrics.js.map +1 -0
- package/dist/website/Music/Music.d.ts +60 -0
- package/dist/website/Music/Music.js +80 -0
- package/dist/website/Music/Music.js.map +1 -0
- package/dist/website/Portfolio/FrameLayout.d.ts +9 -0
- package/dist/website/Portfolio/FrameLayout.js +42 -0
- package/dist/website/Portfolio/FrameLayout.js.map +1 -0
- package/dist/website/Portfolio/Portfolio.d.ts +49 -0
- package/dist/website/Portfolio/Portfolio.js +66 -0
- package/dist/website/Portfolio/Portfolio.js.map +1 -0
- package/dist/website/Portfolio/QuestionCard.d.ts +22 -0
- package/dist/website/Portfolio/QuestionCard.js +33 -0
- package/dist/website/Portfolio/QuestionCard.js.map +1 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.d.ts +21 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js +31 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js.map +1 -0
- package/dist/website/Reading/Reading.d.ts +203 -0
- package/dist/website/Reading/Reading.js +357 -0
- package/dist/website/Reading/Reading.js.map +1 -0
- package/dist/website/Recovery/Recovery.d.ts +39 -0
- package/dist/website/Recovery/Recovery.js +96 -0
- package/dist/website/Recovery/Recovery.js.map +1 -0
- package/dist/website/SearchPalette/SearchPalette.d.ts +59 -0
- package/dist/website/SearchPalette/SearchPalette.js +120 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -0
- package/dist/website/SiteNavigation/SiteNavigation.d.ts +46 -0
- package/dist/website/SiteNavigation/SiteNavigation.js +101 -0
- package/dist/website/SiteNavigation/SiteNavigation.js.map +1 -0
- package/dist/website/SiteShell/SiteShell.d.ts +45 -0
- package/dist/website/SiteShell/SiteShell.js +46 -0
- package/dist/website/SiteShell/SiteShell.js.map +1 -0
- package/dist/website/Timeline/Timeline.d.ts +80 -0
- package/dist/website/Timeline/Timeline.js +99 -0
- package/dist/website/Timeline/Timeline.js.map +1 -0
- package/dist/website/index.d.ts +27 -0
- package/dist/website/index.js +21 -0
- package/dist/website/index.js.map +1 -0
- package/dist/website-actions.css +6 -0
- package/dist/website-base.css +46 -0
- package/dist/website-collection.css +89 -0
- package/dist/website-contact.css +29 -0
- package/dist/website-content.css +17 -0
- package/dist/website-controls.css +91 -0
- package/dist/website-conversation.css +115 -0
- package/dist/website-evidence.css +56 -0
- package/dist/website-media.css +227 -0
- package/dist/website-metrics.css +15 -0
- package/dist/website-music.css +27 -0
- package/dist/website-portfolio.css +94 -0
- package/dist/website-reading.css +159 -0
- package/dist/website-recovery.css +28 -0
- package/dist/website-search.css +26 -0
- package/dist/website-shell.css +89 -0
- package/dist/website-timeline.css +43 -0
- package/dist/website.css +25 -0
- package/llms.txt +35 -0
- package/package.json +163 -5
- package/skills/folio-design/SKILL.md +228 -0
- package/skills/folio-design/evals/claims.json +95 -0
- package/skills/folio-design/evals/evals.json +84 -0
- package/skills/folio-design/rules/a11y.md +167 -0
- package/skills/folio-design/rules/composition.md +108 -0
- package/skills/folio-design/rules/forms.md +135 -0
- package/skills/folio-design/rules/naming.md +155 -0
- package/skills/folio-design/rules/tokens.md +133 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
4
|
+
import { createContext, useContext, useLayoutEffect, useRef, useState } from "react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
const MotionContext = createContext(null);
|
|
7
|
+
function Tabs({ value, defaultValue, onValueChange, swipe = true, orientation = "horizontal", activationMode = "automatic", className, ...rest }) {
|
|
8
|
+
const [internal, setInternal] = useState(defaultValue);
|
|
9
|
+
const current = value ?? internal;
|
|
10
|
+
const change = (next) => {
|
|
11
|
+
if (value === void 0) setInternal(next);
|
|
12
|
+
onValueChange?.(next);
|
|
13
|
+
};
|
|
14
|
+
return /* @__PURE__ */ jsx(MotionContext.Provider, { value: { value: current, change, swipe: swipe && orientation === "horizontal", automatic: activationMode === "automatic" }, children: /* @__PURE__ */ jsx(TabsPrimitive.Root, { ...rest, activationMode, orientation, value: current, onValueChange: change, className: cn("folio-tabs", className) }) });
|
|
15
|
+
}
|
|
16
|
+
function TabsList({ className, ref: forwardedRef, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onClickCapture, ...rest }) {
|
|
17
|
+
const motion = useContext(MotionContext);
|
|
18
|
+
const list = useRef(null);
|
|
19
|
+
const gesture = useRef(null);
|
|
20
|
+
const suppressClick = useRef(false);
|
|
21
|
+
const previousX = useRef(void 0);
|
|
22
|
+
useLayoutEffect(() => {
|
|
23
|
+
const element = list.current;
|
|
24
|
+
if (!element) return;
|
|
25
|
+
const measure = () => {
|
|
26
|
+
const active = element.querySelector("[role=tab][data-state=active]");
|
|
27
|
+
if (!active) return;
|
|
28
|
+
if (previousX.current !== void 0 && previousX.current !== active.offsetLeft) element.closest(".folio-tabs")?.style.setProperty("--tab-enter-x", active.offsetLeft > previousX.current ? "16px" : "-16px");
|
|
29
|
+
previousX.current = active.offsetLeft;
|
|
30
|
+
element.style.setProperty("--tab-x", `${active.offsetLeft}px`);
|
|
31
|
+
element.style.setProperty("--tab-y", `${active.offsetTop}px`);
|
|
32
|
+
element.style.setProperty("--tab-width", `${active.offsetWidth}px`);
|
|
33
|
+
element.style.setProperty("--tab-height", `${active.offsetHeight}px`);
|
|
34
|
+
element.dataset.measured = "true";
|
|
35
|
+
if (element.clientWidth > 0) {
|
|
36
|
+
const viewport = element.getBoundingClientRect();
|
|
37
|
+
const item = active.getBoundingClientRect();
|
|
38
|
+
const delta = item.left < viewport.left ? item.left - viewport.left : item.right > viewport.right ? item.right - viewport.right : 0;
|
|
39
|
+
if (delta) element.scrollBy({ left: delta, behavior: window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? "instant" : "smooth" });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
measure();
|
|
43
|
+
const observer = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(measure);
|
|
44
|
+
observer?.observe(element);
|
|
45
|
+
element.querySelectorAll("[role=tab]").forEach((tab) => observer?.observe(tab));
|
|
46
|
+
return () => observer?.disconnect();
|
|
47
|
+
}, [motion?.value]);
|
|
48
|
+
const reset = () => {
|
|
49
|
+
gesture.current = null;
|
|
50
|
+
list.current?.style.setProperty("--tab-drag-x", "0px");
|
|
51
|
+
list.current?.removeAttribute("data-dragging");
|
|
52
|
+
};
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
54
|
+
TabsPrimitive.List,
|
|
55
|
+
{
|
|
56
|
+
ref: (element) => {
|
|
57
|
+
list.current = element;
|
|
58
|
+
if (typeof forwardedRef === "function") forwardedRef(element);
|
|
59
|
+
else if (forwardedRef) forwardedRef.current = element;
|
|
60
|
+
},
|
|
61
|
+
"data-swipe": motion?.swipe || void 0,
|
|
62
|
+
onPointerDown: (event) => {
|
|
63
|
+
onPointerDown?.(event);
|
|
64
|
+
if (event.defaultPrevented || !motion?.swipe || event.button !== 0 || !event.isPrimary) return;
|
|
65
|
+
suppressClick.current = false;
|
|
66
|
+
gesture.current = { x: event.clientX, y: event.clientY, id: event.pointerId, dragged: false };
|
|
67
|
+
},
|
|
68
|
+
onPointerMove: (event) => {
|
|
69
|
+
onPointerMove?.(event);
|
|
70
|
+
const start = gesture.current;
|
|
71
|
+
if (!start || event.pointerId !== start.id) return;
|
|
72
|
+
const dx = event.clientX - start.x;
|
|
73
|
+
if (Math.abs(event.clientY - start.y) > Math.abs(dx) && !start.dragged) {
|
|
74
|
+
reset();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (Math.abs(dx) > 8) {
|
|
78
|
+
start.dragged = true;
|
|
79
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
80
|
+
event.currentTarget.dataset.dragging = "true";
|
|
81
|
+
event.currentTarget.style.setProperty("--tab-drag-x", `${Math.max(-64, Math.min(64, dx * 0.4))}px`);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
onPointerUp: (event) => {
|
|
85
|
+
onPointerUp?.(event);
|
|
86
|
+
const start = gesture.current;
|
|
87
|
+
if (!start) return;
|
|
88
|
+
const dx = event.clientX - start.x;
|
|
89
|
+
suppressClick.current = start.dragged;
|
|
90
|
+
if (start.dragged && Math.abs(dx) >= 36) {
|
|
91
|
+
const tabs = Array.from(event.currentTarget.querySelectorAll("[role=tab]:not([disabled])"));
|
|
92
|
+
const index = tabs.findIndex((tab) => tab.dataset.state === "active");
|
|
93
|
+
const rtl = getComputedStyle(event.currentTarget).direction === "rtl";
|
|
94
|
+
const next = tabs[index + (dx > 0 !== rtl ? 1 : -1)];
|
|
95
|
+
if (next?.dataset.tabValue) {
|
|
96
|
+
const alreadyFocused = document.activeElement === next;
|
|
97
|
+
next.focus({ preventScroll: true });
|
|
98
|
+
if (!motion?.automatic || alreadyFocused) motion?.change(next.dataset.tabValue);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
reset();
|
|
102
|
+
},
|
|
103
|
+
onPointerCancel: (event) => {
|
|
104
|
+
onPointerCancel?.(event);
|
|
105
|
+
reset();
|
|
106
|
+
},
|
|
107
|
+
onClickCapture: (event) => {
|
|
108
|
+
if (suppressClick.current) {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
event.stopPropagation();
|
|
111
|
+
suppressClick.current = false;
|
|
112
|
+
} else onClickCapture?.(event);
|
|
113
|
+
},
|
|
114
|
+
className: cn(
|
|
115
|
+
// `overflow-y-hidden` is not decoration. A strip only ever scrolls
|
|
116
|
+
// sideways, but `overflow-x: auto` on its own computes `overflow-y` to
|
|
117
|
+
// `auto` as well — and the active trigger's `-mb-px` rule leaves the
|
|
118
|
+
// content exactly one pixel taller than the box, which is enough for a
|
|
119
|
+
// vertical scrollbar to appear beside a row of tabs that has nothing
|
|
120
|
+
// to scroll.
|
|
121
|
+
"folio-tabs-list flex items-center overflow-x-auto overflow-y-hidden gap-1 border-b border-(--rule-2) scroll-slim",
|
|
122
|
+
className
|
|
123
|
+
),
|
|
124
|
+
...rest
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
function TabsTrigger({ className, onMouseDown, onClick, ...rest }) {
|
|
129
|
+
const motion = useContext(MotionContext);
|
|
130
|
+
return /* @__PURE__ */ jsx(
|
|
131
|
+
TabsPrimitive.Trigger,
|
|
132
|
+
{
|
|
133
|
+
"data-tab-value": rest.value,
|
|
134
|
+
onMouseDown: (event) => {
|
|
135
|
+
onMouseDown?.(event);
|
|
136
|
+
if (motion?.swipe && !event.defaultPrevented && event.button === 0) event.preventDefault();
|
|
137
|
+
},
|
|
138
|
+
onClick: (event) => {
|
|
139
|
+
onClick?.(event);
|
|
140
|
+
if (motion?.swipe && !event.defaultPrevented) {
|
|
141
|
+
const alreadyFocused = document.activeElement === event.currentTarget;
|
|
142
|
+
event.currentTarget.focus();
|
|
143
|
+
if (!motion.automatic || alreadyFocused) motion.change(rest.value);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
className: cn(
|
|
147
|
+
"-mb-px min-h-(--control-h-md) shrink-0 whitespace-nowrap border-b-2 border-transparent px-3.5 py-2 text-sm text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:text-(--ink) data-[state=active]:border-(--accent) data-[state=active]:text-(--accent-on-muted)",
|
|
148
|
+
className
|
|
149
|
+
),
|
|
150
|
+
...rest
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
function TabsContent({ className, onTouchStart, onTouchEnd, onTouchCancel, ...rest }) {
|
|
155
|
+
const motion = useContext(MotionContext);
|
|
156
|
+
const start = useRef(null);
|
|
157
|
+
return /* @__PURE__ */ jsx(
|
|
158
|
+
TabsPrimitive.Content,
|
|
159
|
+
{
|
|
160
|
+
"data-folio-animated": true,
|
|
161
|
+
onTouchStart: (event) => {
|
|
162
|
+
onTouchStart?.(event);
|
|
163
|
+
start.current = null;
|
|
164
|
+
if (!motion?.swipe || event.defaultPrevented || event.touches.length !== 1 || event.target.closest(".folio-tabs") !== event.currentTarget.closest(".folio-tabs") || event.target.closest("a,button,input,textarea,select,pre,code,[contenteditable=true],[data-no-swipe]")) return;
|
|
165
|
+
const touch = event.touches[0];
|
|
166
|
+
if (touch) start.current = { x: touch.clientX, y: touch.clientY };
|
|
167
|
+
},
|
|
168
|
+
onTouchEnd: (event) => {
|
|
169
|
+
onTouchEnd?.(event);
|
|
170
|
+
const origin = start.current;
|
|
171
|
+
start.current = null;
|
|
172
|
+
if (!origin || event.defaultPrevented || !event.changedTouches[0] || window.getSelection()?.toString()) return;
|
|
173
|
+
const dx = event.changedTouches[0].clientX - origin.x;
|
|
174
|
+
const dy = event.changedTouches[0].clientY - origin.y;
|
|
175
|
+
if (Math.abs(dx) < 48 || Math.abs(dx) < Math.abs(dy) * 1.5) return;
|
|
176
|
+
const list = event.currentTarget.closest(".folio-tabs")?.querySelector("[role=tablist]");
|
|
177
|
+
if (!list) return;
|
|
178
|
+
const tabs = Array.from(list.querySelectorAll("[role=tab]:not([disabled])"));
|
|
179
|
+
const index = tabs.findIndex((tab) => tab.dataset.state === "active");
|
|
180
|
+
const rtl = getComputedStyle(list).direction === "rtl";
|
|
181
|
+
const next = tabs[index + (dx < 0 !== rtl ? 1 : -1)];
|
|
182
|
+
if (next?.dataset.tabValue) {
|
|
183
|
+
const alreadyFocused = document.activeElement === next;
|
|
184
|
+
next.focus({ preventScroll: true });
|
|
185
|
+
if (!motion?.automatic || alreadyFocused) motion?.change(next.dataset.tabValue);
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
onTouchCancel: (event) => {
|
|
189
|
+
start.current = null;
|
|
190
|
+
onTouchCancel?.(event);
|
|
191
|
+
},
|
|
192
|
+
className: cn("folio-tabs-panel pt-5", className),
|
|
193
|
+
...rest
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
var Tabs_default = Tabs;
|
|
198
|
+
export {
|
|
199
|
+
Tabs,
|
|
200
|
+
TabsContent,
|
|
201
|
+
TabsList,
|
|
202
|
+
TabsTrigger,
|
|
203
|
+
Tabs_default as default
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=Tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["'use client'\n\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\nimport { createContext, useContext, useLayoutEffect, useRef, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\nconst MotionContext = createContext<{ value?: string; change: (value: string) => void; swipe: boolean; automatic: boolean } | null>(null)\n\n/** Accessible tabs with a moving marker and optional horizontal drag gestures. */\nexport function Tabs({ value, defaultValue, onValueChange, swipe = true, orientation = 'horizontal', activationMode = 'automatic', className, ...rest }: ComponentProps<typeof TabsPrimitive.Root> & { swipe?: boolean }) {\n const [internal, setInternal] = useState(defaultValue)\n const current = value ?? internal\n const change = (next: string) => { if (value === undefined) setInternal(next); onValueChange?.(next) }\n return <MotionContext.Provider value={{ value: current, change, swipe: swipe && orientation === 'horizontal', automatic: activationMode === 'automatic' }}><TabsPrimitive.Root {...rest} activationMode={activationMode} orientation={orientation} value={current} onValueChange={change} className={cn('folio-tabs', className)} /></MotionContext.Provider>\n}\n\n/**\n * The tab strip.\n *\n * Scrolls horizontally rather than wrapping. A wrapped second row of tabs moves\n * every tab below it when the strip grows, and the reader loses the one they\n * were about to click.\n *\n * @example\n * <Tabs defaultValue=\"preview\">\n * <TabsList>\n * <TabsTrigger value=\"preview\">Preview</TabsTrigger>\n * <TabsTrigger value=\"code\">Code</TabsTrigger>\n * </TabsList>\n * <TabsContent value=\"preview\">…</TabsContent>\n * </Tabs>\n */\nexport function TabsList({ className, ref: forwardedRef, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onClickCapture, ...rest }: ComponentProps<typeof TabsPrimitive.List>) {\n const motion = useContext(MotionContext)\n const list = useRef<HTMLDivElement>(null)\n const gesture = useRef<{ x: number; y: number; id: number; dragged: boolean } | null>(null)\n const suppressClick = useRef(false)\n const previousX = useRef<number | undefined>(undefined)\n useLayoutEffect(() => {\n const element = list.current\n if (!element) return\n const measure = () => {\n const active = element.querySelector<HTMLElement>('[role=tab][data-state=active]')\n if (!active) return\n if (previousX.current !== undefined && previousX.current !== active.offsetLeft) element.closest<HTMLElement>('.folio-tabs')?.style.setProperty('--tab-enter-x', active.offsetLeft > previousX.current ? '16px' : '-16px')\n previousX.current = active.offsetLeft\n element.style.setProperty('--tab-x', `${active.offsetLeft}px`)\n element.style.setProperty('--tab-y', `${active.offsetTop}px`)\n element.style.setProperty('--tab-width', `${active.offsetWidth}px`)\n element.style.setProperty('--tab-height', `${active.offsetHeight}px`)\n element.dataset.measured = 'true'\n if (element.clientWidth > 0) {\n const viewport = element.getBoundingClientRect()\n const item = active.getBoundingClientRect()\n const delta = item.left < viewport.left ? item.left - viewport.left : item.right > viewport.right ? item.right - viewport.right : 0\n if (delta) element.scrollBy({ left: delta, behavior: window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth' })\n }\n }\n measure()\n const observer = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(measure)\n observer?.observe(element)\n element.querySelectorAll('[role=tab]').forEach(tab => observer?.observe(tab))\n return () => observer?.disconnect()\n }, [motion?.value])\n const reset = () => { gesture.current = null; list.current?.style.setProperty('--tab-drag-x', '0px'); list.current?.removeAttribute('data-dragging') }\n return (\n <TabsPrimitive.List\n ref={element => { list.current = element; if (typeof forwardedRef === 'function') forwardedRef(element); else if (forwardedRef) forwardedRef.current = element }}\n data-swipe={motion?.swipe || undefined}\n onPointerDown={event => {\n onPointerDown?.(event)\n if (event.defaultPrevented || !motion?.swipe || event.button !== 0 || !event.isPrimary) return\n suppressClick.current = false\n gesture.current = { x: event.clientX, y: event.clientY, id: event.pointerId, dragged: false }\n }}\n onPointerMove={event => {\n onPointerMove?.(event)\n const start = gesture.current\n if (!start || event.pointerId !== start.id) return\n const dx = event.clientX - start.x\n if (Math.abs(event.clientY - start.y) > Math.abs(dx) && !start.dragged) { reset(); return }\n if (Math.abs(dx) > 8) {\n start.dragged = true\n event.currentTarget.setPointerCapture(event.pointerId)\n event.currentTarget.dataset.dragging = 'true'\n event.currentTarget.style.setProperty('--tab-drag-x', `${Math.max(-64, Math.min(64, dx * .4))}px`)\n }\n }}\n onPointerUp={event => {\n onPointerUp?.(event)\n const start = gesture.current\n if (!start) return\n const dx = event.clientX - start.x\n suppressClick.current = start.dragged\n if (start.dragged && Math.abs(dx) >= 36) {\n const tabs = Array.from(event.currentTarget.querySelectorAll<HTMLElement>('[role=tab]:not([disabled])'))\n const index = tabs.findIndex(tab => tab.dataset.state === 'active')\n const rtl = getComputedStyle(event.currentTarget).direction === 'rtl'\n const next = tabs[index + ((dx > 0) !== rtl ? 1 : -1)]\n if (next?.dataset.tabValue) {\n const alreadyFocused = document.activeElement === next\n next.focus({ preventScroll: true })\n if (!motion?.automatic || alreadyFocused) motion?.change(next.dataset.tabValue)\n }\n }\n reset()\n }}\n onPointerCancel={event => { onPointerCancel?.(event); reset() }}\n onClickCapture={event => { if (suppressClick.current) { event.preventDefault(); event.stopPropagation(); suppressClick.current = false } else onClickCapture?.(event) }}\n className={cn(\n // `overflow-y-hidden` is not decoration. A strip only ever scrolls\n // sideways, but `overflow-x: auto` on its own computes `overflow-y` to\n // `auto` as well — and the active trigger's `-mb-px` rule leaves the\n // content exactly one pixel taller than the box, which is enough for a\n // vertical scrollbar to appear beside a row of tabs that has nothing\n // to scroll.\n 'folio-tabs-list flex items-center overflow-x-auto overflow-y-hidden gap-1 border-b border-(--rule-2) scroll-slim',\n className,\n )}\n {...rest}\n />\n )\n}\n\n/**\n * One tab.\n *\n * The active marker is a 2px ink rule pulled onto the strip's own border with\n * `-mb-px`, so the two occupy the same line instead of stacking into a 3px\n * edge. 44px tall, because a tab is a pointer target like any other.\n */\nexport function TabsTrigger({ className, onMouseDown, onClick, ...rest }: ComponentProps<typeof TabsPrimitive.Trigger>) {\n const motion = useContext(MotionContext)\n return (\n <TabsPrimitive.Trigger\n data-tab-value={rest.value}\n onMouseDown={event => { onMouseDown?.(event); if (motion?.swipe && !event.defaultPrevented && event.button === 0) event.preventDefault() }}\n onClick={event => { onClick?.(event); if (motion?.swipe && !event.defaultPrevented) { const alreadyFocused = document.activeElement === event.currentTarget; event.currentTarget.focus(); if (!motion.automatic || alreadyFocused) motion.change(rest.value) } }}\n className={cn(\n '-mb-px min-h-(--control-h-md) shrink-0 whitespace-nowrap border-b-2 border-transparent px-3.5 py-2 text-sm text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:text-(--ink) data-[state=active]:border-(--accent) data-[state=active]:text-(--accent-on-muted)',\n className,\n )}\n {...rest}\n />\n )\n}\n\n/** The panel paired to a {@link TabsTrigger} by matching `value`. */\nexport function TabsContent({ className, onTouchStart, onTouchEnd, onTouchCancel, ...rest }: ComponentProps<typeof TabsPrimitive.Content>) {\n const motion = useContext(MotionContext)\n const start = useRef<{ x: number; y: number } | null>(null)\n return (\n <TabsPrimitive.Content\n data-folio-animated\n onTouchStart={event => {\n onTouchStart?.(event)\n start.current = null\n if (!motion?.swipe || event.defaultPrevented || event.touches.length !== 1 || (event.target as HTMLElement).closest('.folio-tabs') !== event.currentTarget.closest('.folio-tabs') || (event.target as HTMLElement).closest('a,button,input,textarea,select,pre,code,[contenteditable=true],[data-no-swipe]')) return\n const touch = event.touches[0]\n if (touch) start.current = { x: touch.clientX, y: touch.clientY }\n }}\n onTouchEnd={event => {\n onTouchEnd?.(event)\n const origin = start.current\n start.current = null\n if (!origin || event.defaultPrevented || !event.changedTouches[0] || window.getSelection()?.toString()) return\n const dx = event.changedTouches[0].clientX - origin.x\n const dy = event.changedTouches[0].clientY - origin.y\n if (Math.abs(dx) < 48 || Math.abs(dx) < Math.abs(dy) * 1.5) return\n const list = event.currentTarget.closest('.folio-tabs')?.querySelector('[role=tablist]')\n if (!list) return\n const tabs = Array.from(list.querySelectorAll<HTMLElement>('[role=tab]:not([disabled])'))\n const index = tabs.findIndex(tab => tab.dataset.state === 'active')\n const rtl = getComputedStyle(list).direction === 'rtl'\n const next = tabs[index + ((dx < 0) !== rtl ? 1 : -1)]\n if (next?.dataset.tabValue) {\n const alreadyFocused = document.activeElement === next\n next.focus({ preventScroll: true })\n if (!motion?.automatic || alreadyFocused) motion?.change(next.dataset.tabValue)\n }\n }}\n onTouchCancel={event => { start.current = null; onTouchCancel?.(event) }}\n className={cn('folio-tabs-panel pt-5', className)}\n {...rest}\n />\n )\n}\n\nexport default Tabs\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface TagBase extends Omit<HTMLAttributes<HTMLElement>, 'onClick'> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Renders the pressed/selected look, and declares the chip a toggle.
|
|
8
|
+
*
|
|
9
|
+
* An interactive chip reads `aria-pressed` off this same value, so the accent
|
|
10
|
+
* fill and the state a screen reader hears cannot drift apart. Leave it off
|
|
11
|
+
* for a chip whose `onClick` navigates or opens something: a control that is
|
|
12
|
+
* neither pressed nor unpressed is better announced as neither than as
|
|
13
|
+
* "not pressed".
|
|
14
|
+
*/
|
|
15
|
+
active?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Makes the chip ITSELF the filter control.
|
|
18
|
+
*
|
|
19
|
+
* This prop exists because the alternative did not survive contact with
|
|
20
|
+
* `onRemove`. The advice used to be to wrap the tag in a button at the call
|
|
21
|
+
* site, which is fine on its own and invalid the moment the chip is also
|
|
22
|
+
* removable: the remove control is a real `<button>`, so the wrapper puts a
|
|
23
|
+
* button inside a button — markup the parser splits into siblings, leaving a
|
|
24
|
+
* DOM neither the author nor the accessibility tree expects.
|
|
25
|
+
*
|
|
26
|
+
* With this the wrapper is never written. The chip carries the click, the
|
|
27
|
+
* focus ring and the pressed state on the element that draws them, and a
|
|
28
|
+
* removable filter chip renders its two controls side by side instead of one
|
|
29
|
+
* inside the other.
|
|
30
|
+
*/
|
|
31
|
+
onClick?: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The removable form: a chip for one thing the reader has already chosen.
|
|
35
|
+
*
|
|
36
|
+
* `removeLabel` is required alongside `onRemove` and not optional with a
|
|
37
|
+
* default, because "Remove" repeated down a row of filters is eight controls a
|
|
38
|
+
* screen reader cannot tell apart. Write the subject into it — "Remove
|
|
39
|
+
* TypeScript filter".
|
|
40
|
+
*/
|
|
41
|
+
interface TagRemovable {
|
|
42
|
+
/** Called when the reader dismisses the chip. */
|
|
43
|
+
onRemove: () => void;
|
|
44
|
+
/** The remove button's accessible name. Name the subject, not the action. */
|
|
45
|
+
removeLabel: string;
|
|
46
|
+
}
|
|
47
|
+
interface TagStatic {
|
|
48
|
+
onRemove?: never;
|
|
49
|
+
removeLabel?: never;
|
|
50
|
+
}
|
|
51
|
+
type TagProps = TagBase & (TagRemovable | TagStatic);
|
|
52
|
+
/**
|
|
53
|
+
* A subject label — a topic, a technology, a filter facet — that can filter
|
|
54
|
+
* with `onClick` and be dismissed with `onRemove`.
|
|
55
|
+
*
|
|
56
|
+
* Distinct from `Badge`, which carries a state or a count. A tag names what
|
|
57
|
+
* something is ABOUT, so several sit together in a row and the reader scans
|
|
58
|
+
* them; a badge is one fact about one record.
|
|
59
|
+
*
|
|
60
|
+
* This is where a `Token` component would have gone. It was not built: a token
|
|
61
|
+
* is a tag with a remove button, and the difference between the two is one
|
|
62
|
+
* prop, not one component. The system already ships three things that look
|
|
63
|
+
* alike — `Badge`, `Tag`, `StatusPill` — and a fourth whose whole distinction
|
|
64
|
+
* is an X on the end would be the one a call site picks by coin toss.
|
|
65
|
+
*
|
|
66
|
+
* Presentational until it is given a handler, and the component owns both
|
|
67
|
+
* interactive cases rather than leaving one to a wrapper at the call site.
|
|
68
|
+
* That is not a convenience: a wrapping `<button>` around a chip that already
|
|
69
|
+
* holds the remove `<button>` is a button inside a button, which no parser
|
|
70
|
+
* keeps and no accessibility tree reports the way it was written. Given both,
|
|
71
|
+
* the chip renders the label and the X as SIBLING buttons — the label takes
|
|
72
|
+
* the leading padding with it, so it is the whole of the chip up to the X
|
|
73
|
+
* rather than the words with dead padding around them.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* <Tag>TypeScript</Tag>
|
|
77
|
+
* @example
|
|
78
|
+
* <Tag active={on} onClick={toggle}>Rust</Tag>
|
|
79
|
+
* @example
|
|
80
|
+
* <Tag onRemove={() => drop('rust')} removeLabel="Remove Rust filter">Rust</Tag>
|
|
81
|
+
* @example
|
|
82
|
+
* // Both: a filter the reader can toggle and also take out of the row.
|
|
83
|
+
* <Tag active={on} onClick={toggle} onRemove={drop} removeLabel="Remove Rust filter">Rust</Tag>
|
|
84
|
+
*/
|
|
85
|
+
declare function Tag({ children, active, onClick, onRemove, removeLabel, className, ...rest }: TagProps): react.JSX.Element;
|
|
86
|
+
|
|
87
|
+
export { Tag, type TagProps, Tag as default };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { RiCloseLine } from "@remixicon/react";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
function Tag({ children, active, onClick, onRemove, removeLabel, className, ...rest }) {
|
|
5
|
+
const split = Boolean(onClick && onRemove);
|
|
6
|
+
const chip = cn(
|
|
7
|
+
"inline-flex items-center rounded-(--radius-sm) font-mono text-xs tracking-wide transition-colors duration-(--duration-fast)",
|
|
8
|
+
active ? "bg-(--accent) text-(--accent-foreground)" : "bg-(--stone) text-(--ink-3-aa)",
|
|
9
|
+
onRemove ? "gap-1 pe-1.5" : "pe-2.5",
|
|
10
|
+
// Handed to the label button in the split form, so the padding is part of
|
|
11
|
+
// the target rather than a ring of dead space around it.
|
|
12
|
+
!split && "py-1 ps-2.5",
|
|
13
|
+
className
|
|
14
|
+
);
|
|
15
|
+
const remove = onRemove ? /* @__PURE__ */ jsx(
|
|
16
|
+
"button",
|
|
17
|
+
{
|
|
18
|
+
type: "button",
|
|
19
|
+
onClick: onRemove,
|
|
20
|
+
"aria-label": removeLabel,
|
|
21
|
+
className: cn(
|
|
22
|
+
// The drawn box is 16px, which is under the 24px minimum a pointer
|
|
23
|
+
// target has to clear (WCAG 2.5.8). The inset pseudo-element takes
|
|
24
|
+
// the hit area out to 24 without changing what is drawn or pushing
|
|
25
|
+
// the chips apart — the 44px floor is for a standalone control, and
|
|
26
|
+
// a chip is 24 tall to begin with.
|
|
27
|
+
"relative inline-flex size-4 shrink-0 items-center justify-center rounded-(--radius-xs)",
|
|
28
|
+
"before:absolute before:inset-[-4px] before:content-['']",
|
|
29
|
+
"opacity-60 transition-opacity duration-(--duration-fast) hover:opacity-100 focus-visible:opacity-100"
|
|
30
|
+
),
|
|
31
|
+
children: /* @__PURE__ */ jsx(RiCloseLine, { size: 12, "aria-hidden": true })
|
|
32
|
+
}
|
|
33
|
+
) : null;
|
|
34
|
+
if (split) {
|
|
35
|
+
return /* @__PURE__ */ jsxs("span", { className: chip, ...rest, children: [
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"button",
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
onClick,
|
|
41
|
+
"aria-pressed": active,
|
|
42
|
+
className: "rounded-(--radius-sm) py-1 ps-2.5 font-mono text-xs tracking-wide",
|
|
43
|
+
children
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
remove
|
|
47
|
+
] });
|
|
48
|
+
}
|
|
49
|
+
if (onClick) {
|
|
50
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick, "aria-pressed": active, className: chip, ...rest, children });
|
|
51
|
+
}
|
|
52
|
+
return /* @__PURE__ */ jsxs("span", { className: chip, ...rest, children: [
|
|
53
|
+
children,
|
|
54
|
+
remove
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
var Tag_default = Tag;
|
|
58
|
+
export {
|
|
59
|
+
Tag,
|
|
60
|
+
Tag_default as default
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=Tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Tag/Tag.tsx"],"sourcesContent":["import { RiCloseLine } from '@remixicon/react'\nimport type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\ninterface TagBase extends Omit<HTMLAttributes<HTMLElement>, 'onClick'> {\n children: ReactNode\n /**\n * Renders the pressed/selected look, and declares the chip a toggle.\n *\n * An interactive chip reads `aria-pressed` off this same value, so the accent\n * fill and the state a screen reader hears cannot drift apart. Leave it off\n * for a chip whose `onClick` navigates or opens something: a control that is\n * neither pressed nor unpressed is better announced as neither than as\n * \"not pressed\".\n */\n active?: boolean\n /**\n * Makes the chip ITSELF the filter control.\n *\n * This prop exists because the alternative did not survive contact with\n * `onRemove`. The advice used to be to wrap the tag in a button at the call\n * site, which is fine on its own and invalid the moment the chip is also\n * removable: the remove control is a real `<button>`, so the wrapper puts a\n * button inside a button — markup the parser splits into siblings, leaving a\n * DOM neither the author nor the accessibility tree expects.\n *\n * With this the wrapper is never written. The chip carries the click, the\n * focus ring and the pressed state on the element that draws them, and a\n * removable filter chip renders its two controls side by side instead of one\n * inside the other.\n */\n onClick?: () => void\n}\n\n/**\n * The removable form: a chip for one thing the reader has already chosen.\n *\n * `removeLabel` is required alongside `onRemove` and not optional with a\n * default, because \"Remove\" repeated down a row of filters is eight controls a\n * screen reader cannot tell apart. Write the subject into it — \"Remove\n * TypeScript filter\".\n */\ninterface TagRemovable {\n /** Called when the reader dismisses the chip. */\n onRemove: () => void\n /** The remove button's accessible name. Name the subject, not the action. */\n removeLabel: string\n}\n\ninterface TagStatic {\n onRemove?: never\n removeLabel?: never\n}\n\nexport type TagProps = TagBase & (TagRemovable | TagStatic)\n\n/**\n * A subject label — a topic, a technology, a filter facet — that can filter\n * with `onClick` and be dismissed with `onRemove`.\n *\n * Distinct from `Badge`, which carries a state or a count. A tag names what\n * something is ABOUT, so several sit together in a row and the reader scans\n * them; a badge is one fact about one record.\n *\n * This is where a `Token` component would have gone. It was not built: a token\n * is a tag with a remove button, and the difference between the two is one\n * prop, not one component. The system already ships three things that look\n * alike — `Badge`, `Tag`, `StatusPill` — and a fourth whose whole distinction\n * is an X on the end would be the one a call site picks by coin toss.\n *\n * Presentational until it is given a handler, and the component owns both\n * interactive cases rather than leaving one to a wrapper at the call site.\n * That is not a convenience: a wrapping `<button>` around a chip that already\n * holds the remove `<button>` is a button inside a button, which no parser\n * keeps and no accessibility tree reports the way it was written. Given both,\n * the chip renders the label and the X as SIBLING buttons — the label takes\n * the leading padding with it, so it is the whole of the chip up to the X\n * rather than the words with dead padding around them.\n *\n * @example\n * <Tag>TypeScript</Tag>\n * @example\n * <Tag active={on} onClick={toggle}>Rust</Tag>\n * @example\n * <Tag onRemove={() => drop('rust')} removeLabel=\"Remove Rust filter\">Rust</Tag>\n * @example\n * // Both: a filter the reader can toggle and also take out of the row.\n * <Tag active={on} onClick={toggle} onRemove={drop} removeLabel=\"Remove Rust filter\">Rust</Tag>\n */\nexport function Tag({ children, active, onClick, onRemove, removeLabel, className, ...rest }: TagProps) {\n // Two controls cannot nest, so a chip that is both a filter and a selection\n // splits its label out into a button of its own beside the remove button.\n const split = Boolean(onClick && onRemove)\n\n const chip = cn(\n 'inline-flex items-center rounded-(--radius-sm) font-mono text-xs tracking-wide transition-colors duration-(--duration-fast)',\n active ? 'bg-(--accent) text-(--accent-foreground)' : 'bg-(--stone) text-(--ink-3-aa)',\n onRemove ? 'gap-1 pe-1.5' : 'pe-2.5',\n // Handed to the label button in the split form, so the padding is part of\n // the target rather than a ring of dead space around it.\n !split && 'py-1 ps-2.5',\n className,\n )\n\n const remove = onRemove ? (\n <button\n type=\"button\"\n onClick={onRemove}\n aria-label={removeLabel}\n className={cn(\n // The drawn box is 16px, which is under the 24px minimum a pointer\n // target has to clear (WCAG 2.5.8). The inset pseudo-element takes\n // the hit area out to 24 without changing what is drawn or pushing\n // the chips apart — the 44px floor is for a standalone control, and\n // a chip is 24 tall to begin with.\n 'relative inline-flex size-4 shrink-0 items-center justify-center rounded-(--radius-xs)',\n \"before:absolute before:inset-[-4px] before:content-['']\",\n 'opacity-60 transition-opacity duration-(--duration-fast) hover:opacity-100 focus-visible:opacity-100',\n )}\n >\n <RiCloseLine size={12} aria-hidden />\n </button>\n ) : null\n\n if (split) {\n return (\n <span className={chip} {...rest}>\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n className=\"rounded-(--radius-sm) py-1 ps-2.5 font-mono text-xs tracking-wide\"\n >\n {children}\n </button>\n {remove}\n </span>\n )\n }\n\n if (onClick) {\n return (\n <button type=\"button\" onClick={onClick} aria-pressed={active} className={chip} {...rest}>\n {children}\n </button>\n )\n }\n\n return (\n <span className={chip} {...rest}>\n {children}\n {remove}\n </span>\n )\n}\n\nexport default Tag\n"],"mappings":"AAwHM,cAMA,YANA;AAxHN,SAAS,mBAAmB;AAE5B,SAAS,UAAU;AAuFZ,SAAS,IAAI,EAAE,UAAU,QAAQ,SAAS,UAAU,aAAa,WAAW,GAAG,KAAK,GAAa;AAGtG,QAAM,QAAQ,QAAQ,WAAW,QAAQ;AAEzC,QAAM,OAAO;AAAA,IACX;AAAA,IACA,SAAS,6CAA6C;AAAA,IACtD,WAAW,iBAAiB;AAAA;AAAA;AAAA,IAG5B,CAAC,SAAS;AAAA,IACV;AAAA,EACF;AAEA,QAAM,SAAS,WACb;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,cAAY;AAAA,MACZ,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,8BAAC,eAAY,MAAM,IAAI,eAAW,MAAC;AAAA;AAAA,EACrC,IACE;AAEJ,MAAI,OAAO;AACT,WACE,qBAAC,UAAK,WAAW,MAAO,GAAG,MACzB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL;AAAA,UACA,gBAAc;AAAA,UACd,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACC;AAAA,OACH;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE,oBAAC,YAAO,MAAK,UAAS,SAAkB,gBAAc,QAAQ,WAAW,MAAO,GAAG,MAChF,UACH;AAAA,EAEJ;AAEA,SACE,qBAAC,UAAK,WAAW,MAAO,GAAG,MACxB;AAAA;AAAA,IACA;AAAA,KACH;AAEJ;AAEA,IAAO,cAAQ;","names":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A rung of the type scale, named for what it is FOR rather than for a pixel
|
|
6
|
+
* value. `base` is body copy; `lead` is the standfirst that carries a piece and
|
|
7
|
+
* is the only step here that touches the heading ladder (`--fs-item`, its
|
|
8
|
+
* bottom rung). Nothing above that: a paragraph larger than a record title is a
|
|
9
|
+
* heading that forgot to be one.
|
|
10
|
+
*/
|
|
11
|
+
type TextSize = 'xs' | 'sm' | 'base' | 'lead';
|
|
12
|
+
/**
|
|
13
|
+
* A rung of the ink ladder. Three, because the ladder has three.
|
|
14
|
+
*
|
|
15
|
+
* `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper
|
|
16
|
+
* and are not the same token: `--ink-3` is a translucent tint that inherits
|
|
17
|
+
* whatever is under it, so it clears AA on the page ground and quietly fails on
|
|
18
|
+
* a card, a plate, or a code block.
|
|
19
|
+
*/
|
|
20
|
+
type TextTone = 'body' | 'strong' | 'muted';
|
|
21
|
+
type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption';
|
|
22
|
+
interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
/** Which rung of the type scale. See {@link TextSize}. */
|
|
25
|
+
size?: TextSize;
|
|
26
|
+
/** Which rung of the ink ladder. See {@link TextTone}. */
|
|
27
|
+
tone?: TextTone;
|
|
28
|
+
/**
|
|
29
|
+
* The element, and ONLY the element.
|
|
30
|
+
*
|
|
31
|
+
* Changing it changes what the markup means — a `span` inside a sentence, an
|
|
32
|
+
* `li` inside a list someone else opened — and changes nothing about the
|
|
33
|
+
* look. That separation is the whole point: the alternative is a `<p>` nested
|
|
34
|
+
* inside a `<p>`, which the HTML parser silently splits into two, or a
|
|
35
|
+
* paragraph faked out of a `<div>` because the real element brought a size
|
|
36
|
+
* with it.
|
|
37
|
+
*/
|
|
38
|
+
as?: TextElement;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A paragraph, or a run of text that wants the system's voice.
|
|
42
|
+
*
|
|
43
|
+
* The step between `Article` and raw JSX. `Article` styles a whole reading
|
|
44
|
+
* column from element selectors and is the right answer for a post; this is for
|
|
45
|
+
* the single paragraph that is NOT in a column — a card's description, a
|
|
46
|
+
* dialog's explanation, the line under an empty state.
|
|
47
|
+
*
|
|
48
|
+
* The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs
|
|
49
|
+
* are all full-strength ink has spent the top of the ladder on its body copy
|
|
50
|
+
* and has nothing left for the headings, which is the single most common way a
|
|
51
|
+
* monochrome page loses its hierarchy.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* <Text>Twelve releases this quarter, none rolled back.</Text>
|
|
55
|
+
* @example
|
|
56
|
+
* <Text size="lead" tone="strong">A monochrome system for software and writing.</Text>
|
|
57
|
+
* @example
|
|
58
|
+
* <Text as="span" size="sm" tone="muted">Updated just now</Text>
|
|
59
|
+
*/
|
|
60
|
+
declare function Text({ children, size, tone, as, className, ...rest }: TextProps): react.JSX.Element;
|
|
61
|
+
|
|
62
|
+
export { Text, type TextElement, type TextProps, type TextSize, type TextTone, Text as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
const SIZE = {
|
|
4
|
+
xs: "text-xs leading-[1.6]",
|
|
5
|
+
sm: "text-sm leading-[1.65]",
|
|
6
|
+
base: "text-base font-light leading-[1.75]",
|
|
7
|
+
lead: "text-[length:var(--fs-item)] font-light leading-[1.6]"
|
|
8
|
+
};
|
|
9
|
+
const TONE = {
|
|
10
|
+
body: "text-(--ink-2)",
|
|
11
|
+
strong: "text-(--ink)",
|
|
12
|
+
muted: "text-(--ink-3-aa)"
|
|
13
|
+
};
|
|
14
|
+
function Text({
|
|
15
|
+
children,
|
|
16
|
+
size = "base",
|
|
17
|
+
tone = "body",
|
|
18
|
+
as = "p",
|
|
19
|
+
className,
|
|
20
|
+
...rest
|
|
21
|
+
}) {
|
|
22
|
+
const Comp = as;
|
|
23
|
+
return /* @__PURE__ */ jsx(Comp, { className: cn("m-0", SIZE[size], TONE[tone], className), ...rest, children });
|
|
24
|
+
}
|
|
25
|
+
var Text_default = Text;
|
|
26
|
+
export {
|
|
27
|
+
Text,
|
|
28
|
+
Text_default as default
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=Text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Text/Text.tsx"],"sourcesContent":["import type { ElementType, HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * A rung of the type scale, named for what it is FOR rather than for a pixel\n * value. `base` is body copy; `lead` is the standfirst that carries a piece and\n * is the only step here that touches the heading ladder (`--fs-item`, its\n * bottom rung). Nothing above that: a paragraph larger than a record title is a\n * heading that forgot to be one.\n */\nexport type TextSize = 'xs' | 'sm' | 'base' | 'lead'\n\n/**\n * A rung of the ink ladder. Three, because the ladder has three.\n *\n * `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper\n * and are not the same token: `--ink-3` is a translucent tint that inherits\n * whatever is under it, so it clears AA on the page ground and quietly fails on\n * a card, a plate, or a code block.\n */\nexport type TextTone = 'body' | 'strong' | 'muted'\n\nexport type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption'\n\n/**\n * Weight travels with the size, deliberately.\n *\n * The system sets long-form copy at 300 — it is what gives a page of prose its\n * air. At 12 and 14px that same weight is a hairline: the strokes thin out\n * below the point where a light face is a choice and turn into a legibility\n * bug. So the two small steps step back up to 400, and a caller never has to\n * know that the trade exists.\n */\nconst SIZE: Record<TextSize, string> = {\n xs: 'text-xs leading-[1.6]',\n sm: 'text-sm leading-[1.65]',\n base: 'text-base font-light leading-[1.75]',\n lead: 'text-[length:var(--fs-item)] font-light leading-[1.6]',\n}\n\nconst TONE: Record<TextTone, string> = {\n body: 'text-(--ink-2)',\n strong: 'text-(--ink)',\n muted: 'text-(--ink-3-aa)',\n}\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n children?: ReactNode\n /** Which rung of the type scale. See {@link TextSize}. */\n size?: TextSize\n /** Which rung of the ink ladder. See {@link TextTone}. */\n tone?: TextTone\n /**\n * The element, and ONLY the element.\n *\n * Changing it changes what the markup means — a `span` inside a sentence, an\n * `li` inside a list someone else opened — and changes nothing about the\n * look. That separation is the whole point: the alternative is a `<p>` nested\n * inside a `<p>`, which the HTML parser silently splits into two, or a\n * paragraph faked out of a `<div>` because the real element brought a size\n * with it.\n */\n as?: TextElement\n}\n\n/**\n * A paragraph, or a run of text that wants the system's voice.\n *\n * The step between `Article` and raw JSX. `Article` styles a whole reading\n * column from element selectors and is the right answer for a post; this is for\n * the single paragraph that is NOT in a column — a card's description, a\n * dialog's explanation, the line under an empty state.\n *\n * The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs\n * are all full-strength ink has spent the top of the ladder on its body copy\n * and has nothing left for the headings, which is the single most common way a\n * monochrome page loses its hierarchy.\n *\n * @example\n * <Text>Twelve releases this quarter, none rolled back.</Text>\n * @example\n * <Text size=\"lead\" tone=\"strong\">A monochrome system for software and writing.</Text>\n * @example\n * <Text as=\"span\" size=\"sm\" tone=\"muted\">Updated just now</Text>\n */\nexport function Text({\n children,\n size = 'base',\n tone = 'body',\n as = 'p',\n className,\n ...rest\n}: TextProps) {\n const Comp = as as ElementType\n\n return (\n <Comp className={cn('m-0', SIZE[size], TONE[tone], className)} {...rest}>\n {children}\n </Comp>\n )\n}\n\nexport default Text\n"],"mappings":"AAgGI;AA/FJ,SAAS,UAAU;AAgCnB,MAAM,OAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,OAAiC;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAyCO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AAAA,EACL;AAAA,EACA,GAAG;AACL,GAAc;AACZ,QAAM,OAAO;AAEb,SACE,oBAAC,QAAK,WAAW,GAAG,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,GAAI,GAAG,MAChE,UACH;AAEJ;AAEA,IAAO,eAAQ;","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { TextareaHTMLAttributes, Ref } from 'react';
|
|
3
|
+
|
|
4
|
+
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
|
+
/** Paints the resting border with `--danger` and reflects `aria-invalid`. */
|
|
6
|
+
invalid?: boolean;
|
|
7
|
+
ref?: Ref<HTMLTextAreaElement>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Multi-line text entry.
|
|
11
|
+
*
|
|
12
|
+
* Resizes vertically only: horizontal resize lets a reader drag the control
|
|
13
|
+
* past the measure and past the page's own gutter.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <Field label="Notes" htmlFor="notes"><Textarea id="notes" rows={4} /></Field>
|
|
17
|
+
*/
|
|
18
|
+
declare function Textarea({ invalid, className, ref, 'aria-invalid': ariaInvalid, ...rest }: TextareaProps): react.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { Textarea, type TextareaProps, Textarea as default };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { CONTROL_BASE, CONTROL_BORDER, isInvalid } from "../../lib/control.js";
|
|
4
|
+
function Textarea({
|
|
5
|
+
invalid,
|
|
6
|
+
className,
|
|
7
|
+
ref,
|
|
8
|
+
"aria-invalid": ariaInvalid,
|
|
9
|
+
...rest
|
|
10
|
+
}) {
|
|
11
|
+
const bad = isInvalid(invalid, ariaInvalid);
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"textarea",
|
|
14
|
+
{
|
|
15
|
+
ref,
|
|
16
|
+
"aria-invalid": ariaInvalid ?? (invalid ? true : void 0),
|
|
17
|
+
className: cn(
|
|
18
|
+
CONTROL_BASE,
|
|
19
|
+
"min-h-24 resize-y",
|
|
20
|
+
bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,
|
|
21
|
+
className
|
|
22
|
+
),
|
|
23
|
+
...rest
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
var Textarea_default = Textarea;
|
|
28
|
+
export {
|
|
29
|
+
Textarea,
|
|
30
|
+
Textarea_default as default
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=Textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import type { Ref, TextareaHTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\nimport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from '../../lib/control'\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Paints the resting border with `--danger` and reflects `aria-invalid`. */\n invalid?: boolean\n ref?: Ref<HTMLTextAreaElement>\n}\n\n/**\n * Multi-line text entry.\n *\n * Resizes vertically only: horizontal resize lets a reader drag the control\n * past the measure and past the page's own gutter.\n *\n * @example\n * <Field label=\"Notes\" htmlFor=\"notes\"><Textarea id=\"notes\" rows={4} /></Field>\n */\nexport function Textarea({\n invalid,\n className,\n ref,\n 'aria-invalid': ariaInvalid,\n ...rest\n}: TextareaProps) {\n const bad = isInvalid(invalid, ariaInvalid)\n return (\n <textarea\n ref={ref}\n aria-invalid={ariaInvalid ?? (invalid ? true : undefined)}\n className={cn(\n CONTROL_BASE,\n 'min-h-24 resize-y',\n bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport default Textarea\n"],"mappings":"AA4BI;AA3BJ,SAAS,UAAU;AACnB,SAAS,cAAc,gBAAgB,iBAAiB;AAiBjD,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,GAAG;AACL,GAAkB;AAChB,QAAM,MAAM,UAAU,SAAS,WAAW;AAC1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,gBAAc,gBAAgB,UAAU,OAAO;AAAA,MAC/C,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA,MAAM,eAAe,UAAU,eAAe;AAAA,QAC9C;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,mBAAQ;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { TimeHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How the instant reads.
|
|
6
|
+
*
|
|
7
|
+
* `auto` is relative while the gap is small enough to be useful and absolute
|
|
8
|
+
* once it is not — "3 hours ago" answers the question a reader is actually
|
|
9
|
+
* asking about a recent record, and "2 years ago" does not.
|
|
10
|
+
*/
|
|
11
|
+
type TimestampFormat = 'auto' | 'relative' | 'absolute';
|
|
12
|
+
interface TimestampProps extends Omit<TimeHTMLAttributes<HTMLTimeElement>, 'dateTime' | 'children'> {
|
|
13
|
+
/** The instant. A `Date`, an ISO string, or epoch milliseconds. */
|
|
14
|
+
value: Date | string | number;
|
|
15
|
+
/** How the instant reads. See {@link TimestampFormat}. */
|
|
16
|
+
format?: TimestampFormat;
|
|
17
|
+
/**
|
|
18
|
+
* How far from now `auto` still prints a relative time, in milliseconds.
|
|
19
|
+
* Seven days by default — past a week the calendar date is the more useful
|
|
20
|
+
* fact, and it is also the one that stops changing.
|
|
21
|
+
*/
|
|
22
|
+
relativeWithin?: number;
|
|
23
|
+
/** Adds the clock time to the absolute form. */
|
|
24
|
+
showTime?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A date or a time, rendered the one way the system renders them.
|
|
28
|
+
*
|
|
29
|
+
* Every list of records needs this, and `new Date().toLocaleString()` at the
|
|
30
|
+
* call site is precisely how a product ends up with four date formats on one
|
|
31
|
+
* screen.
|
|
32
|
+
*
|
|
33
|
+
* **On hydration.** Both halves of a formatted date are environment-dependent:
|
|
34
|
+
* a relative time depends on when it is read, and even an absolute one depends
|
|
35
|
+
* on the reader's locale and time zone, none of which a static build knows. So
|
|
36
|
+
* the first paint — the one the server produces and the one the client must
|
|
37
|
+
* reproduce exactly — is the ISO calendar date in UTC, sliced straight out of
|
|
38
|
+
* the ISO string with no `Intl` anywhere near it. Both sides compute it from
|
|
39
|
+
* the same characters, so they cannot disagree. The locale-aware and relative
|
|
40
|
+
* forms are applied after mount, in an effect, where there is a reader to be
|
|
41
|
+
* local to. This package statically exports every page, so the alternative is a
|
|
42
|
+
* hydration mismatch on any page with a date on it.
|
|
43
|
+
*
|
|
44
|
+
* The `datetime` attribute is the full ISO instant from the first render
|
|
45
|
+
* onwards and never changes, so a screen reader, a crawler, or anything else
|
|
46
|
+
* parsing the markup gets the exact moment whether or not the effect has run.
|
|
47
|
+
*
|
|
48
|
+
* It formats once per mount. A hundred rows each holding a ticking interval to
|
|
49
|
+
* keep "3 minutes ago" honest is a cost nobody asked for; a list that must tick
|
|
50
|
+
* should re-key or re-render from above.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* <Timestamp value={deploy.finishedAt} />
|
|
54
|
+
* @example
|
|
55
|
+
* <Timestamp value="2026-01-14T09:30:00Z" format="absolute" showTime />
|
|
56
|
+
*/
|
|
57
|
+
declare function Timestamp({ value, format, relativeWithin, showTime, className, ...rest }: TimestampProps): react.JSX.Element;
|
|
58
|
+
|
|
59
|
+
export { Timestamp, type TimestampFormat, type TimestampProps, Timestamp as default };
|