@cronus-ui/ui 0.6.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/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/charts/animation.d.ts +11 -0
- package/dist/charts/animation.js +29 -0
- package/dist/charts/area-chart-loading.d.ts +34 -0
- package/dist/charts/area-chart-loading.js +22 -0
- package/dist/charts/area-chart.d.ts +48 -0
- package/dist/charts/area-chart.js +57 -0
- package/dist/charts/area-gradient-defs.d.ts +20 -0
- package/dist/charts/area-gradient-defs.js +15 -0
- package/dist/charts/area.d.ts +76 -0
- package/dist/charts/area.js +104 -0
- package/dist/charts/background.d.ts +27 -0
- package/dist/charts/background.js +68 -0
- package/dist/charts/bar-chart-loading.d.ts +17 -0
- package/dist/charts/bar-chart-loading.js +14 -0
- package/dist/charts/bar-chart.d.ts +55 -0
- package/dist/charts/bar-chart.js +432 -0
- package/dist/charts/bar-depth-geometry.d.ts +33 -0
- package/dist/charts/bar-depth-geometry.js +38 -0
- package/dist/charts/bar-depth.d.ts +157 -0
- package/dist/charts/bar-depth.js +586 -0
- package/dist/charts/bar-squares-layout.d.ts +28 -0
- package/dist/charts/bar-squares-layout.js +47 -0
- package/dist/charts/bar-squares.d.ts +49 -0
- package/dist/charts/bar-squares.js +207 -0
- package/dist/charts/bar-x-axis.d.ts +14 -0
- package/dist/charts/bar-x-axis.js +73 -0
- package/dist/charts/bar-y-axis.d.ts +12 -0
- package/dist/charts/bar-y-axis.js +64 -0
- package/dist/charts/bar.d.ts +41 -0
- package/dist/charts/bar.js +208 -0
- package/dist/charts/candlestick-chart.d.ts +46 -0
- package/dist/charts/candlestick-chart.js +203 -0
- package/dist/charts/candlestick.d.ts +24 -0
- package/dist/charts/candlestick.js +139 -0
- package/dist/charts/chart-brush-handle.d.ts +15 -0
- package/dist/charts/chart-brush-handle.js +47 -0
- package/dist/charts/chart-brush-layout.d.ts +27 -0
- package/dist/charts/chart-brush-layout.js +42 -0
- package/dist/charts/chart-brush-selection-overlay.d.ts +19 -0
- package/dist/charts/chart-brush-selection-overlay.js +44 -0
- package/dist/charts/chart-brush-track-overlay.d.ts +23 -0
- package/dist/charts/chart-brush-track-overlay.js +65 -0
- package/dist/charts/chart-brush.d.ts +32 -0
- package/dist/charts/chart-brush.js +116 -0
- package/dist/charts/chart-center-typography.d.ts +12 -0
- package/dist/charts/chart-center-typography.js +12 -0
- package/dist/charts/chart-child-passthrough.d.ts +17 -0
- package/dist/charts/chart-child-passthrough.js +74 -0
- package/dist/charts/chart-config-context.d.ts +26 -0
- package/dist/charts/chart-config-context.js +47 -0
- package/dist/charts/chart-context.d.ts +199 -0
- package/dist/charts/chart-context.js +201 -0
- package/dist/charts/chart-defs.d.ts +13 -0
- package/dist/charts/chart-defs.js +49 -0
- package/dist/charts/chart-formatters.d.ts +10 -0
- package/dist/charts/chart-formatters.js +28 -0
- package/dist/charts/chart-legend-hover.d.ts +13 -0
- package/dist/charts/chart-legend-hover.js +18 -0
- package/dist/charts/chart-legend.d.ts +55 -0
- package/dist/charts/chart-legend.js +30 -0
- package/dist/charts/chart-loading-label.d.ts +10 -0
- package/dist/charts/chart-loading-label.js +21 -0
- package/dist/charts/chart-phase.d.ts +31 -0
- package/dist/charts/chart-phase.js +21 -0
- package/dist/charts/chart-reveal-clip.d.ts +24 -0
- package/dist/charts/chart-reveal-clip.js +24 -0
- package/dist/charts/chart-scale.d.ts +12 -0
- package/dist/charts/chart-scale.js +17 -0
- package/dist/charts/chart-stat-flow.d.ts +36 -0
- package/dist/charts/chart-stat-flow.js +23 -0
- package/dist/charts/choropleth/choropleth-chart.d.ts +43 -0
- package/dist/charts/choropleth/choropleth-chart.js +218 -0
- package/dist/charts/choropleth/choropleth-context.d.ts +86 -0
- package/dist/charts/choropleth/choropleth-context.js +106 -0
- package/dist/charts/choropleth/choropleth-feature.d.ts +13 -0
- package/dist/charts/choropleth/choropleth-feature.js +125 -0
- package/dist/charts/choropleth/choropleth-graticule.d.ts +11 -0
- package/dist/charts/choropleth/choropleth-graticule.js +12 -0
- package/dist/charts/choropleth/choropleth-tooltip.d.ts +31 -0
- package/dist/charts/choropleth/choropleth-tooltip.js +50 -0
- package/dist/charts/choropleth/index.d.ts +7 -0
- package/dist/charts/choropleth/index.js +6 -0
- package/dist/charts/composed-chart.d.ts +36 -0
- package/dist/charts/composed-chart.js +152 -0
- package/dist/charts/dash-tail-stroke.d.ts +18 -0
- package/dist/charts/dash-tail-stroke.js +13 -0
- package/dist/charts/decimate-time-series.d.ts +10 -0
- package/dist/charts/decimate-time-series.js +112 -0
- package/dist/charts/fade-edges.d.ts +34 -0
- package/dist/charts/fade-edges.js +35 -0
- package/dist/charts/filter-data-by-x-domain.d.ts +5 -0
- package/dist/charts/filter-data-by-x-domain.js +42 -0
- package/dist/charts/funnel-chart.d.ts +91 -0
- package/dist/charts/funnel-chart.js +302 -0
- package/dist/charts/gauge-label-layout.d.ts +22 -0
- package/dist/charts/gauge-label-layout.js +44 -0
- package/dist/charts/gauge.d.ts +56 -0
- package/dist/charts/gauge.js +307 -0
- package/dist/charts/generate-chart-skeleton-data.d.ts +16 -0
- package/dist/charts/generate-chart-skeleton-data.js +25 -0
- package/dist/charts/grid.d.ts +58 -0
- package/dist/charts/grid.js +80 -0
- package/dist/charts/heatmap/generate-heatmap-skeleton-data.d.ts +4 -0
- package/dist/charts/heatmap/generate-heatmap-skeleton-data.js +12 -0
- package/dist/charts/heatmap/heatmap-animation.d.ts +41 -0
- package/dist/charts/heatmap/heatmap-animation.js +85 -0
- package/dist/charts/heatmap/heatmap-cells.d.ts +21 -0
- package/dist/charts/heatmap/heatmap-cells.js +265 -0
- package/dist/charts/heatmap/heatmap-chart-loading.d.ts +21 -0
- package/dist/charts/heatmap/heatmap-chart-loading.js +14 -0
- package/dist/charts/heatmap/heatmap-chart.d.ts +80 -0
- package/dist/charts/heatmap/heatmap-chart.js +275 -0
- package/dist/charts/heatmap/heatmap-colors.d.ts +70 -0
- package/dist/charts/heatmap/heatmap-colors.js +113 -0
- package/dist/charts/heatmap/heatmap-context.d.ts +109 -0
- package/dist/charts/heatmap/heatmap-context.js +69 -0
- package/dist/charts/heatmap/heatmap-legend-gradient.d.ts +20 -0
- package/dist/charts/heatmap/heatmap-legend-gradient.js +44 -0
- package/dist/charts/heatmap/heatmap-legend-swatch.d.ts +8 -0
- package/dist/charts/heatmap/heatmap-legend-swatch.js +26 -0
- package/dist/charts/heatmap/heatmap-legend.d.ts +41 -0
- package/dist/charts/heatmap/heatmap-legend.js +68 -0
- package/dist/charts/heatmap/heatmap-pattern-defs.d.ts +5 -0
- package/dist/charts/heatmap/heatmap-pattern-defs.js +25 -0
- package/dist/charts/heatmap/heatmap-resolve-separator.d.ts +8 -0
- package/dist/charts/heatmap/heatmap-resolve-separator.js +82 -0
- package/dist/charts/heatmap/heatmap-separator.d.ts +63 -0
- package/dist/charts/heatmap/heatmap-separator.js +71 -0
- package/dist/charts/heatmap/heatmap-tooltip.d.ts +30 -0
- package/dist/charts/heatmap/heatmap-tooltip.js +20 -0
- package/dist/charts/heatmap/heatmap-utils.d.ts +175 -0
- package/dist/charts/heatmap/heatmap-utils.js +595 -0
- package/dist/charts/heatmap/heatmap-x-axis.d.ts +7 -0
- package/dist/charts/heatmap/heatmap-x-axis.js +54 -0
- package/dist/charts/heatmap/heatmap-y-axis.d.ts +14 -0
- package/dist/charts/heatmap/heatmap-y-axis.js +37 -0
- package/dist/charts/heatmap/index.d.ts +15 -0
- package/dist/charts/heatmap/index.js +15 -0
- package/dist/charts/heatmap/use-delayed-tooltip-data.d.ts +3 -0
- package/dist/charts/heatmap/use-delayed-tooltip-data.js +53 -0
- package/dist/charts/highlight-segment-bounds.d.ts +18 -0
- package/dist/charts/highlight-segment-bounds.js +36 -0
- package/dist/charts/highlight-segment.d.ts +22 -0
- package/dist/charts/highlight-segment.js +14 -0
- package/dist/charts/index.d.ts +106 -0
- package/dist/charts/index.js +133 -0
- package/dist/charts/indicator-fade.d.ts +15 -0
- package/dist/charts/indicator-fade.js +42 -0
- package/dist/charts/legend/index.d.ts +8 -0
- package/dist/charts/legend/index.js +10 -0
- package/dist/charts/legend/legend-context.d.ts +48 -0
- package/dist/charts/legend/legend-context.js +34 -0
- package/dist/charts/legend/legend-item.d.ts +12 -0
- package/dist/charts/legend/legend-item.js +11 -0
- package/dist/charts/legend/legend-label.d.ts +9 -0
- package/dist/charts/legend/legend-label.js +10 -0
- package/dist/charts/legend/legend-marker.d.ts +9 -0
- package/dist/charts/legend/legend-marker.js +11 -0
- package/dist/charts/legend/legend-progress.d.ts +13 -0
- package/dist/charts/legend/legend-progress.js +15 -0
- package/dist/charts/legend/legend-value.d.ts +17 -0
- package/dist/charts/legend/legend-value.js +11 -0
- package/dist/charts/legend/legend.d.ts +23 -0
- package/dist/charts/legend/legend.js +43 -0
- package/dist/charts/line-chart-loading.d.ts +34 -0
- package/dist/charts/line-chart-loading.js +22 -0
- package/dist/charts/line-chart.d.ts +46 -0
- package/dist/charts/line-chart.js +91 -0
- package/dist/charts/line-loading-pulse.d.ts +20 -0
- package/dist/charts/line-loading-pulse.js +124 -0
- package/dist/charts/line-loading-timing.d.ts +10 -0
- package/dist/charts/line-loading-timing.js +10 -0
- package/dist/charts/line-series-terminal-marker.d.ts +16 -0
- package/dist/charts/line-series-terminal-marker.js +46 -0
- package/dist/charts/line.d.ts +64 -0
- package/dist/charts/line.js +96 -0
- package/dist/charts/live-line-chart.d.ts +35 -0
- package/dist/charts/live-line-chart.js +374 -0
- package/dist/charts/live-line.d.ts +39 -0
- package/dist/charts/live-line.js +78 -0
- package/dist/charts/live-x-axis.d.ts +12 -0
- package/dist/charts/live-x-axis.js +85 -0
- package/dist/charts/live-y-axis.d.ts +16 -0
- package/dist/charts/live-y-axis.js +137 -0
- package/dist/charts/loading-sweep.d.ts +66 -0
- package/dist/charts/loading-sweep.js +174 -0
- package/dist/charts/markers/chart-markers.d.ts +25 -0
- package/dist/charts/markers/chart-markers.js +87 -0
- package/dist/charts/markers/index.d.ts +3 -0
- package/dist/charts/markers/index.js +3 -0
- package/dist/charts/markers/marker-group.d.ts +88 -0
- package/dist/charts/markers/marker-group.js +171 -0
- package/dist/charts/motion-utils.d.ts +9 -0
- package/dist/charts/motion-utils.js +28 -0
- package/dist/charts/notch-gauge-shared.d.ts +49 -0
- package/dist/charts/notch-gauge-shared.js +103 -0
- package/dist/charts/path-stroke-utils.d.ts +20 -0
- package/dist/charts/path-stroke-utils.js +55 -0
- package/dist/charts/pattern-area.d.ts +21 -0
- package/dist/charts/pattern-area.js +19 -0
- package/dist/charts/pattern-preset.d.ts +26 -0
- package/dist/charts/pattern-preset.js +83 -0
- package/dist/charts/pie-center-shell.d.ts +24 -0
- package/dist/charts/pie-center-shell.js +109 -0
- package/dist/charts/pie-center.d.ts +46 -0
- package/dist/charts/pie-center.js +46 -0
- package/dist/charts/pie-chart.d.ts +50 -0
- package/dist/charts/pie-chart.js +248 -0
- package/dist/charts/pie-context.d.ts +74 -0
- package/dist/charts/pie-context.js +95 -0
- package/dist/charts/pie-slice.d.ts +28 -0
- package/dist/charts/pie-slice.js +180 -0
- package/dist/charts/profit-loss-legend-hover.d.ts +11 -0
- package/dist/charts/profit-loss-legend-hover.js +12 -0
- package/dist/charts/profit-loss-legend.d.ts +17 -0
- package/dist/charts/profit-loss-legend.js +18 -0
- package/dist/charts/profit-loss-line.d.ts +27 -0
- package/dist/charts/profit-loss-line.js +77 -0
- package/dist/charts/profit-loss-segments.d.ts +12 -0
- package/dist/charts/profit-loss-segments.js +86 -0
- package/dist/charts/projection-config.d.ts +11 -0
- package/dist/charts/projection-config.js +80 -0
- package/dist/charts/projection-line-end-marker.d.ts +15 -0
- package/dist/charts/projection-line-end-marker.js +27 -0
- package/dist/charts/projection-line.d.ts +40 -0
- package/dist/charts/projection-line.js +79 -0
- package/dist/charts/projection-utils.d.ts +46 -0
- package/dist/charts/projection-utils.js +253 -0
- package/dist/charts/radar-area.d.ts +17 -0
- package/dist/charts/radar-area.js +84 -0
- package/dist/charts/radar-axis.d.ts +14 -0
- package/dist/charts/radar-axis.js +24 -0
- package/dist/charts/radar-chart.d.ts +36 -0
- package/dist/charts/radar-chart.js +89 -0
- package/dist/charts/radar-context.d.ts +68 -0
- package/dist/charts/radar-context.js +87 -0
- package/dist/charts/radar-grid.d.ts +16 -0
- package/dist/charts/radar-grid.js +40 -0
- package/dist/charts/radar-labels.d.ts +16 -0
- package/dist/charts/radar-labels.js +29 -0
- package/dist/charts/reference-area-config.d.ts +10 -0
- package/dist/charts/reference-area-config.js +39 -0
- package/dist/charts/reference-area-geometry.d.ts +23 -0
- package/dist/charts/reference-area-geometry.js +68 -0
- package/dist/charts/reference-area-registration-context.d.ts +8 -0
- package/dist/charts/reference-area-registration-context.js +7 -0
- package/dist/charts/reference-area.d.ts +52 -0
- package/dist/charts/reference-area.js +101 -0
- package/dist/charts/ring-center.d.ts +46 -0
- package/dist/charts/ring-center.js +41 -0
- package/dist/charts/ring-chart.d.ts +41 -0
- package/dist/charts/ring-chart.js +212 -0
- package/dist/charts/ring-context.d.ts +66 -0
- package/dist/charts/ring-context.js +92 -0
- package/dist/charts/ring.d.ts +11 -0
- package/dist/charts/ring.js +104 -0
- package/dist/charts/sankey/index.d.ts +6 -0
- package/dist/charts/sankey/index.js +6 -0
- package/dist/charts/sankey/sankey-chart.d.ts +39 -0
- package/dist/charts/sankey/sankey-chart.js +117 -0
- package/dist/charts/sankey/sankey-context.d.ts +69 -0
- package/dist/charts/sankey/sankey-context.js +23 -0
- package/dist/charts/sankey/sankey-link.d.ts +26 -0
- package/dist/charts/sankey/sankey-link.js +155 -0
- package/dist/charts/sankey/sankey-node.d.ts +29 -0
- package/dist/charts/sankey/sankey-node.js +200 -0
- package/dist/charts/sankey/sankey-tooltip.d.ts +24 -0
- package/dist/charts/sankey/sankey-tooltip.js +70 -0
- package/dist/charts/scatter-chart-shell.d.ts +21 -0
- package/dist/charts/scatter-chart-shell.js +152 -0
- package/dist/charts/scatter-chart.d.ts +32 -0
- package/dist/charts/scatter-chart.js +56 -0
- package/dist/charts/scatter-svg.d.ts +6 -0
- package/dist/charts/scatter-svg.js +16 -0
- package/dist/charts/scatter.d.ts +21 -0
- package/dist/charts/scatter.js +30 -0
- package/dist/charts/segment.d.ts +26 -0
- package/dist/charts/segment.js +42 -0
- package/dist/charts/series-bar-layout.d.ts +18 -0
- package/dist/charts/series-bar-layout.js +31 -0
- package/dist/charts/series-bar.d.ts +20 -0
- package/dist/charts/series-bar.js +120 -0
- package/dist/charts/series-dash-tail-overlay.d.ts +17 -0
- package/dist/charts/series-dash-tail-overlay.js +39 -0
- package/dist/charts/series-highlight-layer.d.ts +23 -0
- package/dist/charts/series-highlight-layer.js +21 -0
- package/dist/charts/series-hover-dim.d.ts +29 -0
- package/dist/charts/series-hover-dim.js +26 -0
- package/dist/charts/series-markers.d.ts +14 -0
- package/dist/charts/series-markers.js +98 -0
- package/dist/charts/series-path-utils.d.ts +19 -0
- package/dist/charts/series-path-utils.js +60 -0
- package/dist/charts/series-point-marker.d.ts +48 -0
- package/dist/charts/series-point-marker.js +48 -0
- package/dist/charts/shimmering-text.d.ts +23 -0
- package/dist/charts/shimmering-text.js +31 -0
- package/dist/charts/static-chart-preview-context.d.ts +7 -0
- package/dist/charts/static-chart-preview-context.js +12 -0
- package/dist/charts/sunburst-breadcrumb.d.ts +16 -0
- package/dist/charts/sunburst-breadcrumb.js +26 -0
- package/dist/charts/sunburst-center.d.ts +5 -0
- package/dist/charts/sunburst-center.js +17 -0
- package/dist/charts/sunburst-chart.d.ts +30 -0
- package/dist/charts/sunburst-chart.js +263 -0
- package/dist/charts/sunburst-context.d.ts +61 -0
- package/dist/charts/sunburst-context.js +112 -0
- package/dist/charts/sunburst-data.d.ts +9 -0
- package/dist/charts/sunburst-data.js +2 -0
- package/dist/charts/sunburst-hint.d.ts +13 -0
- package/dist/charts/sunburst-hint.js +31 -0
- package/dist/charts/sunburst-labels.d.ts +9 -0
- package/dist/charts/sunburst-labels.js +63 -0
- package/dist/charts/sunburst-segment.d.ts +11 -0
- package/dist/charts/sunburst-segment.js +78 -0
- package/dist/charts/sunburst.d.ts +101 -0
- package/dist/charts/sunburst.js +396 -0
- package/dist/charts/time-series-chart-shell.d.ts +47 -0
- package/dist/charts/time-series-chart-shell.js +390 -0
- package/dist/charts/tooltip/chart-tooltip.d.ts +76 -0
- package/dist/charts/tooltip/chart-tooltip.js +150 -0
- package/dist/charts/tooltip/date-ticker.d.ts +11 -0
- package/dist/charts/tooltip/date-ticker.js +77 -0
- package/dist/charts/tooltip/index.d.ts +7 -0
- package/dist/charts/tooltip/index.js +7 -0
- package/dist/charts/tooltip/tooltip-box.d.ts +48 -0
- package/dist/charts/tooltip/tooltip-box.js +114 -0
- package/dist/charts/tooltip/tooltip-content.d.ts +18 -0
- package/dist/charts/tooltip/tooltip-content.js +9 -0
- package/dist/charts/tooltip/tooltip-dot.d.ts +28 -0
- package/dist/charts/tooltip/tooltip-dot.js +54 -0
- package/dist/charts/tooltip/tooltip-indicator.d.ts +45 -0
- package/dist/charts/tooltip/tooltip-indicator.js +65 -0
- package/dist/charts/use-animated-series-path.d.ts +19 -0
- package/dist/charts/use-animated-series-path.js +93 -0
- package/dist/charts/use-animated-y-domains.d.ts +14 -0
- package/dist/charts/use-animated-y-domains.js +150 -0
- package/dist/charts/use-chart-interaction.d.ts +41 -0
- package/dist/charts/use-chart-interaction.js +244 -0
- package/dist/charts/use-chart-phase-orchestrator.d.ts +23 -0
- package/dist/charts/use-chart-phase-orchestrator.js +139 -0
- package/dist/charts/use-enter-complete.d.ts +8 -0
- package/dist/charts/use-enter-complete.js +23 -0
- package/dist/charts/use-grid-shimmer.d.ts +16 -0
- package/dist/charts/use-grid-shimmer.js +63 -0
- package/dist/charts/use-highlight-segment.d.ts +14 -0
- package/dist/charts/use-highlight-segment.js +34 -0
- package/dist/charts/use-mount-progress.d.ts +4 -0
- package/dist/charts/use-mount-progress.js +22 -0
- package/dist/charts/use-scatter-chart-interaction.d.ts +35 -0
- package/dist/charts/use-scatter-chart-interaction.js +228 -0
- package/dist/charts/use-scheduled-tooltip.d.ts +9 -0
- package/dist/charts/use-scheduled-tooltip.js +76 -0
- package/dist/charts/visx-pattern.d.ts +19 -0
- package/dist/charts/visx-pattern.js +20 -0
- package/dist/charts/x-axis.d.ts +27 -0
- package/dist/charts/x-axis.js +415 -0
- package/dist/charts/y-axis-scales.d.ts +26 -0
- package/dist/charts/y-axis-scales.js +72 -0
- package/dist/charts/y-axis-ticks.d.ts +12 -0
- package/dist/charts/y-axis-ticks.js +24 -0
- package/dist/charts/y-axis.d.ts +22 -0
- package/dist/charts/y-axis.js +80 -0
- package/dist/charts/y-domain-utils.d.ts +27 -0
- package/dist/charts/y-domain-utils.js +88 -0
- package/dist/components/accordion.d.ts +6 -0
- package/dist/components/accordion.js +20 -0
- package/dist/components/alert-dialog.d.ts +18 -0
- package/dist/components/alert-dialog.js +41 -0
- package/dist/components/alert.d.ts +24 -0
- package/dist/components/alert.js +46 -0
- package/dist/components/animated-button.d.ts +5 -0
- package/dist/components/animated-button.js +16 -0
- package/dist/components/animated-list.d.ts +26 -0
- package/dist/components/animated-list.js +25 -0
- package/dist/components/animated-number.d.ts +67 -0
- package/dist/components/animated-number.js +131 -0
- package/dist/components/app-shell.d.ts +27 -0
- package/dist/components/app-shell.js +18 -0
- package/dist/components/area-chart.d.ts +11 -0
- package/dist/components/area-chart.js +12 -0
- package/dist/components/aspect-ratio.d.ts +16 -0
- package/dist/components/aspect-ratio.js +14 -0
- package/dist/components/aurora-background.d.ts +3 -0
- package/dist/components/aurora-background.js +8 -0
- package/dist/components/autocomplete.d.ts +55 -0
- package/dist/components/autocomplete.js +279 -0
- package/dist/components/avatar-group.d.ts +39 -0
- package/dist/components/avatar-group.js +50 -0
- package/dist/components/avatar.d.ts +5 -0
- package/dist/components/avatar.js +17 -0
- package/dist/components/badge.d.ts +10 -0
- package/dist/components/badge.js +35 -0
- package/dist/components/banner.d.ts +45 -0
- package/dist/components/banner.js +80 -0
- package/dist/components/bar-chart.d.ts +11 -0
- package/dist/components/bar-chart.js +9 -0
- package/dist/components/border-beam.d.ts +45 -0
- package/dist/components/border-beam.js +48 -0
- package/dist/components/breadcrumb.d.ts +12 -0
- package/dist/components/breadcrumb.js +35 -0
- package/dist/components/button-group.d.ts +7 -0
- package/dist/components/button-group.js +10 -0
- package/dist/components/button.d.ts +12 -0
- package/dist/components/button.js +39 -0
- package/dist/components/calendar.d.ts +7 -0
- package/dist/components/calendar.js +71 -0
- package/dist/components/candlestick-chart.d.ts +13 -0
- package/dist/components/candlestick-chart.js +66 -0
- package/dist/components/card-stack.d.ts +28 -0
- package/dist/components/card-stack.js +47 -0
- package/dist/components/card.d.ts +9 -0
- package/dist/components/card.js +32 -0
- package/dist/components/carousel.d.ts +82 -0
- package/dist/components/carousel.js +310 -0
- package/dist/components/chart.d.ts +100 -0
- package/dist/components/chart.js +210 -0
- package/dist/components/checkbox.d.ts +3 -0
- package/dist/components/checkbox.js +11 -0
- package/dist/components/chip.d.ts +80 -0
- package/dist/components/chip.js +186 -0
- package/dist/components/choropleth-chart.d.ts +12 -0
- package/dist/components/choropleth-chart.js +31 -0
- package/dist/components/click-spark.d.ts +19 -0
- package/dist/components/click-spark.js +51 -0
- package/dist/components/code-block.d.ts +13 -0
- package/dist/components/code-block.js +20 -0
- package/dist/components/code-tabs.d.ts +51 -0
- package/dist/components/code-tabs.js +150 -0
- package/dist/components/collapsible.d.ts +5 -0
- package/dist/components/collapsible.js +12 -0
- package/dist/components/color-picker.d.ts +30 -0
- package/dist/components/color-picker.js +300 -0
- package/dist/components/combobox.d.ts +33 -0
- package/dist/components/combobox.js +32 -0
- package/dist/components/command.d.ts +87 -0
- package/dist/components/command.js +44 -0
- package/dist/components/comparison-slider.d.ts +17 -0
- package/dist/components/comparison-slider.js +81 -0
- package/dist/components/composed-chart.d.ts +13 -0
- package/dist/components/composed-chart.js +22 -0
- package/dist/components/confetti.d.ts +21 -0
- package/dist/components/confetti.js +111 -0
- package/dist/components/confirmation-dialog.d.ts +46 -0
- package/dist/components/confirmation-dialog.js +102 -0
- package/dist/components/context-menu.d.ts +28 -0
- package/dist/components/context-menu.js +52 -0
- package/dist/components/copy-button.d.ts +13 -0
- package/dist/components/copy-button.js +72 -0
- package/dist/components/countdown.d.ts +58 -0
- package/dist/components/countdown.js +106 -0
- package/dist/components/credit-card-input.d.ts +62 -0
- package/dist/components/credit-card-input.js +211 -0
- package/dist/components/currency-input.d.ts +86 -0
- package/dist/components/currency-input.js +215 -0
- package/dist/components/data-table.d.ts +232 -0
- package/dist/components/data-table.js +359 -0
- package/dist/components/date-picker.d.ts +66 -0
- package/dist/components/date-picker.js +55 -0
- package/dist/components/date-range-picker.d.ts +59 -0
- package/dist/components/date-range-picker.js +59 -0
- package/dist/components/description-list.d.ts +84 -0
- package/dist/components/description-list.js +138 -0
- package/dist/components/dialog.d.ts +26 -0
- package/dist/components/dialog.js +35 -0
- package/dist/components/dock.d.ts +34 -0
- package/dist/components/dock.js +61 -0
- package/dist/components/dot-pattern.d.ts +24 -0
- package/dist/components/dot-pattern.js +19 -0
- package/dist/components/drawer.d.ts +22 -0
- package/dist/components/drawer.js +37 -0
- package/dist/components/dropdown-menu.d.ts +32 -0
- package/dist/components/dropdown-menu.js +56 -0
- package/dist/components/dynamic-island.d.ts +26 -0
- package/dist/components/dynamic-island.js +31 -0
- package/dist/components/empty.d.ts +7 -0
- package/dist/components/empty.js +24 -0
- package/dist/components/expandable-tabs.d.ts +24 -0
- package/dist/components/expandable-tabs.js +30 -0
- package/dist/components/fab.d.ts +35 -0
- package/dist/components/fab.js +36 -0
- package/dist/components/field.d.ts +6 -0
- package/dist/components/field.js +22 -0
- package/dist/components/file-dropzone.d.ts +28 -0
- package/dist/components/file-dropzone.js +59 -0
- package/dist/components/flickering-grid.d.ts +25 -0
- package/dist/components/flickering-grid.js +30 -0
- package/dist/components/flip-card.d.ts +70 -0
- package/dist/components/flip-card.js +117 -0
- package/dist/components/floating-label-input.d.ts +34 -0
- package/dist/components/floating-label-input.js +25 -0
- package/dist/components/form.d.ts +25 -0
- package/dist/components/form.js +68 -0
- package/dist/components/frame.d.ts +12 -0
- package/dist/components/frame.js +10 -0
- package/dist/components/funnel-chart.d.ts +11 -0
- package/dist/components/funnel-chart.js +16 -0
- package/dist/components/gauge-chart.d.ts +8 -0
- package/dist/components/gauge-chart.js +10 -0
- package/dist/components/glare-hover.d.ts +15 -0
- package/dist/components/glare-hover.js +64 -0
- package/dist/components/glass-card.d.ts +3 -0
- package/dist/components/glass-card.js +8 -0
- package/dist/components/gradient-border.d.ts +7 -0
- package/dist/components/gradient-border.js +8 -0
- package/dist/components/gradient-text.d.ts +6 -0
- package/dist/components/gradient-text.js +10 -0
- package/dist/components/grid-pattern.d.ts +23 -0
- package/dist/components/grid-pattern.js +18 -0
- package/dist/components/heatmap-chart.d.ts +6 -0
- package/dist/components/heatmap-chart.js +8 -0
- package/dist/components/heatmap.d.ts +28 -0
- package/dist/components/heatmap.js +41 -0
- package/dist/components/highlighter.d.ts +20 -0
- package/dist/components/highlighter.js +19 -0
- package/dist/components/hover-card.d.ts +5 -0
- package/dist/components/hover-card.js +12 -0
- package/dist/components/image-zoom.d.ts +47 -0
- package/dist/components/image-zoom.js +125 -0
- package/dist/components/input-group.d.ts +10 -0
- package/dist/components/input-group.js +12 -0
- package/dist/components/input-otp.d.ts +18 -0
- package/dist/components/input-otp.js +38 -0
- package/dist/components/input.d.ts +6 -0
- package/dist/components/input.js +8 -0
- package/dist/components/json-viewer.d.ts +43 -0
- package/dist/components/json-viewer.js +313 -0
- package/dist/components/kanban.d.ts +31 -0
- package/dist/components/kanban.js +143 -0
- package/dist/components/kbd.d.ts +3 -0
- package/dist/components/kbd.js +8 -0
- package/dist/components/label.d.ts +3 -0
- package/dist/components/label.js +9 -0
- package/dist/components/light-rays.d.ts +19 -0
- package/dist/components/light-rays.js +20 -0
- package/dist/components/lightbox.d.ts +24 -0
- package/dist/components/lightbox.js +68 -0
- package/dist/components/line-chart.d.ts +10 -0
- package/dist/components/line-chart.js +9 -0
- package/dist/components/live-line-chart.d.ts +12 -0
- package/dist/components/live-line-chart.js +42 -0
- package/dist/components/logo-carousel.d.ts +27 -0
- package/dist/components/logo-carousel.js +101 -0
- package/dist/components/magnetic.d.ts +44 -0
- package/dist/components/magnetic.js +172 -0
- package/dist/components/marquee.d.ts +71 -0
- package/dist/components/marquee.js +141 -0
- package/dist/components/masonry.d.ts +16 -0
- package/dist/components/masonry.js +84 -0
- package/dist/components/menubar.d.ts +33 -0
- package/dist/components/menubar.js +56 -0
- package/dist/components/meteors.d.ts +20 -0
- package/dist/components/meteors.js +39 -0
- package/dist/components/metric.d.ts +9 -0
- package/dist/components/metric.js +35 -0
- package/dist/components/mode-toggle.d.ts +32 -0
- package/dist/components/mode-toggle.js +40 -0
- package/dist/components/morphing-popover.d.ts +91 -0
- package/dist/components/morphing-popover.js +194 -0
- package/dist/components/motion-presets.d.ts +9 -0
- package/dist/components/motion-presets.js +20 -0
- package/dist/components/multi-select.d.ts +54 -0
- package/dist/components/multi-select.js +0 -0
- package/dist/components/navigation-menu.d.ts +12 -0
- package/dist/components/navigation-menu.js +42 -0
- package/dist/components/noise.d.ts +19 -0
- package/dist/components/noise.js +18 -0
- package/dist/components/notification-center.d.ts +68 -0
- package/dist/components/notification-center.js +57 -0
- package/dist/components/number-input.d.ts +45 -0
- package/dist/components/number-input.js +148 -0
- package/dist/components/orbit.d.ts +77 -0
- package/dist/components/orbit.js +100 -0
- package/dist/components/pagination.d.ts +16 -0
- package/dist/components/pagination.js +34 -0
- package/dist/components/particles.d.ts +18 -0
- package/dist/components/particles.js +92 -0
- package/dist/components/password-input.d.ts +16 -0
- package/dist/components/password-input.js +49 -0
- package/dist/components/phone-input.d.ts +67 -0
- package/dist/components/phone-input.js +225 -0
- package/dist/components/pie-chart.d.ts +12 -0
- package/dist/components/pie-chart.js +13 -0
- package/dist/components/pill-nav.d.ts +25 -0
- package/dist/components/pill-nav.js +66 -0
- package/dist/components/popover.d.ts +7 -0
- package/dist/components/popover.js +15 -0
- package/dist/components/profit-loss-chart.d.ts +10 -0
- package/dist/components/profit-loss-chart.js +8 -0
- package/dist/components/progress.d.ts +10 -0
- package/dist/components/progress.js +17 -0
- package/dist/components/progressive-blur.d.ts +24 -0
- package/dist/components/progressive-blur.js +43 -0
- package/dist/components/radar-chart.d.ts +9 -0
- package/dist/components/radar-chart.js +9 -0
- package/dist/components/radio-group.d.ts +4 -0
- package/dist/components/radio-group.js +15 -0
- package/dist/components/rating.d.ts +29 -0
- package/dist/components/rating.js +94 -0
- package/dist/components/resizable.d.ts +57 -0
- package/dist/components/resizable.js +73 -0
- package/dist/components/retro-grid.d.ts +25 -0
- package/dist/components/retro-grid.js +26 -0
- package/dist/components/reveal.d.ts +9 -0
- package/dist/components/reveal.js +14 -0
- package/dist/components/rich-text-editor.d.ts +28 -0
- package/dist/components/rich-text-editor.js +83 -0
- package/dist/components/ring-chart.d.ts +13 -0
- package/dist/components/ring-chart.js +16 -0
- package/dist/components/ripple.d.ts +25 -0
- package/dist/components/ripple.js +26 -0
- package/dist/components/sankey-chart.d.ts +16 -0
- package/dist/components/sankey-chart.js +8 -0
- package/dist/components/scatter-chart.d.ts +12 -0
- package/dist/components/scatter-chart.js +9 -0
- package/dist/components/scheduler.d.ts +50 -0
- package/dist/components/scheduler.js +93 -0
- package/dist/components/scramble-text.d.ts +39 -0
- package/dist/components/scramble-text.js +78 -0
- package/dist/components/scroll-area.d.ts +13 -0
- package/dist/components/scroll-area.js +14 -0
- package/dist/components/scroll-progress.d.ts +19 -0
- package/dist/components/scroll-progress.js +67 -0
- package/dist/components/segmented-control.d.ts +48 -0
- package/dist/components/segmented-control.js +222 -0
- package/dist/components/select.d.ts +12 -0
- package/dist/components/select.js +43 -0
- package/dist/components/separator.d.ts +3 -0
- package/dist/components/separator.js +9 -0
- package/dist/components/sheet.d.ts +25 -0
- package/dist/components/sheet.js +47 -0
- package/dist/components/shimmer.d.ts +3 -0
- package/dist/components/shimmer.js +8 -0
- package/dist/components/shiny-text.d.ts +20 -0
- package/dist/components/shiny-text.js +24 -0
- package/dist/components/sidebar.d.ts +92 -0
- package/dist/components/sidebar.js +290 -0
- package/dist/components/signature-pad.d.ts +44 -0
- package/dist/components/signature-pad.js +317 -0
- package/dist/components/skeleton.d.ts +3 -0
- package/dist/components/skeleton.js +8 -0
- package/dist/components/slider.d.ts +10 -0
- package/dist/components/slider.js +27 -0
- package/dist/components/sonner.d.ts +9 -0
- package/dist/components/sonner.js +17 -0
- package/dist/components/sparkles-text.d.ts +19 -0
- package/dist/components/sparkles-text.js +36 -0
- package/dist/components/sparkline.d.ts +22 -0
- package/dist/components/sparkline.js +100 -0
- package/dist/components/spinner.d.ts +10 -0
- package/dist/components/spinner.js +20 -0
- package/dist/components/spinning-text.d.ts +29 -0
- package/dist/components/spinning-text.js +40 -0
- package/dist/components/split-button.d.ts +71 -0
- package/dist/components/split-button.js +30 -0
- package/dist/components/spotlight-card.d.ts +11 -0
- package/dist/components/spotlight-card.js +63 -0
- package/dist/components/star-border.d.ts +19 -0
- package/dist/components/star-border.js +18 -0
- package/dist/components/status-dot.d.ts +60 -0
- package/dist/components/status-dot.js +76 -0
- package/dist/components/stepper.d.ts +98 -0
- package/dist/components/stepper.js +164 -0
- package/dist/components/sunburst-chart.d.ts +11 -0
- package/dist/components/sunburst-chart.js +45 -0
- package/dist/components/switch.d.ts +3 -0
- package/dist/components/switch.js +10 -0
- package/dist/components/table-of-contents.d.ts +64 -0
- package/dist/components/table-of-contents.js +0 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/table.js +38 -0
- package/dist/components/tabs.d.ts +6 -0
- package/dist/components/tabs.js +22 -0
- package/dist/components/tags-input.d.ts +39 -0
- package/dist/components/tags-input.js +86 -0
- package/dist/components/terminal.d.ts +86 -0
- package/dist/components/terminal.js +182 -0
- package/dist/components/text-effect.d.ts +71 -0
- package/dist/components/text-effect.js +166 -0
- package/dist/components/textarea.d.ts +6 -0
- package/dist/components/textarea.js +8 -0
- package/dist/components/tilt-card.d.ts +30 -0
- package/dist/components/tilt-card.js +84 -0
- package/dist/components/time-picker.d.ts +58 -0
- package/dist/components/time-picker.js +245 -0
- package/dist/components/timeline.d.ts +81 -0
- package/dist/components/timeline.js +165 -0
- package/dist/components/toggle-group.d.ts +12 -0
- package/dist/components/toggle-group.js +23 -0
- package/dist/components/toggle.d.ts +12 -0
- package/dist/components/toggle.js +25 -0
- package/dist/components/toolbar.d.ts +14 -0
- package/dist/components/toolbar.js +89 -0
- package/dist/components/tooltip.d.ts +29 -0
- package/dist/components/tooltip.js +48 -0
- package/dist/components/tree-view.d.ts +45 -0
- package/dist/components/tree-view.js +197 -0
- package/dist/components/typing-text.d.ts +49 -0
- package/dist/components/typing-text.js +90 -0
- package/dist/components/usage-meter.d.ts +30 -0
- package/dist/components/usage-meter.js +90 -0
- package/dist/components/video-player.d.ts +48 -0
- package/dist/components/video-player.js +216 -0
- package/dist/components/word-rotate.d.ts +40 -0
- package/dist/components/word-rotate.js +34 -0
- package/dist/index.d.ts +306 -0
- package/dist/index.js +179 -0
- package/dist/lib/cn.d.ts +7 -0
- package/dist/lib/cn.js +10 -0
- package/dist/lib/demo-saas.d.ts +171 -0
- package/dist/lib/demo-saas.js +210 -0
- package/dist/lib/demo-store.d.ts +157 -0
- package/dist/lib/demo-store.js +353 -0
- package/dist/testing/index.d.ts +76 -0
- package/dist/testing/index.js +116 -0
- package/package.json +941 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface TagsInputProps {
|
|
2
|
+
/** Controlled list of committed tags. Pair with `onValueChange`. */
|
|
3
|
+
value?: string[];
|
|
4
|
+
/** Initial tags for uncontrolled usage. */
|
|
5
|
+
defaultValue?: string[];
|
|
6
|
+
/** Called with the next list of tags whenever a tag is added or removed. */
|
|
7
|
+
onValueChange?: (tags: string[]) => void;
|
|
8
|
+
/** Placeholder shown in the text field when it is empty. */
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
/** Maximum number of tags. Once reached, further additions are ignored. */
|
|
11
|
+
max?: number;
|
|
12
|
+
/** Disables typing and tag removal. */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** When true, the same tag may be added more than once. Defaults to false. */
|
|
15
|
+
allowDuplicates?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Characters that commit the current input as a tag, in addition to Enter.
|
|
18
|
+
* Defaults to a comma, so both Enter and "," commit.
|
|
19
|
+
*/
|
|
20
|
+
delimiter?: string | string[];
|
|
21
|
+
/** Reject a tag when this returns false. Receives the trimmed candidate. */
|
|
22
|
+
validate?: (tag: string) => boolean;
|
|
23
|
+
/** Marks the field as invalid, applying error styling. */
|
|
24
|
+
"aria-invalid"?: boolean | "true" | "false";
|
|
25
|
+
/** Native id for the text input (for an external `<label htmlFor>`). */
|
|
26
|
+
id?: string;
|
|
27
|
+
/** Accessible name for the text input when there is no visible label. */
|
|
28
|
+
"aria-label"?: string;
|
|
29
|
+
/** id of an element that labels the text input. */
|
|
30
|
+
"aria-labelledby"?: string;
|
|
31
|
+
/** Native name for the text input. */
|
|
32
|
+
name?: string;
|
|
33
|
+
/** Extra classes for the field wrapper. */
|
|
34
|
+
className?: string;
|
|
35
|
+
/** Extra classes for the inner text input. */
|
|
36
|
+
inputClassName?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare const TagsInput: import("react").ForwardRefExoticComponent<TagsInputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
39
|
+
//# sourceMappingURL=tags-input.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { X } from "lucide-react";
|
|
4
|
+
import { forwardRef, useCallback, useImperativeHandle, useRef, useState, } from "react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Badge } from "./badge.js";
|
|
7
|
+
const DEFAULT_DELIMITERS = [","];
|
|
8
|
+
export const TagsInput = forwardRef(({ value: valueProp, defaultValue, onValueChange, placeholder, max, disabled = false, allowDuplicates = false, delimiter = DEFAULT_DELIMITERS, validate, "aria-invalid": ariaInvalid, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, name, className, inputClassName, }, ref) => {
|
|
9
|
+
const inputRef = useRef(null);
|
|
10
|
+
// Expose the inner input as the forwarded ref so consumers can focus it.
|
|
11
|
+
useImperativeHandle(ref, () => inputRef.current, []);
|
|
12
|
+
const [draft, setDraft] = useState("");
|
|
13
|
+
const isControlled = valueProp !== undefined;
|
|
14
|
+
const [internalValue, setInternalValue] = useState(defaultValue ?? []);
|
|
15
|
+
const tags = isControlled ? valueProp : internalValue;
|
|
16
|
+
const delimiters = Array.isArray(delimiter) ? delimiter : [delimiter];
|
|
17
|
+
const setTags = useCallback((next) => {
|
|
18
|
+
if (!isControlled)
|
|
19
|
+
setInternalValue(next);
|
|
20
|
+
onValueChange?.(next);
|
|
21
|
+
}, [isControlled, onValueChange]);
|
|
22
|
+
const addTag = useCallback((raw) => {
|
|
23
|
+
const tag = raw.trim();
|
|
24
|
+
if (tag === "")
|
|
25
|
+
return false;
|
|
26
|
+
if (max !== undefined && tags.length >= max)
|
|
27
|
+
return false;
|
|
28
|
+
if (!allowDuplicates && tags.includes(tag))
|
|
29
|
+
return false;
|
|
30
|
+
if (validate && !validate(tag))
|
|
31
|
+
return false;
|
|
32
|
+
setTags([...tags, tag]);
|
|
33
|
+
return true;
|
|
34
|
+
}, [tags, max, allowDuplicates, validate, setTags]);
|
|
35
|
+
const removeTag = useCallback((index) => {
|
|
36
|
+
setTags(tags.filter((_, i) => i !== index));
|
|
37
|
+
}, [tags, setTags]);
|
|
38
|
+
const handleKeyDown = useCallback((event) => {
|
|
39
|
+
if (disabled)
|
|
40
|
+
return;
|
|
41
|
+
if (event.key === "Enter") {
|
|
42
|
+
// Don't submit a surrounding form when committing a tag.
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
if (addTag(draft))
|
|
45
|
+
setDraft("");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (delimiters.includes(event.key)) {
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
if (addTag(draft))
|
|
51
|
+
setDraft("");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (event.key === "Backspace" && draft === "" && tags.length > 0) {
|
|
55
|
+
// Empty field: backspace edits the committed tags, not the text.
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
removeTag(tags.length - 1);
|
|
58
|
+
}
|
|
59
|
+
}, [disabled, draft, delimiters, tags.length, addTag, removeTag]);
|
|
60
|
+
const handleBlur = useCallback(() => {
|
|
61
|
+
// Commit any pending text on blur so a typed-but-not-entered tag isn't lost.
|
|
62
|
+
if (disabled)
|
|
63
|
+
return;
|
|
64
|
+
if (addTag(draft))
|
|
65
|
+
setDraft("");
|
|
66
|
+
}, [disabled, draft, addTag]);
|
|
67
|
+
const handleFieldMouseDown = useCallback((event) => {
|
|
68
|
+
if (disabled)
|
|
69
|
+
return;
|
|
70
|
+
// Clicking anywhere in the field (the padding, between chips) focuses the
|
|
71
|
+
// input — but let clicks land on the remove buttons themselves.
|
|
72
|
+
if (event.target === inputRef.current)
|
|
73
|
+
return;
|
|
74
|
+
if (event.target.closest("[data-slot='tags-input-remove']"))
|
|
75
|
+
return;
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
inputRef.current?.focus();
|
|
78
|
+
}, [disabled]);
|
|
79
|
+
const atMax = max !== undefined && tags.length >= max;
|
|
80
|
+
return (_jsxs("div", { "data-slot": "tags-input", "data-disabled": disabled ? "" : undefined, "aria-invalid": ariaInvalid, onMouseDown: handleFieldMouseDown, className: cn("flex min-h-10 w-full flex-wrap items-center gap-1.5 rounded-lg border border-border bg-surface-inset px-3 py-1.5 text-sm text-fg", "transition-[border-color,box-shadow] duration-150 ease-[var(--ease-out-quart)]", "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-surface-base", "data-[disabled]:opacity-50 data-[disabled]:pointer-events-none", "aria-invalid:border-error aria-invalid:ring-2 aria-invalid:ring-error/30", className), children: [tags.map((tag, index) => (_jsxs(Badge, { variant: "secondary", className: "gap-1 pr-1", children: [_jsx("span", { className: "truncate", children: tag }), disabled ? null : (_jsx("button", { type: "button", tabIndex: -1, "aria-label": `Remove ${tag}`, "data-slot": "tags-input-remove", className: "flex size-3.5 items-center justify-center rounded-sm text-fg-tertiary outline-none transition-colors hover:text-fg focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", onClick: () => removeTag(index), children: _jsx(X, { className: "size-3", "aria-hidden": "true" }) }))] }, `${tag}-${index}`))), _jsx("input", { ref: inputRef, id: id, name: name, type: "text", autoComplete: "off", disabled: disabled,
|
|
81
|
+
// Once `max` is reached, keep the field present but read-only so focus
|
|
82
|
+
// and chip removal still work; clearing a tag re-enables typing.
|
|
83
|
+
readOnly: atMax, "aria-invalid": ariaInvalid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, placeholder: tags.length === 0 ? placeholder : undefined, value: draft, "data-slot": "tags-input-field", className: cn("min-w-[6rem] flex-1 bg-transparent text-sm text-fg outline-none", "placeholder:text-fg-tertiary", "selection:bg-primary selection:text-primary-foreground", "disabled:pointer-events-none", inputClassName), onChange: (event) => setDraft(event.target.value), onKeyDown: handleKeyDown, onBlur: handleBlur })] }));
|
|
84
|
+
});
|
|
85
|
+
TagsInput.displayName = "TagsInput";
|
|
86
|
+
//# sourceMappingURL=tags-input.js.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type HTMLAttributes } from "react";
|
|
2
|
+
/** One line of the terminal script. */
|
|
3
|
+
export interface TerminalLine {
|
|
4
|
+
/**
|
|
5
|
+
* `"input"` lines render behind the prompt and type in char-by-char with a
|
|
6
|
+
* blinking block cursor; `"output"` lines fade in whole, like a command's
|
|
7
|
+
* result being printed.
|
|
8
|
+
*/
|
|
9
|
+
type: "input" | "output";
|
|
10
|
+
/** The line's text, rendered verbatim (whitespace is preserved). */
|
|
11
|
+
text: string;
|
|
12
|
+
/**
|
|
13
|
+
* Milliseconds to wait before this line starts — before typing begins for
|
|
14
|
+
* inputs, before the reveal for outputs. Defaults to 400 for inputs (the
|
|
15
|
+
* prompt sits with a blinking cursor, like a person pausing) and 150 for
|
|
16
|
+
* outputs (a beat of "execution time").
|
|
17
|
+
*/
|
|
18
|
+
delay?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Whether the session animates. `"respect"` (default) honours the visitor's
|
|
22
|
+
* `prefers-reduced-motion` setting — reduced-motion visitors get the full
|
|
23
|
+
* transcript instantly. `"always"` forces the animation (e.g. a showcase that
|
|
24
|
+
* must demonstrate it); `"never"` always renders the finished transcript.
|
|
25
|
+
*/
|
|
26
|
+
export type TerminalMotionPreference = "respect" | "always" | "never";
|
|
27
|
+
export interface TerminalProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
28
|
+
/** The scripted session, played from first to last. */
|
|
29
|
+
lines: TerminalLine[];
|
|
30
|
+
/** Title shown centered in the chrome bar (e.g. `"zsh"` or a file path). */
|
|
31
|
+
title?: string;
|
|
32
|
+
/** Render the macOS-style chrome bar (three dots + title). Defaults to `true`. */
|
|
33
|
+
chrome?: boolean;
|
|
34
|
+
/** Prompt glyph rendered before each input line. Defaults to `"$"`. */
|
|
35
|
+
prompt?: string;
|
|
36
|
+
/** Milliseconds per typed character. Defaults to `30`. */
|
|
37
|
+
typingSpeed?: number;
|
|
38
|
+
/** Restart the script from the top after it finishes. Defaults to `false`. */
|
|
39
|
+
loop?: boolean;
|
|
40
|
+
/** Milliseconds the finished transcript rests before a loop restarts. Defaults to `2000`. */
|
|
41
|
+
loopDelay?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Show a copy button that copies the joined `input` commands (one per line,
|
|
44
|
+
* without the prompt) — the exact text a reader wants to paste into their
|
|
45
|
+
* own shell. Defaults to `true`; hidden automatically when the script has
|
|
46
|
+
* no input lines.
|
|
47
|
+
*/
|
|
48
|
+
copyButton?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Whether the typing animation plays vs. honours `prefers-reduced-motion`:
|
|
51
|
+
* `"respect"` (default), `"always"` (force motion), or `"never"` (always
|
|
52
|
+
* static).
|
|
53
|
+
*/
|
|
54
|
+
motionPreference?: TerminalMotionPreference;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* An animated terminal window that replays a scripted shell session. Input
|
|
58
|
+
* lines type in char-by-char behind a `$` prompt with a blinking block
|
|
59
|
+
* cursor; output lines fade in whole after a beat of "execution time". The
|
|
60
|
+
* script is driven by a single chain of `setTimeout`s (one live timer at any
|
|
61
|
+
* moment, fully cleaned up on unmount/restart) that advances a tiny
|
|
62
|
+
* `{ revealed, typedChars }` state — no per-frame work, no layout thrash.
|
|
63
|
+
*
|
|
64
|
+
* **SSR-safe:** the server (and the hydration pass) renders the *finished*
|
|
65
|
+
* transcript, so no-JS readers and crawlers see the real content and there is
|
|
66
|
+
* no hydration mismatch. A layout effect flips to the animated state before
|
|
67
|
+
* first paint, so animated visitors never see a flash of the full transcript.
|
|
68
|
+
*
|
|
69
|
+
* **Reduced motion:** `prefers-reduced-motion` (or
|
|
70
|
+
* {@link TerminalProps.motionPreference} `"never"`) renders everything
|
|
71
|
+
* instantly — no typing, no cursor, no fades — and the preference is tracked
|
|
72
|
+
* live via `matchMedia`.
|
|
73
|
+
*
|
|
74
|
+
* **No layout shift:** an invisible copy of the finished transcript sits
|
|
75
|
+
* in-flow as a sizer and the animation plays in an absolutely-positioned
|
|
76
|
+
* overlay, so the window is final-size from the first frame and looping never
|
|
77
|
+
* collapses the page.
|
|
78
|
+
*
|
|
79
|
+
* **Accessibility:** the animated pane is `aria-hidden`; assistive tech gets
|
|
80
|
+
* the complete transcript immediately from a visually-hidden `<pre>` (no
|
|
81
|
+
* live-region spam, no half-typed announcements). The scrollable body is
|
|
82
|
+
* keyboard-focusable with a visible focus ring, and the copy button copies
|
|
83
|
+
* the joined input commands.
|
|
84
|
+
*/
|
|
85
|
+
export declare const Terminal: import("react").ForwardRefExoticComponent<TerminalProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
86
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { CopyButton } from "./copy-button.js";
|
|
6
|
+
/**
|
|
7
|
+
* Grapheme segmenter so char-by-char typing never splits a user-perceived
|
|
8
|
+
* character. Slicing by UTF-16 code units shatters emoji (✅, 🇧🇷) and complex
|
|
9
|
+
* scripts mid-glyph; segmenting by grapheme types each cluster as one unit.
|
|
10
|
+
* Null on platforms without `Intl.Segmenter`, where we fall back to code
|
|
11
|
+
* points (still safe for surrogate pairs).
|
|
12
|
+
*/
|
|
13
|
+
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl
|
|
14
|
+
? new Intl.Segmenter(undefined, { granularity: "grapheme" })
|
|
15
|
+
: null;
|
|
16
|
+
function segmentGraphemes(text) {
|
|
17
|
+
if (graphemeSegmenter) {
|
|
18
|
+
return Array.from(graphemeSegmenter.segment(text), (segment) => segment.segment);
|
|
19
|
+
}
|
|
20
|
+
return Array.from(text);
|
|
21
|
+
}
|
|
22
|
+
const DEFAULT_TYPING_SPEED = 30;
|
|
23
|
+
const DEFAULT_LOOP_DELAY = 2000;
|
|
24
|
+
const DEFAULT_INPUT_DELAY = 400;
|
|
25
|
+
const DEFAULT_OUTPUT_DELAY = 150;
|
|
26
|
+
/**
|
|
27
|
+
* Fixed (not per-instance) keyframe names are safe here because every
|
|
28
|
+
* instance declares the exact same frames — later identical declarations are
|
|
29
|
+
* no-ops. Output lines rise-and-fade in; `both` keeps them visible after the
|
|
30
|
+
* animation so finished lines never flicker. The blinking cursor reuses the
|
|
31
|
+
* theme's `animate-caret-blink` utility.
|
|
32
|
+
*/
|
|
33
|
+
const TERMINAL_KEYFRAMES = "@keyframes cronus-terminal-fade{from{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}";
|
|
34
|
+
function finitePositive(value, fallback) {
|
|
35
|
+
return Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One rendered line. Input lines carry the prompt in `text-fg-tertiary` and
|
|
39
|
+
* the command in `text-fg`; output lines print flush-left in
|
|
40
|
+
* `text-fg-secondary`, matching a real shell.
|
|
41
|
+
*/
|
|
42
|
+
function TerminalRow({ line, prompt, typedChars, showCursor = false, reveal = false, }) {
|
|
43
|
+
const isInput = line.type === "input";
|
|
44
|
+
const graphemes = useMemo(() => segmentGraphemes(line.text), [line.text]);
|
|
45
|
+
const shown = typedChars === undefined ? line.text : graphemes.slice(0, typedChars).join("");
|
|
46
|
+
return (_jsxs("div", { "data-slot": "terminal-line", "data-line-type": line.type, className: cn("flex gap-2", !isInput &&
|
|
47
|
+
reveal &&
|
|
48
|
+
"[animation:cronus-terminal-fade_240ms_ease-out_both] motion-reduce:[animation:none]"), children: [isInput ? (_jsx("span", { "data-slot": "terminal-prompt", className: "select-none text-fg-tertiary", children: prompt })) : null, _jsxs("span", { className: cn("min-w-0 flex-1 whitespace-pre-wrap break-words", isInput ? "text-fg" : "text-fg-secondary"), children: [shown, showCursor ? (_jsx("span", { "data-slot": "terminal-cursor", className: "ml-px inline-block h-[1.1em] w-[0.55em] translate-y-[0.18em] rounded-[1px] bg-fg animate-caret-blink" })) : null] })] }));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* An animated terminal window that replays a scripted shell session. Input
|
|
52
|
+
* lines type in char-by-char behind a `$` prompt with a blinking block
|
|
53
|
+
* cursor; output lines fade in whole after a beat of "execution time". The
|
|
54
|
+
* script is driven by a single chain of `setTimeout`s (one live timer at any
|
|
55
|
+
* moment, fully cleaned up on unmount/restart) that advances a tiny
|
|
56
|
+
* `{ revealed, typedChars }` state — no per-frame work, no layout thrash.
|
|
57
|
+
*
|
|
58
|
+
* **SSR-safe:** the server (and the hydration pass) renders the *finished*
|
|
59
|
+
* transcript, so no-JS readers and crawlers see the real content and there is
|
|
60
|
+
* no hydration mismatch. A layout effect flips to the animated state before
|
|
61
|
+
* first paint, so animated visitors never see a flash of the full transcript.
|
|
62
|
+
*
|
|
63
|
+
* **Reduced motion:** `prefers-reduced-motion` (or
|
|
64
|
+
* {@link TerminalProps.motionPreference} `"never"`) renders everything
|
|
65
|
+
* instantly — no typing, no cursor, no fades — and the preference is tracked
|
|
66
|
+
* live via `matchMedia`.
|
|
67
|
+
*
|
|
68
|
+
* **No layout shift:** an invisible copy of the finished transcript sits
|
|
69
|
+
* in-flow as a sizer and the animation plays in an absolutely-positioned
|
|
70
|
+
* overlay, so the window is final-size from the first frame and looping never
|
|
71
|
+
* collapses the page.
|
|
72
|
+
*
|
|
73
|
+
* **Accessibility:** the animated pane is `aria-hidden`; assistive tech gets
|
|
74
|
+
* the complete transcript immediately from a visually-hidden `<pre>` (no
|
|
75
|
+
* live-region spam, no half-typed announcements). The scrollable body is
|
|
76
|
+
* keyboard-focusable with a visible focus ring, and the copy button copies
|
|
77
|
+
* the joined input commands.
|
|
78
|
+
*/
|
|
79
|
+
export const Terminal = forwardRef(({ lines, title, chrome = true, prompt = "$", typingSpeed = DEFAULT_TYPING_SPEED, loop = false, loopDelay = DEFAULT_LOOP_DELAY, copyButton = true, motionPreference = "respect", className, ...props }, ref) => {
|
|
80
|
+
const [mounted, setMounted] = useState(false);
|
|
81
|
+
const [reducedMotion, setReducedMotion] = useState(false);
|
|
82
|
+
const [progress, setProgress] = useState({ revealed: 0, typedChars: 0 });
|
|
83
|
+
const safeTypingSpeed = Math.max(finitePositive(typingSpeed, DEFAULT_TYPING_SPEED), 1);
|
|
84
|
+
const safeLoopDelay = finitePositive(loopDelay, DEFAULT_LOOP_DELAY);
|
|
85
|
+
// Content signature: identity-stable across parent re-renders (an inline
|
|
86
|
+
// `lines={[...]}` literal must NOT restart the session every render), yet
|
|
87
|
+
// changes whenever the script's content actually changes.
|
|
88
|
+
const signature = useMemo(() => lines.map((line) => `${line.type}${line.text}${line.delay ?? ""}`).join(""), [lines]);
|
|
89
|
+
// The engine reads lines through a ref at tick time so a same-content,
|
|
90
|
+
// new-identity array never restarts (nor stales) a running session. This
|
|
91
|
+
// effect is declared BEFORE the engine effect so the ref is fresh by the
|
|
92
|
+
// time a signature change re-runs the script.
|
|
93
|
+
const linesRef = useRef(lines);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
linesRef.current = lines;
|
|
96
|
+
});
|
|
97
|
+
// Mount + reduced-motion resolve in ONE layout effect (before first
|
|
98
|
+
// client paint): the SSR/hydration render shows the finished transcript,
|
|
99
|
+
// and by the time the browser paints we already know whether to animate —
|
|
100
|
+
// reduced-motion visitors never see content clear, animated visitors
|
|
101
|
+
// never see it flash.
|
|
102
|
+
useLayoutEffect(() => {
|
|
103
|
+
setMounted(true);
|
|
104
|
+
if (typeof window.matchMedia !== "function")
|
|
105
|
+
return;
|
|
106
|
+
const query = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
107
|
+
setReducedMotion(query.matches);
|
|
108
|
+
const onChange = (event) => setReducedMotion(event.matches);
|
|
109
|
+
query.addEventListener("change", onChange);
|
|
110
|
+
return () => query.removeEventListener("change", onChange);
|
|
111
|
+
}, []);
|
|
112
|
+
const animate = motionPreference === "never"
|
|
113
|
+
? false
|
|
114
|
+
: motionPreference === "always"
|
|
115
|
+
? mounted
|
|
116
|
+
: mounted && !reducedMotion;
|
|
117
|
+
// The script engine: a chain of setTimeouts advancing one shared timer.
|
|
118
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: `signature` stands in for `lines` (restart on content change, not identity change); the line data itself is read from `linesRef` at tick time.
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (!animate)
|
|
121
|
+
return;
|
|
122
|
+
let disposed = false;
|
|
123
|
+
let timer;
|
|
124
|
+
const run = (index) => {
|
|
125
|
+
if (disposed)
|
|
126
|
+
return;
|
|
127
|
+
const script = linesRef.current;
|
|
128
|
+
setProgress({ revealed: Math.min(index, script.length), typedChars: 0 });
|
|
129
|
+
if (index >= script.length) {
|
|
130
|
+
if (loop && script.length > 0) {
|
|
131
|
+
timer = setTimeout(() => run(0), safeLoopDelay);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const line = script[index];
|
|
136
|
+
if (!line)
|
|
137
|
+
return;
|
|
138
|
+
const wait = line.delay ?? (line.type === "input" ? DEFAULT_INPUT_DELAY : DEFAULT_OUTPUT_DELAY);
|
|
139
|
+
if (line.type === "output") {
|
|
140
|
+
// Outputs reveal atomically after their delay; the fade is CSS.
|
|
141
|
+
timer = setTimeout(() => run(index + 1), wait);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const graphemes = segmentGraphemes(line.text);
|
|
145
|
+
const typeChar = (count) => {
|
|
146
|
+
if (disposed)
|
|
147
|
+
return;
|
|
148
|
+
setProgress({ revealed: index, typedChars: count });
|
|
149
|
+
if (count >= graphemes.length) {
|
|
150
|
+
run(index + 1);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
timer = setTimeout(() => typeChar(count + 1), safeTypingSpeed);
|
|
154
|
+
};
|
|
155
|
+
timer = setTimeout(() => typeChar(graphemes.length > 0 ? 1 : 0), wait);
|
|
156
|
+
};
|
|
157
|
+
run(0);
|
|
158
|
+
return () => {
|
|
159
|
+
disposed = true;
|
|
160
|
+
if (timer !== undefined)
|
|
161
|
+
clearTimeout(timer);
|
|
162
|
+
};
|
|
163
|
+
}, [animate, signature, loop, safeLoopDelay, safeTypingSpeed]);
|
|
164
|
+
const totalLines = lines.length;
|
|
165
|
+
const revealedCount = animate ? Math.min(progress.revealed, totalLines) : totalLines;
|
|
166
|
+
const activeLine = animate ? lines[progress.revealed] : undefined;
|
|
167
|
+
const finished = revealedCount >= totalLines;
|
|
168
|
+
const copyValue = useMemo(() => lines
|
|
169
|
+
.filter((line) => line.type === "input")
|
|
170
|
+
.map((line) => line.text)
|
|
171
|
+
.join("\n"), [lines]);
|
|
172
|
+
const showCopy = copyButton && copyValue.length > 0;
|
|
173
|
+
const transcript = useMemo(() => lines
|
|
174
|
+
.map((line) => (line.type === "input" ? `${prompt} ${line.text}` : line.text))
|
|
175
|
+
.join("\n"), [lines, prompt]);
|
|
176
|
+
const regionLabel = title ? `Terminal, ${title}` : "Terminal";
|
|
177
|
+
return (_jsxs("div", { ref: ref, "data-slot": "terminal", "data-state": !animate ? "static" : finished ? "done" : "animating", className: cn("overflow-hidden rounded-xl border border-border bg-surface-inset text-fg shadow-sm", className), ...props, children: [_jsx("style", { children: TERMINAL_KEYFRAMES }), chrome ? (_jsxs("div", { "data-slot": "terminal-chrome", className: "flex items-center gap-2 border-b border-border bg-surface-raised px-4 py-2.5", children: [_jsxs("div", { "aria-hidden": "true", className: "flex shrink-0 items-center gap-1.5", children: [_jsx("span", { className: "size-2.5 rounded-full bg-error/80" }), _jsx("span", { className: "size-2.5 rounded-full bg-warning/80" }), _jsx("span", { className: "size-2.5 rounded-full bg-success/80" })] }), _jsx("span", { "data-slot": "terminal-title", className: "min-w-0 flex-1 select-none truncate text-center text-xs font-medium text-fg-tertiary", children: title }), showCopy ? (_jsx(CopyButton, { value: copyValue, size: "icon-sm", "aria-label": "Copy commands", className: "-mr-1.5 shrink-0" })) : (_jsx("span", { "aria-hidden": "true", className: "w-10 shrink-0" }))] })) : null, _jsxs("div", { className: "relative", children: [!chrome && showCopy ? (_jsx(CopyButton, { value: copyValue, size: "icon-sm", "aria-label": "Copy commands", className: "absolute right-2 top-2 z-10 shrink-0 bg-surface-overlay/80 backdrop-blur-sm" })) : null, _jsxs("section", { "data-slot": "terminal-body",
|
|
178
|
+
// biome-ignore lint/a11y/noNoninteractiveTabindex: a scrollable region is intentionally focusable so keyboard users can scroll it.
|
|
179
|
+
tabIndex: 0, "aria-label": regionLabel, className: "relative overflow-auto font-mono text-sm leading-relaxed tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", children: [_jsx("pre", { "data-slot": "terminal-transcript", className: "sr-only", children: transcript }), _jsxs("div", { "aria-hidden": "true", className: "relative p-4", children: [_jsx("div", { "data-slot": "terminal-sizer", className: "invisible", children: lines.map((line, index) => (_jsx(TerminalRow, { line: line, prompt: prompt }, index))) }), _jsxs("div", { "data-slot": "terminal-screen", className: "absolute inset-0 overflow-hidden p-4", children: [lines.slice(0, revealedCount).map((line, index) => (_jsx(TerminalRow, { line: line, prompt: prompt, reveal: animate }, index))), activeLine?.type === "input" ? (_jsx(TerminalRow, { line: activeLine, prompt: prompt, typedChars: progress.typedChars, showCursor: true })) : null] })] })] })] })] }));
|
|
180
|
+
});
|
|
181
|
+
Terminal.displayName = "Terminal";
|
|
182
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** How the text is broken up before staggering the enter animation. */
|
|
2
|
+
export type TextEffectPer = "word" | "char";
|
|
3
|
+
/** Which per-unit enter animation plays. */
|
|
4
|
+
export type TextEffectPreset = "fade" | "blur" | "slide";
|
|
5
|
+
/** When the reveal fires. */
|
|
6
|
+
export type TextEffectTrigger = "mount" | "inView";
|
|
7
|
+
export interface TextEffectProps extends Omit<React.HTMLAttributes<HTMLElement>, "children"> {
|
|
8
|
+
/**
|
|
9
|
+
* The text to reveal. Must be a plain string so it can be split into words
|
|
10
|
+
* or characters — pass interpolated values as a single template string, not
|
|
11
|
+
* as child nodes.
|
|
12
|
+
*/
|
|
13
|
+
children: string;
|
|
14
|
+
/** Split granularity. `"word"` (default) staggers words; `"char"` staggers letters. */
|
|
15
|
+
per?: TextEffectPer;
|
|
16
|
+
/** Which enter animation each unit plays. Defaults to `"blur"`. */
|
|
17
|
+
preset?: TextEffectPreset;
|
|
18
|
+
/**
|
|
19
|
+
* The rendered wrapper element/tag (e.g. `"h1"`, `"span"`). Defaults to `"p"`.
|
|
20
|
+
* The wrapper itself is not animated — it carries the accessible label while
|
|
21
|
+
* inner `motion.span`s do the animating.
|
|
22
|
+
*/
|
|
23
|
+
as?: React.ElementType;
|
|
24
|
+
/** Delay (seconds) before the first unit animates. Defaults to `0`. */
|
|
25
|
+
delay?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Time (seconds) between consecutive units. Defaults to `0.04` for words and
|
|
28
|
+
* `0.02` for characters.
|
|
29
|
+
*/
|
|
30
|
+
stagger?: number;
|
|
31
|
+
/** Per-unit animation duration (seconds). Defaults to `0.4`. */
|
|
32
|
+
duration?: number;
|
|
33
|
+
/**
|
|
34
|
+
* `"inView"` (default) animates once when the element scrolls into view;
|
|
35
|
+
* `"mount"` animates immediately on mount.
|
|
36
|
+
*/
|
|
37
|
+
trigger?: TextEffectTrigger;
|
|
38
|
+
/**
|
|
39
|
+
* How `prefers-reduced-motion` is honoured. Defaults to `"user"` (render the
|
|
40
|
+
* text statically for users who opt out). Pass `"never"` to always play the
|
|
41
|
+
* stagger — e.g. a showcase that must demonstrate it — or `"always"` to force
|
|
42
|
+
* the static render.
|
|
43
|
+
*/
|
|
44
|
+
reducedMotion?: "user" | "always" | "never";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Reveal a string by splitting it into words or characters and staggering an
|
|
48
|
+
* enter animation across the units. Built for heros, section titles, and
|
|
49
|
+
* onboarding moments where copy should "arrive" rather than pop.
|
|
50
|
+
*
|
|
51
|
+
* **Presets** — `fade` (opacity), `blur` (opacity + a clearing 8px blur, the
|
|
52
|
+
* default and most premium-feeling), and `slide` (opacity + an 8px rise). The
|
|
53
|
+
* container drives timing via `staggerChildren`; each unit only animates its own
|
|
54
|
+
* property, so the settled state is byte-identical to plain text.
|
|
55
|
+
*
|
|
56
|
+
* **Trigger** — `inView` (default) plays the reveal once when the text scrolls
|
|
57
|
+
* into view; `mount` plays it immediately. In-view detection fires a little
|
|
58
|
+
* before the element fully enters the viewport so the motion feels anticipatory.
|
|
59
|
+
*
|
|
60
|
+
* **Accessibility** — split text is hostile to screen readers, selection, and
|
|
61
|
+
* find-in-page. So the wrapper carries `aria-label={children}` (assistive tech
|
|
62
|
+
* reads the whole string once, naturally) while the animated `motion.span` tree
|
|
63
|
+
* is marked `aria-hidden`. Sighted users see the staggered reveal; AT users get
|
|
64
|
+
* the clean string.
|
|
65
|
+
*
|
|
66
|
+
* **Reduced motion** — when the user prefers reduced motion the text renders
|
|
67
|
+
* fully visible with no blur, transform, or stagger (a single instant fade at
|
|
68
|
+
* most). Honours `prefers-reduced-motion` via {@link useReducedMotion}.
|
|
69
|
+
*/
|
|
70
|
+
export declare const TextEffect: import("react").ForwardRefExoticComponent<TextEffectProps & import("react").RefAttributes<HTMLElement>>;
|
|
71
|
+
//# sourceMappingURL=text-effect.d.ts.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { motion, useInView, useReducedMotion } from "motion/react";
|
|
4
|
+
import { forwardRef, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
/**
|
|
7
|
+
* Grapheme segmenter for `per: "char"` so user-perceived characters stay whole.
|
|
8
|
+
* Splitting by code point shatters ZWJ emoji (👨👩👧👦), flags (🇧🇷), and complex
|
|
9
|
+
* scripts; segmenting by grapheme keeps each cluster as one animated unit. Null
|
|
10
|
+
* on platforms without `Intl.Segmenter`, where we fall back to code-point split.
|
|
11
|
+
*/
|
|
12
|
+
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl
|
|
13
|
+
? new Intl.Segmenter(undefined, { granularity: "grapheme" })
|
|
14
|
+
: null;
|
|
15
|
+
/**
|
|
16
|
+
* Per-unit enter animations. Each is a {@link Variants} pair keyed `hidden` /
|
|
17
|
+
* `visible`; the container orchestrates timing via `staggerChildren`, so the
|
|
18
|
+
* per-unit `transition` only carries the easing/duration (duration is injected
|
|
19
|
+
* at runtime from the `duration` prop). All presets land on the fully-visible
|
|
20
|
+
* resting state — no residual transform/filter — so layout and text rendering
|
|
21
|
+
* are pixel-identical to plain text once the animation settles.
|
|
22
|
+
*/
|
|
23
|
+
const PRESETS = {
|
|
24
|
+
fade: {
|
|
25
|
+
hidden: { opacity: 0 },
|
|
26
|
+
visible: { opacity: 1 },
|
|
27
|
+
},
|
|
28
|
+
blur: {
|
|
29
|
+
hidden: { opacity: 0, filter: "blur(8px)" },
|
|
30
|
+
visible: { opacity: 1, filter: "blur(0px)" },
|
|
31
|
+
},
|
|
32
|
+
slide: {
|
|
33
|
+
hidden: { opacity: 0, y: 8 },
|
|
34
|
+
visible: { opacity: 1, y: 0 },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
/** Default per-unit stagger, tuned so a whole title still reads as one gesture. */
|
|
38
|
+
const DEFAULT_STAGGER = {
|
|
39
|
+
word: 0.04,
|
|
40
|
+
char: 0.02,
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Container variants: hold children hidden, then release them on a stagger.
|
|
44
|
+
* When `reduced` is set the stagger collapses to an instant, zero-delay release
|
|
45
|
+
* so reduced-motion users get fully-static text the frame after hydration.
|
|
46
|
+
*/
|
|
47
|
+
function buildContainerVariants(stagger, delay, reduced) {
|
|
48
|
+
return {
|
|
49
|
+
hidden: {},
|
|
50
|
+
visible: {
|
|
51
|
+
transition: reduced
|
|
52
|
+
? { staggerChildren: 0, delayChildren: 0, duration: 0 }
|
|
53
|
+
: { staggerChildren: stagger, delayChildren: delay },
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Split text into renderable units while keeping word boundaries intact.
|
|
59
|
+
*
|
|
60
|
+
* For `per: "word"` each token is a word and a trailing space is preserved as a
|
|
61
|
+
* separate token so wrapping/justification behave exactly like normal text. For
|
|
62
|
+
* `per: "char"` we split into words *first*, then into characters, so a word can
|
|
63
|
+
* never wrap mid-token — the word stays an inline-block group whose own letters
|
|
64
|
+
* stagger inside it.
|
|
65
|
+
*/
|
|
66
|
+
function splitText(text, per) {
|
|
67
|
+
// Split on whitespace runs but keep the separators, so multiple/explicit
|
|
68
|
+
// spaces survive round-tripping.
|
|
69
|
+
const tokens = text.split(/(\s+)/).filter((token) => token.length > 0);
|
|
70
|
+
if (per === "word") {
|
|
71
|
+
return tokens.map((token) => [token]);
|
|
72
|
+
}
|
|
73
|
+
return tokens.map((token) => /^\s+$/.test(token)
|
|
74
|
+
? [token]
|
|
75
|
+
: graphemeSegmenter
|
|
76
|
+
? Array.from(graphemeSegmenter.segment(token), (s) => s.segment)
|
|
77
|
+
: Array.from(token));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Reveal a string by splitting it into words or characters and staggering an
|
|
81
|
+
* enter animation across the units. Built for heros, section titles, and
|
|
82
|
+
* onboarding moments where copy should "arrive" rather than pop.
|
|
83
|
+
*
|
|
84
|
+
* **Presets** — `fade` (opacity), `blur` (opacity + a clearing 8px blur, the
|
|
85
|
+
* default and most premium-feeling), and `slide` (opacity + an 8px rise). The
|
|
86
|
+
* container drives timing via `staggerChildren`; each unit only animates its own
|
|
87
|
+
* property, so the settled state is byte-identical to plain text.
|
|
88
|
+
*
|
|
89
|
+
* **Trigger** — `inView` (default) plays the reveal once when the text scrolls
|
|
90
|
+
* into view; `mount` plays it immediately. In-view detection fires a little
|
|
91
|
+
* before the element fully enters the viewport so the motion feels anticipatory.
|
|
92
|
+
*
|
|
93
|
+
* **Accessibility** — split text is hostile to screen readers, selection, and
|
|
94
|
+
* find-in-page. So the wrapper carries `aria-label={children}` (assistive tech
|
|
95
|
+
* reads the whole string once, naturally) while the animated `motion.span` tree
|
|
96
|
+
* is marked `aria-hidden`. Sighted users see the staggered reveal; AT users get
|
|
97
|
+
* the clean string.
|
|
98
|
+
*
|
|
99
|
+
* **Reduced motion** — when the user prefers reduced motion the text renders
|
|
100
|
+
* fully visible with no blur, transform, or stagger (a single instant fade at
|
|
101
|
+
* most). Honours `prefers-reduced-motion` via {@link useReducedMotion}.
|
|
102
|
+
*/
|
|
103
|
+
export const TextEffect = forwardRef(({ children, per = "word", preset = "blur", as: Component = "p", delay = 0, stagger, duration = 0.4, trigger = "inView", reducedMotion = "user", className, ...props }, forwardedRef) => {
|
|
104
|
+
const localRef = useRef(null);
|
|
105
|
+
const systemReducedMotion = useReducedMotion();
|
|
106
|
+
const prefersReducedMotion = reducedMotion === "never" ? false : reducedMotion === "always" ? true : systemReducedMotion;
|
|
107
|
+
// `will-change` is only worth its GPU layer while a unit is actually moving;
|
|
108
|
+
// gating on this flag (set/cleared by the container's animation lifecycle)
|
|
109
|
+
// lets the leaf spans drop their promoted layers at rest.
|
|
110
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
111
|
+
const resolvedStagger = stagger ?? DEFAULT_STAGGER[per];
|
|
112
|
+
// Observe for the in-view trigger. We render a single DOM tree for server
|
|
113
|
+
// and client (no early reduced-motion return) so reduced motion is driven
|
|
114
|
+
// purely through animation props below — not through divergent markup.
|
|
115
|
+
const isInView = useInView(localRef, { once: true, margin: "-80px" });
|
|
116
|
+
// Reduced-motion users snap straight to `visible` (post-hydration, instantly
|
|
117
|
+
// via the zero-duration transitions); everyone else plays on mount/in-view.
|
|
118
|
+
const shouldPlay = prefersReducedMotion ? true : trigger === "mount" ? true : isInView;
|
|
119
|
+
const units = useMemo(() => splitText(children, per), [children, per]);
|
|
120
|
+
const containerVariants = useMemo(() => buildContainerVariants(resolvedStagger, delay, !!prefersReducedMotion), [resolvedStagger, delay, prefersReducedMotion]);
|
|
121
|
+
const itemVariants = PRESETS[preset];
|
|
122
|
+
const itemTransition = useMemo(() => ({ duration, ease: "easeOut" }), [duration]);
|
|
123
|
+
const setRef = (node) => {
|
|
124
|
+
localRef.current = node;
|
|
125
|
+
if (typeof forwardedRef === "function") {
|
|
126
|
+
forwardedRef(node);
|
|
127
|
+
}
|
|
128
|
+
else if (forwardedRef) {
|
|
129
|
+
forwardedRef.current = node;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
return (_jsxs(Component, { ref: setRef, "data-slot": "text-effect", className: cn(className), ...props, children: [_jsx("span", { className: "sr-only", children: children }), _jsx(motion.span, { "aria-hidden": "true",
|
|
133
|
+
// `initial` is the only variant framer renders into the SSR'd HTML, so
|
|
134
|
+
// it must be deterministic across server (reduced-motion null) and a
|
|
135
|
+
// reduced-motion client — keep it `"hidden"` unconditionally to avoid a
|
|
136
|
+
// hydration mismatch. Reduced motion is expressed by the transitions.
|
|
137
|
+
initial: "hidden", animate: shouldPlay ? "visible" : "hidden", variants: containerVariants,
|
|
138
|
+
// Drive the will-change flag from the container's animation lifecycle so
|
|
139
|
+
// the leaf spans only promote a GPU layer while motion is in flight.
|
|
140
|
+
onAnimationStart: () => setIsAnimating(true), onAnimationComplete: () => setIsAnimating(false),
|
|
141
|
+
// inline so the wrapper's own typography (line-height, alignment) is
|
|
142
|
+
// unaffected; child word-groups handle wrapping.
|
|
143
|
+
style: { display: "inline" }, children: units.map((unit, unitIndex) => {
|
|
144
|
+
const unitKey = `unit-${unitIndex}`;
|
|
145
|
+
// A whitespace-only token: render as a plain inline span so the
|
|
146
|
+
// space can break/collapse like normal text (not an inline-block).
|
|
147
|
+
if (unit.length === 1 && /^\s+$/.test(unit[0] ?? "")) {
|
|
148
|
+
return (_jsx("span", { style: { whiteSpace: "pre" }, children: unit[0] }, unitKey));
|
|
149
|
+
}
|
|
150
|
+
// For `per: "word"` the unit is a single word token; for
|
|
151
|
+
// `per: "char"` it is the word's characters. Either way wrap the
|
|
152
|
+
// group inline-block so it never breaks mid-word.
|
|
153
|
+
return (_jsx("span", { className: "inline-block", children: unit.map((piece, pieceIndex) => (_jsx(motion.span
|
|
154
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: split text pieces are positional and stable within their word.
|
|
155
|
+
, { className: "inline-block", variants: itemVariants,
|
|
156
|
+
// Reduced motion snaps instantly to `visible` (no movement);
|
|
157
|
+
// otherwise carry the easing/duration from the `duration` prop.
|
|
158
|
+
transition: prefersReducedMotion ? { duration: 0 } : itemTransition,
|
|
159
|
+
// `will-change` only while animating; the `inline-block`
|
|
160
|
+
// class (not will-change) gives transforms/filters their
|
|
161
|
+
// formatting context, so dropping the hint at rest is safe.
|
|
162
|
+
style: { willChange: isAnimating ? "transform, filter, opacity" : undefined }, children: piece }, `${unitKey}-piece-${pieceIndex}`))) }, unitKey));
|
|
163
|
+
}) })] }));
|
|
164
|
+
});
|
|
165
|
+
TextEffect.displayName = "TextEffect";
|
|
166
|
+
//# sourceMappingURL=text-effect.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TextareaHTMLAttributes } from "react";
|
|
2
|
+
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
3
|
+
invalid?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
6
|
+
//# sourceMappingURL=textarea.d.ts.map
|