@zendir/ui 0.5.0 → 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/CHANGELOG.md +20 -0
- package/README.md +640 -631
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/index.js +17 -221
- package/dist/react/3d/CesiumCaptureSource.d.ts +0 -1
- package/dist/react/3d/CesiumCaptureSource.js +364 -283
- package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
- package/dist/react/3d/ZenSpace3D.d.ts +2 -3
- package/dist/react/3d/ZenSpace3D.js +1681 -1237
- package/dist/react/3d/ZenSpace3D.js.map +1 -1
- package/dist/react/3d/ZenSpace3DCesium.d.ts +0 -1
- package/dist/react/3d/ZenSpace3DCesium.js +513 -560
- package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
- package/dist/react/3d/ZenSpace3DShaders.js +61 -66
- package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
- package/dist/react/3d/ZenSpace3DTypes.d.ts +19 -20
- package/dist/react/3d/ZenSpace3DUtils.d.ts +0 -1
- package/dist/react/3d/ZenSpace3DUtils.js +37 -24
- package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
- package/dist/react/3d/capturePngAnalysis.js +42 -36
- package/dist/react/3d/capturePngAnalysis.js.map +1 -1
- package/dist/react/3d/index.d.ts +3 -3
- package/dist/react/3d/index.js +5 -53
- package/dist/react/3d/threeLoader.d.ts +1 -1
- package/dist/react/3d/threeLoader.js +23 -18
- package/dist/react/3d/threeLoader.js.map +1 -1
- package/dist/react/astro/ClassificationBanner.d.ts +2 -3
- package/dist/react/astro/ClassificationBanner.js +95 -79
- package/dist/react/astro/ClassificationBanner.js.map +1 -1
- package/dist/react/astro/GlobalStatusBar.d.ts +0 -1
- package/dist/react/astro/GlobalStatusBar.js +157 -163
- package/dist/react/astro/GlobalStatusBar.js.map +1 -1
- package/dist/react/astro/MissionClock.d.ts +7 -8
- package/dist/react/astro/MissionClock.js +377 -400
- package/dist/react/astro/MissionClock.js.map +1 -1
- package/dist/react/astro/MonitoringIcon.d.ts +1 -2
- package/dist/react/astro/MonitoringIcon.js +422 -358
- package/dist/react/astro/MonitoringIcon.js.map +1 -1
- package/dist/react/astro/Notification.d.ts +1 -2
- package/dist/react/astro/Notification.js +229 -126
- package/dist/react/astro/Notification.js.map +1 -1
- package/dist/react/astro/Progress.d.ts +0 -1
- package/dist/react/astro/Progress.js +199 -141
- package/dist/react/astro/Progress.js.map +1 -1
- package/dist/react/astro/SimulationControls.d.ts +3 -4
- package/dist/react/astro/SimulationControls.js +596 -650
- package/dist/react/astro/SimulationControls.js.map +1 -1
- package/dist/react/astro/StatusIndicator.d.ts +0 -1
- package/dist/react/astro/StatusIndicator.js +236 -170
- package/dist/react/astro/StatusIndicator.js.map +1 -1
- package/dist/react/astro/UnifiedTimeline.d.ts +9 -10
- package/dist/react/astro/UnifiedTimeline.js +2345 -2392
- package/dist/react/astro/UnifiedTimeline.js.map +1 -1
- package/dist/react/astro/index.d.ts +5 -5
- package/dist/react/astro/index.js +1 -25
- package/dist/react/cards/AccessCard.d.ts +0 -1
- package/dist/react/cards/AccessCard.js +471 -405
- package/dist/react/cards/AccessCard.js.map +1 -1
- package/dist/react/cards/OrbitCard.d.ts +0 -1
- package/dist/react/cards/OrbitCard.js +487 -364
- package/dist/react/cards/OrbitCard.js.map +1 -1
- package/dist/react/cards/SpacecraftCard.d.ts +0 -1
- package/dist/react/cards/SpacecraftCard.js +813 -925
- package/dist/react/cards/SpacecraftCard.js.map +1 -1
- package/dist/react/cards/TelemetryCard.d.ts +0 -1
- package/dist/react/cards/TelemetryCard.js +1055 -732
- package/dist/react/cards/TelemetryCard.js.map +1 -1
- package/dist/react/cards/TelemetryStreamCard.d.ts +0 -1
- package/dist/react/cards/TelemetryStreamCard.js +323 -297
- package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
- package/dist/react/cards/index.d.ts +1 -1
- package/dist/react/cards/index.js +1 -8
- package/dist/react/charts/GroundTrackMap.d.ts +6 -7
- package/dist/react/charts/GroundTrackMap.js +1377 -1256
- package/dist/react/charts/GroundTrackMap.js.map +1 -1
- package/dist/react/charts/GroundTrackMapLeaflet.d.ts +1 -2
- package/dist/react/charts/GroundTrackMapLeaflet.js +1065 -987
- package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
- package/dist/react/charts/groundTrackMapLeafletTiles.js +34 -25
- package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
- package/dist/react/charts/groundTrackMapLeafletUtils.js +70 -61
- package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
- package/dist/react/charts/index.d.ts +1 -1
- package/dist/react/charts/index.js +7 -100
- package/dist/react/charts/unified/AstroChart.d.ts +1 -2
- package/dist/react/charts/unified/AstroChart.js +1331 -1411
- package/dist/react/charts/unified/AstroChart.js.map +1 -1
- package/dist/react/charts/unified/PowerOverviewChart.d.ts +3 -3
- package/dist/react/charts/unified/PowerOverviewChart.js +495 -478
- package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
- package/dist/react/charts/unified/domain.d.ts +12 -13
- package/dist/react/charts/unified/domain.js +3999 -3145
- package/dist/react/charts/unified/domain.js.map +1 -1
- package/dist/react/charts/unified/generators.d.ts +3 -4
- package/dist/react/charts/unified/generators.js +561 -498
- package/dist/react/charts/unified/generators.js.map +1 -1
- package/dist/react/charts/unified/index.d.ts +1 -1
- package/dist/react/charts/unified/presets.d.ts +14 -15
- package/dist/react/charts/unified/presets.js +857 -994
- package/dist/react/charts/unified/presets.js.map +1 -1
- package/dist/react/charts/unified/sync.d.ts +2 -3
- package/dist/react/charts/unified/sync.js +229 -195
- package/dist/react/charts/unified/sync.js.map +1 -1
- package/dist/react/charts/unified/theme.d.ts +11 -12
- package/dist/react/charts/unified/theme.js +606 -642
- package/dist/react/charts/unified/theme.js.map +1 -1
- package/dist/react/charts/unified/types.d.ts +32 -33
- package/dist/react/charts/unified/useChartStream.d.ts +1 -2
- package/dist/react/charts/unified/useChartStream.js +203 -216
- package/dist/react/charts/unified/useChartStream.js.map +1 -1
- package/dist/react/chatgpt/AppCard.d.ts +1 -2
- package/dist/react/chatgpt/index.d.ts +7 -7
- package/dist/react/chatgpt/index.js +160 -139
- package/dist/react/chatgpt/index.js.map +1 -1
- package/dist/react/context/CategoryContext.d.ts +0 -1
- package/dist/react/context/CategoryContext.js +78 -29
- package/dist/react/context/CategoryContext.js.map +1 -1
- package/dist/react/context/DisplaySettingsContext.d.ts +1 -2
- package/dist/react/context/DisplaySettingsContext.js +205 -156
- package/dist/react/context/DisplaySettingsContext.js.map +1 -1
- package/dist/react/context/SpatialSelectionContext.d.ts +0 -1
- package/dist/react/context/SpatialSelectionContext.js +36 -7
- package/dist/react/context/SpatialSelectionContext.js.map +1 -1
- package/dist/react/core/data/DataTable.d.ts +3 -4
- package/dist/react/core/data/DataTable.js +473 -440
- package/dist/react/core/data/DataTable.js.map +1 -1
- package/dist/react/core/data/DataValue.d.ts +4 -5
- package/dist/react/core/data/DataValue.js +605 -571
- package/dist/react/core/data/DataValue.js.map +1 -1
- package/dist/react/core/data/propertyConfig.d.ts +1 -2
- package/dist/react/core/data/propertyConfig.js +446 -382
- package/dist/react/core/data/propertyConfig.js.map +1 -1
- package/dist/react/core/display/AstroIcon.d.ts +4 -5
- package/dist/react/core/display/AstroIcon.js +339 -429
- package/dist/react/core/display/AstroIcon.js.map +1 -1
- package/dist/react/core/display/Badge.d.ts +2 -3
- package/dist/react/core/display/Badge.js +131 -131
- package/dist/react/core/display/Badge.js.map +1 -1
- package/dist/react/core/display/CardHeader.d.ts +0 -1
- package/dist/react/core/display/CardHeader.js +398 -311
- package/dist/react/core/display/CardHeader.js.map +1 -1
- package/dist/react/core/display/Container.d.ts +2 -3
- package/dist/react/core/display/Container.js +640 -668
- package/dist/react/core/display/Container.js.map +1 -1
- package/dist/react/core/display/CopyButton.d.ts +1 -2
- package/dist/react/core/display/CopyButton.js +158 -101
- package/dist/react/core/display/CopyButton.js.map +1 -1
- package/dist/react/core/display/GlassCard.d.ts +3 -4
- package/dist/react/core/display/GlassCard.js +416 -369
- package/dist/react/core/display/GlassCard.js.map +1 -1
- package/dist/react/core/display/HeaderIconWithStatus.d.ts +0 -1
- package/dist/react/core/display/HeaderIconWithStatus.js +152 -152
- package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
- package/dist/react/core/display/Icon.d.ts +2 -3
- package/dist/react/core/display/Icon.js +172 -143
- package/dist/react/core/display/Icon.js.map +1 -1
- package/dist/react/core/display/Typography.d.ts +24 -25
- package/dist/react/core/display/Typography.js +360 -178
- package/dist/react/core/display/Typography.js.map +1 -1
- package/dist/react/core/feedback/ConfirmDialog.d.ts +1 -2
- package/dist/react/core/feedback/ConfirmDialog.js +343 -304
- package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
- package/dist/react/core/feedback/Dialog.d.ts +2 -3
- package/dist/react/core/feedback/Dialog.js +189 -197
- package/dist/react/core/feedback/Dialog.js.map +1 -1
- package/dist/react/core/feedback/Toast.d.ts +2 -3
- package/dist/react/core/feedback/Toast.js +346 -207
- package/dist/react/core/feedback/Toast.js.map +1 -1
- package/dist/react/core/index.d.ts +26 -26
- package/dist/react/core/index.js +7 -119
- package/dist/react/core/inputs/Button.d.ts +2 -3
- package/dist/react/core/inputs/Button.js +281 -304
- package/dist/react/core/inputs/Button.js.map +1 -1
- package/dist/react/core/inputs/Checkbox.d.ts +2 -3
- package/dist/react/core/inputs/Checkbox.js +139 -127
- package/dist/react/core/inputs/Checkbox.js.map +1 -1
- package/dist/react/core/inputs/Input.d.ts +3 -4
- package/dist/react/core/inputs/Input.js +277 -285
- package/dist/react/core/inputs/Input.js.map +1 -1
- package/dist/react/core/inputs/LimitsBar.d.ts +1 -2
- package/dist/react/core/inputs/LimitsBar.js +271 -196
- package/dist/react/core/inputs/LimitsBar.js.map +1 -1
- package/dist/react/core/inputs/NumberInput.d.ts +2 -3
- package/dist/react/core/inputs/NumberInput.js +531 -503
- package/dist/react/core/inputs/NumberInput.js.map +1 -1
- package/dist/react/core/inputs/PinInput.d.ts +2 -3
- package/dist/react/core/inputs/PinInput.js +224 -207
- package/dist/react/core/inputs/PinInput.js.map +1 -1
- package/dist/react/core/inputs/Select.d.ts +1 -2
- package/dist/react/core/inputs/Select.js +298 -299
- package/dist/react/core/inputs/Select.js.map +1 -1
- package/dist/react/core/inputs/Toggle.d.ts +2 -3
- package/dist/react/core/inputs/Toggle.js +142 -148
- package/dist/react/core/inputs/Toggle.js.map +1 -1
- package/dist/react/core/layout/Box.d.ts +3 -4
- package/dist/react/core/layout/Box.js +118 -122
- package/dist/react/core/layout/Box.js.map +1 -1
- package/dist/react/core/layout/Center.d.ts +0 -1
- package/dist/react/core/layout/Center.js +45 -32
- package/dist/react/core/layout/Center.js.map +1 -1
- package/dist/react/core/layout/Divider.d.ts +1 -2
- package/dist/react/core/layout/Divider.js +112 -106
- package/dist/react/core/layout/Divider.js.map +1 -1
- package/dist/react/core/layout/Flex.d.ts +4 -5
- package/dist/react/core/layout/Flex.js +120 -124
- package/dist/react/core/layout/Flex.js.map +1 -1
- package/dist/react/core/layout/Grid.d.ts +5 -6
- package/dist/react/core/layout/Grid.js +131 -138
- package/dist/react/core/layout/Grid.js.map +1 -1
- package/dist/react/core/layout/Spacer.d.ts +0 -1
- package/dist/react/core/layout/Spacer.js +36 -29
- package/dist/react/core/layout/Spacer.js.map +1 -1
- package/dist/react/core/layout/Stack.d.ts +4 -5
- package/dist/react/core/layout/Stack.js +127 -70
- package/dist/react/core/layout/Stack.js.map +1 -1
- package/dist/react/core/layout/responsive.d.ts +1 -2
- package/dist/react/core/layout/responsive.js +25 -19
- package/dist/react/core/layout/responsive.js.map +1 -1
- package/dist/react/core/layout/useBreakpoint.d.ts +1 -1
- package/dist/react/core/layout/useBreakpoint.js +119 -66
- package/dist/react/core/layout/useBreakpoint.js.map +1 -1
- package/dist/react/core/navigation/AppBar.d.ts +1 -2
- package/dist/react/core/navigation/AppBar.js +827 -805
- package/dist/react/core/navigation/AppBar.js.map +1 -1
- package/dist/react/core/navigation/Pagination.d.ts +2 -3
- package/dist/react/core/navigation/Pagination.js +207 -187
- package/dist/react/core/navigation/Pagination.js.map +1 -1
- package/dist/react/core/navigation/SideNav.d.ts +5 -6
- package/dist/react/core/navigation/SideNav.js +855 -629
- package/dist/react/core/navigation/SideNav.js.map +1 -1
- package/dist/react/core/navigation/Tabs.d.ts +0 -1
- package/dist/react/core/navigation/Tabs.js +113 -119
- package/dist/react/core/navigation/Tabs.js.map +1 -1
- package/dist/react/core/overlays/Popover.d.ts +2 -3
- package/dist/react/core/overlays/Popover.js +303 -282
- package/dist/react/core/overlays/Popover.js.map +1 -1
- package/dist/react/core/overlays/SidePanel.d.ts +1 -2
- package/dist/react/core/overlays/SidePanel.js +217 -212
- package/dist/react/core/overlays/SidePanel.js.map +1 -1
- package/dist/react/core/overlays/Tooltip.d.ts +1 -2
- package/dist/react/core/overlays/Tooltip.js +170 -176
- package/dist/react/core/overlays/Tooltip.js.map +1 -1
- package/dist/react/core/widgets/ActivityPlanner.d.ts +0 -1
- package/dist/react/core/widgets/ActivityPlanner.js +855 -517
- package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
- package/dist/react/core/widgets/Capture.d.ts +2 -3
- package/dist/react/core/widgets/Capture.js +965 -779
- package/dist/react/core/widgets/Capture.js.map +1 -1
- package/dist/react/core/widgets/ChatPanel.d.ts +16 -17
- package/dist/react/core/widgets/ChatPanel.js +1734 -1034
- package/dist/react/core/widgets/ChatPanel.js.map +1 -1
- package/dist/react/core/widgets/ColorPickerPanel.d.ts +0 -1
- package/dist/react/core/widgets/ColorPickerPanel.js +298 -287
- package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
- package/dist/react/core/widgets/CommandBuilder.d.ts +2 -3
- package/dist/react/core/widgets/CommandBuilder.js +624 -516
- package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
- package/dist/react/core/widgets/ConnectionForm.d.ts +2 -3
- package/dist/react/core/widgets/ConnectionForm.js +528 -492
- package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
- package/dist/react/core/widgets/FileExplorer.d.ts +3 -4
- package/dist/react/core/widgets/FileExplorer.js +617 -505
- package/dist/react/core/widgets/FileExplorer.js.map +1 -1
- package/dist/react/core/widgets/HexViewer.d.ts +2 -3
- package/dist/react/core/widgets/HexViewer.js +1353 -1091
- package/dist/react/core/widgets/HexViewer.js.map +1 -1
- package/dist/react/core/widgets/ImageFrame.d.ts +1 -2
- package/dist/react/core/widgets/ImageFrame.js +230 -193
- package/dist/react/core/widgets/ImageFrame.js.map +1 -1
- package/dist/react/core/widgets/ImageGallery.d.ts +2 -1
- package/dist/react/core/widgets/ImageGallery.js +380 -314
- package/dist/react/core/widgets/ImageGallery.js.map +1 -1
- package/dist/react/core/widgets/ImagePanel.d.ts +0 -1
- package/dist/react/core/widgets/ImagePanel.js +110 -101
- package/dist/react/core/widgets/ImagePanel.js.map +1 -1
- package/dist/react/core/widgets/LogViewer.d.ts +2 -3
- package/dist/react/core/widgets/LogViewer.js +711 -607
- package/dist/react/core/widgets/LogViewer.js.map +1 -1
- package/dist/react/core/widgets/MessageStream.d.ts +3 -4
- package/dist/react/core/widgets/MessageStream.js +514 -444
- package/dist/react/core/widgets/MessageStream.js.map +1 -1
- package/dist/react/core/widgets/MissionCalendar.d.ts +3 -4
- package/dist/react/core/widgets/MissionCalendar.js +1488 -1020
- package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
- package/dist/react/core/widgets/PacketViewer.d.ts +2 -3
- package/dist/react/core/widgets/PacketViewer.js +550 -421
- package/dist/react/core/widgets/PacketViewer.js.map +1 -1
- package/dist/react/core/widgets/capture-placeholder.png.js +6 -5
- package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -1
- package/dist/react/hooks/index.d.ts +5 -5
- package/dist/react/hooks/useAccessWindows.d.ts +0 -1
- package/dist/react/hooks/useCompactMode.d.ts +1 -1
- package/dist/react/hooks/useCompactMode.js +104 -58
- package/dist/react/hooks/useCompactMode.js.map +1 -1
- package/dist/react/hooks/useGroundTrackHistory.d.ts +0 -1
- package/dist/react/hooks/useSimulationScene.d.ts +1 -2
- package/dist/react/hooks/useSimulationScene.js +481 -374
- package/dist/react/hooks/useSimulationScene.js.map +1 -1
- package/dist/react/index.d.ts +3 -3
- package/dist/react/panels/LayerControlPanel.d.ts +1 -2
- package/dist/react/panels/LayerControlPanel.js +223 -180
- package/dist/react/panels/LayerControlPanel.js.map +1 -1
- package/dist/react/panels/ObjectInventoryPanel.d.ts +2 -3
- package/dist/react/panels/ObjectInventoryPanel.js +315 -250
- package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
- package/dist/react/panels/index.d.ts +1 -1
- package/dist/react/panels/index.js +1 -6
- package/dist/react/shared/ErrorBoundary.d.ts +1 -2
- package/dist/react/shared/ErrorBoundary.js +170 -139
- package/dist/react/shared/ErrorBoundary.js.map +1 -1
- package/dist/react/shared/Skeleton.d.ts +1 -2
- package/dist/react/shared/Skeleton.js +300 -301
- package/dist/react/shared/Skeleton.js.map +1 -1
- package/dist/react/theme/ThemeProvider.d.ts +2 -321
- package/dist/react/theme/ThemeProvider.js +312 -939
- package/dist/react/theme/ThemeProvider.js.map +1 -1
- package/dist/react/theme/cardAccent.d.ts +1 -2
- package/dist/react/theme/cardAccent.js +196 -126
- package/dist/react/theme/cardAccent.js.map +1 -1
- package/dist/react/theme/config.d.ts +0 -1
- package/dist/react/theme/config.js +47 -25
- package/dist/react/theme/config.js.map +1 -1
- package/dist/react/theme/index.d.ts +2 -2
- package/dist/react/theme/index.js +1 -16
- package/dist/react/theme/types.d.ts +332 -0
- package/dist/react/theme/types.js +39 -0
- package/dist/react/theme/types.js.map +1 -0
- package/dist/react/types.d.ts +8 -8
- package/dist/react/types.js +147 -47
- package/dist/react/types.js.map +1 -1
- package/dist/react/utils/categoryPalette.d.ts +0 -1
- package/dist/react/utils/categoryPalette.js +91 -102
- package/dist/react/utils/categoryPalette.js.map +1 -1
- package/dist/react/utils/index.d.ts +5 -5
- package/dist/react/utils/index.js +457 -371
- package/dist/react/utils/index.js.map +1 -1
- package/dist/react/visualizations/EclipseTimerCard.d.ts +0 -1
- package/dist/react/visualizations/LinkBudgetCard.d.ts +0 -1
- package/dist/react/visualizations/NavBallCard.d.ts +0 -1
- package/dist/react/visualizations/PropulsionCard.d.ts +1 -2
- package/dist/react/visualizations/SensorFootprintCard.d.ts +1 -2
- package/dist/react/visualizations/ThermalHeatmapCard.d.ts +0 -1
- package/dist/react/visualizations/index.d.ts +3 -3
- package/dist/react.d.ts +2 -1
- package/dist/react.js +17 -221
- package/dist/shaders/atmosphere.frag.js +6 -5
- package/dist/shaders/atmosphere.frag.js.map +1 -1
- package/dist/shaders/atmosphere.vert.js +6 -5
- package/dist/shaders/atmosphere.vert.js.map +1 -1
- package/dist/shaders/stars.frag.js +6 -5
- package/dist/shaders/stars.frag.js.map +1 -1
- package/dist/shaders/stars.vert.js +6 -5
- package/dist/shaders/stars.vert.js.map +1 -1
- package/dist/style.css +217 -194
- package/dist/tokens/core.d.ts +159 -0
- package/dist/tokens/core.js +144 -0
- package/dist/tokens/core.js.map +1 -0
- package/dist/tokens/css-vars.d.ts +213 -2
- package/dist/tokens/css-vars.js +590 -227
- package/dist/tokens/css-vars.js.map +1 -1
- package/dist/tokens/index.d.ts +31 -228
- package/dist/tokens/index.js +281 -366
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/palettes/astro.d.ts +129 -0
- package/dist/tokens/palettes/astro.js +112 -0
- package/dist/tokens/palettes/astro.js.map +1 -0
- package/dist/tokens/palettes/index.d.ts +288 -0
- package/dist/tokens/palettes/index.js +35 -0
- package/dist/tokens/palettes/index.js.map +1 -0
- package/dist/tokens/palettes/tailwind.d.ts +324 -0
- package/dist/tokens/palettes/tailwind.js +201 -0
- package/dist/tokens/palettes/tailwind.js.map +1 -0
- package/dist/tokens/palettes/zendir.d.ts +126 -0
- package/dist/tokens/palettes/zendir.js +92 -0
- package/dist/tokens/palettes/zendir.js.map +1 -0
- package/dist/tokens/themes.d.ts +30 -0
- package/dist/tokens/themes.js +704 -0
- package/dist/tokens/themes.js.map +1 -0
- package/dist/tokens/tokens.css +419 -41
- package/dist/types/index.d.ts +2 -2
- package/package.json +310 -313
- package/dist/index.js.map +0 -1
- package/dist/react/3d/index.js.map +0 -1
- package/dist/react/astro/index.js.map +0 -1
- package/dist/react/cards/index.js.map +0 -1
- package/dist/react/charts/index.js.map +0 -1
- package/dist/react/core/index.js.map +0 -1
- package/dist/react/panels/index.js.map +0 -1
- package/dist/react/theme/astro-tokens.d.ts +0 -153
- package/dist/react/theme/index.js.map +0 -1
- package/dist/react.js.map +0 -1
|
@@ -1,210 +1,227 @@
|
|
|
1
|
-
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo, useRef, useState, useEffect, useCallback } from "react";
|
|
3
1
|
import { useTheme } from "../../theme/ThemeProvider.js";
|
|
4
2
|
import { useBreakpoint } from "../layout/useBreakpoint.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
3
|
+
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/react/core/inputs/PinInput.tsx
|
|
6
|
+
/**
|
|
7
|
+
* @zendir/ui - PinInput Component
|
|
8
|
+
*
|
|
9
|
+
* Multi-character code entry for passwords, verification codes, and team IDs.
|
|
10
|
+
* Auto-advances focus between cells. Supports numeric and alphanumeric modes.
|
|
11
|
+
*
|
|
12
|
+
* Astro UX Compliance:
|
|
13
|
+
* - Consistent styling with Input component
|
|
14
|
+
* - Focus ring for accessibility
|
|
15
|
+
* - Monospace tabular numbers
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <PinInput length={6} type="alphanumeric" value={password} onChange={setPassword} label="Team Password" />
|
|
20
|
+
* <PinInput length={4} type="numeric" value={code} onChange={setCode} label="Verification Code" />
|
|
21
|
+
* <PinInput length={8} value={token} onChange={setToken} label="API Token" />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
var PinInput = memo(function PinInput({ length = 6, type = "alphanumeric", value, onChange, label, helperText, error, disabled = false, mask = false, size = "medium", autoFocus = false, onComplete, labelPlacement = "outlined", required, fullWidth = false }) {
|
|
25
|
+
const { tokens, theme } = useTheme();
|
|
26
|
+
const { isMobile } = useBreakpoint();
|
|
27
|
+
const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
|
|
28
|
+
const refs = useRef([]);
|
|
29
|
+
const [focusedIndex, setFocusedIndex] = useState(null);
|
|
30
|
+
const chars = value.split("").concat(Array(length).fill("")).slice(0, length);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (autoFocus && refs.current[0]) refs.current[0].focus();
|
|
33
|
+
}, [autoFocus]);
|
|
34
|
+
const controlHeight = isMobile ? "44px" : size === "small" ? "26px" : size === "medium" ? "34px" : "42px";
|
|
35
|
+
const config = {
|
|
36
|
+
...{
|
|
37
|
+
small: { fontSize: tokens.typography.fontSize.xs },
|
|
38
|
+
medium: { fontSize: tokens.typography.fontSize.sm },
|
|
39
|
+
large: { fontSize: tokens.typography.fontSize.base }
|
|
40
|
+
}[size],
|
|
41
|
+
height: controlHeight
|
|
42
|
+
};
|
|
43
|
+
const isValid = (char) => {
|
|
44
|
+
if (type === "numeric") return /^[0-9]$/.test(char);
|
|
45
|
+
return /^[a-zA-Z0-9]$/.test(char);
|
|
46
|
+
};
|
|
47
|
+
const handleChange = useCallback((index, inputValue) => {
|
|
48
|
+
if (inputValue.length > 1) {
|
|
49
|
+
const filtered = inputValue.replace(/\s/g, "").split("").filter(isValid).slice(0, length);
|
|
50
|
+
const newValue = filtered.join("");
|
|
51
|
+
onChange(newValue);
|
|
52
|
+
const nextIndex = Math.min(filtered.length, length - 1);
|
|
53
|
+
refs.current[nextIndex]?.focus();
|
|
54
|
+
if (filtered.length === length) onComplete?.(newValue);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const char = inputValue;
|
|
58
|
+
if (char && !isValid(char)) return;
|
|
59
|
+
const newChars = [...chars];
|
|
60
|
+
newChars[index] = char.toUpperCase();
|
|
61
|
+
const newValue = newChars.join("").replace(/\s/g, "");
|
|
62
|
+
onChange(newValue);
|
|
63
|
+
if (char && index < length - 1) refs.current[index + 1]?.focus();
|
|
64
|
+
if (newValue.length === length) onComplete?.(newValue);
|
|
65
|
+
}, [
|
|
66
|
+
chars,
|
|
67
|
+
length,
|
|
68
|
+
onChange,
|
|
69
|
+
onComplete,
|
|
70
|
+
type
|
|
71
|
+
]);
|
|
72
|
+
const handleKeyDown = useCallback((index, e) => {
|
|
73
|
+
if (e.key === "Backspace") {
|
|
74
|
+
if (!chars[index] && index > 0) {
|
|
75
|
+
refs.current[index - 1]?.focus();
|
|
76
|
+
const newChars = [...chars];
|
|
77
|
+
newChars[index - 1] = "";
|
|
78
|
+
onChange(newChars.join(""));
|
|
79
|
+
}
|
|
80
|
+
} else if (e.key === "ArrowLeft" && index > 0) refs.current[index - 1]?.focus();
|
|
81
|
+
else if (e.key === "ArrowRight" && index < length - 1) refs.current[index + 1]?.focus();
|
|
82
|
+
}, [
|
|
83
|
+
chars,
|
|
84
|
+
length,
|
|
85
|
+
onChange
|
|
86
|
+
]);
|
|
87
|
+
const hasError = !!error;
|
|
88
|
+
const errorMessage = typeof error === "string" ? error : void 0;
|
|
89
|
+
const inputBg = isTransparentTheme ? tokens.colors.interactive.transparentInputBg || "rgba(139, 92, 246, 0.08)" : tokens.colors.background.surface;
|
|
90
|
+
const isOutlined = labelPlacement === "outlined";
|
|
91
|
+
const isFocused = focusedIndex !== null;
|
|
92
|
+
const labelBg = isTransparentTheme ? tokens.colors.background.base : tokens.colors.background.surface;
|
|
93
|
+
const outlinedLabelSizeMap = {
|
|
94
|
+
small: "0.625rem",
|
|
95
|
+
medium: "0.6875rem",
|
|
96
|
+
large: "0.75rem"
|
|
97
|
+
};
|
|
98
|
+
const outlinedLabelLeftMap = {
|
|
99
|
+
small: "2px",
|
|
100
|
+
medium: "2px",
|
|
101
|
+
large: "2px"
|
|
102
|
+
};
|
|
103
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [label, required && /* @__PURE__ */ jsx("span", {
|
|
104
|
+
style: {
|
|
105
|
+
color: tokens.colors.status.critical,
|
|
106
|
+
marginLeft: "2px"
|
|
107
|
+
},
|
|
108
|
+
children: "*"
|
|
109
|
+
})] });
|
|
110
|
+
const cellsEl = /* @__PURE__ */ jsx("div", {
|
|
111
|
+
style: {
|
|
112
|
+
display: "flex",
|
|
113
|
+
gap: tokens.spacing.xs,
|
|
114
|
+
width: fullWidth ? "100%" : void 0
|
|
115
|
+
},
|
|
116
|
+
children: Array.from({ length }, (_, i) => /* @__PURE__ */ jsx("input", {
|
|
117
|
+
ref: (el) => {
|
|
118
|
+
refs.current[i] = el;
|
|
119
|
+
},
|
|
120
|
+
type: mask ? "password" : "text",
|
|
121
|
+
inputMode: type === "numeric" ? "numeric" : "text",
|
|
122
|
+
maxLength: 1,
|
|
123
|
+
value: chars[i] || "",
|
|
124
|
+
onChange: (e) => handleChange(i, e.target.value),
|
|
125
|
+
onKeyDown: (e) => handleKeyDown(i, e),
|
|
126
|
+
onFocus: () => setFocusedIndex(i),
|
|
127
|
+
onBlur: () => setFocusedIndex(null),
|
|
128
|
+
onPaste: (e) => {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
handleChange(i, e.clipboardData.getData("text"));
|
|
131
|
+
},
|
|
132
|
+
disabled,
|
|
133
|
+
"aria-label": `Character ${i + 1} of ${length}`,
|
|
134
|
+
"aria-invalid": hasError || void 0,
|
|
135
|
+
"aria-describedby": errorMessage ? "zendir-pin-error" : helperText ? "zendir-pin-helper" : void 0,
|
|
136
|
+
style: {
|
|
137
|
+
...fullWidth ? {
|
|
138
|
+
flex: 1,
|
|
139
|
+
minWidth: 0
|
|
140
|
+
} : { width: controlHeight },
|
|
141
|
+
height: config.height,
|
|
142
|
+
textAlign: "center",
|
|
143
|
+
fontSize: config.fontSize,
|
|
144
|
+
fontWeight: tokens.typography.fontWeight.bold,
|
|
145
|
+
fontFamily: tokens.typography.fontFamily.mono,
|
|
146
|
+
fontVariantNumeric: "tabular-nums",
|
|
147
|
+
color: tokens.colors.text.primary,
|
|
148
|
+
backgroundColor: isOutlined ? "transparent" : inputBg,
|
|
149
|
+
border: isOutlined ? "none" : hasError ? `${tokens.borders.width.medium} solid ${tokens.colors.status.critical}` : focusedIndex === i ? `${tokens.borders.width.medium} solid ${tokens.colors.accent.primary}` : chars[i] ? `${tokens.borders.width.medium} solid ${tokens.colors.border.default}` : `${tokens.borders.width.medium} solid ${tokens.colors.border.muted}`,
|
|
150
|
+
borderRadius: isOutlined ? 0 : tokens.borderRadius.md,
|
|
151
|
+
outline: "none",
|
|
152
|
+
transition: tokens.animation.fast,
|
|
153
|
+
opacity: disabled ? .5 : 1,
|
|
154
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
155
|
+
...!isOutlined && focusedIndex === i ? { boxShadow: tokens.borders.focusRing.subtle } : {}
|
|
156
|
+
}
|
|
157
|
+
}, i))
|
|
158
|
+
});
|
|
159
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
160
|
+
style: {
|
|
161
|
+
fontFamily: tokens.typography.fontFamily.primary,
|
|
162
|
+
width: fullWidth ? "100%" : void 0
|
|
163
|
+
},
|
|
164
|
+
children: [
|
|
165
|
+
label && !isOutlined && /* @__PURE__ */ jsx("div", {
|
|
166
|
+
style: {
|
|
167
|
+
fontSize: tokens.typography.fontSize.xs,
|
|
168
|
+
fontWeight: tokens.typography.fontWeight.medium,
|
|
169
|
+
color: tokens.colors.text.secondary,
|
|
170
|
+
letterSpacing: tokens.typography.letterSpacing.wide,
|
|
171
|
+
marginBottom: tokens.spacing.xs
|
|
172
|
+
},
|
|
173
|
+
children: labelContent
|
|
174
|
+
}),
|
|
175
|
+
isOutlined ? /* @__PURE__ */ jsxs("div", {
|
|
176
|
+
style: {
|
|
177
|
+
position: "relative",
|
|
178
|
+
width: fullWidth ? "100%" : void 0,
|
|
179
|
+
minHeight: controlHeight,
|
|
180
|
+
border: hasError ? tokens.borders.input.error : isFocused ? tokens.borders.input.focus : tokens.borders.input.default,
|
|
181
|
+
borderRadius: tokens.borderRadius.md,
|
|
182
|
+
padding: `0 ${tokens.spacing.sm}`,
|
|
183
|
+
display: "flex",
|
|
184
|
+
alignItems: "center",
|
|
185
|
+
backgroundColor: inputBg,
|
|
186
|
+
transition: tokens.animation.fast,
|
|
187
|
+
boxSizing: "border-box",
|
|
188
|
+
...isFocused ? { boxShadow: tokens.borders.focusRing.subtle } : {}
|
|
189
|
+
},
|
|
190
|
+
children: [label && /* @__PURE__ */ jsx("div", {
|
|
191
|
+
style: {
|
|
192
|
+
position: "absolute",
|
|
193
|
+
top: 0,
|
|
194
|
+
left: outlinedLabelLeftMap[size],
|
|
195
|
+
transform: "translateY(-50%)",
|
|
196
|
+
backgroundColor: labelBg,
|
|
197
|
+
padding: `0 ${tokens.spacing.xs}`,
|
|
198
|
+
fontSize: outlinedLabelSizeMap[size],
|
|
199
|
+
fontWeight: tokens.typography.fontWeight.medium,
|
|
200
|
+
color: isFocused ? hasError ? tokens.colors.status.critical : tokens.colors.accent.primary : hasError ? tokens.colors.status.critical : tokens.colors.text.secondary,
|
|
201
|
+
letterSpacing: tokens.typography.letterSpacing.wide,
|
|
202
|
+
zIndex: 1,
|
|
203
|
+
pointerEvents: "none",
|
|
204
|
+
transition: tokens.animation.fast,
|
|
205
|
+
lineHeight: 1.2,
|
|
206
|
+
whiteSpace: "nowrap"
|
|
207
|
+
},
|
|
208
|
+
children: labelContent
|
|
209
|
+
}), cellsEl]
|
|
210
|
+
}) : cellsEl,
|
|
211
|
+
(helperText || errorMessage) && /* @__PURE__ */ jsx("div", {
|
|
212
|
+
id: errorMessage ? "zendir-pin-error" : "zendir-pin-helper",
|
|
213
|
+
role: errorMessage ? "alert" : void 0,
|
|
214
|
+
style: {
|
|
215
|
+
fontSize: tokens.typography.fontSize.xs,
|
|
216
|
+
color: hasError ? tokens.colors.status.critical : tokens.colors.text.tertiary,
|
|
217
|
+
marginTop: tokens.spacing.xs
|
|
218
|
+
},
|
|
219
|
+
children: errorMessage || helperText
|
|
220
|
+
})
|
|
221
|
+
]
|
|
222
|
+
});
|
|
206
223
|
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
//# sourceMappingURL=PinInput.js.map
|
|
224
|
+
//#endregion
|
|
225
|
+
export { PinInput, PinInput as default };
|
|
226
|
+
|
|
227
|
+
//# sourceMappingURL=PinInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PinInput.js","sources":["../../../../src/react/core/inputs/PinInput.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - PinInput Component\r\n * \r\n * Multi-character code entry for passwords, verification codes, and team IDs.\r\n * Auto-advances focus between cells. Supports numeric and alphanumeric modes.\r\n * \r\n * Astro UX Compliance:\r\n * - Consistent styling with Input component\r\n * - Focus ring for accessibility\r\n * - Monospace tabular numbers\r\n * \r\n * @example\r\n * ```tsx\r\n * <PinInput length={6} type=\"alphanumeric\" value={password} onChange={setPassword} label=\"Team Password\" />\r\n * <PinInput length={4} type=\"numeric\" value={code} onChange={setCode} label=\"Verification Code\" />\r\n * <PinInput length={8} value={token} onChange={setToken} label=\"API Token\" />\r\n * ```\r\n */\r\n\r\nimport React, { memo, useState, useRef, useCallback, useEffect } from 'react';\r\nimport { useTheme } from '../../theme';\r\nimport type { LabelPlacement } from './Input';\r\nimport { useBreakpoint } from '../layout/useBreakpoint';\r\n\r\nexport interface PinInputProps {\r\n /** Number of character cells (default 6; any positive number, e.g. 4, 6, 8) */\r\n length?: number;\r\n /** Input type */\r\n type?: 'numeric' | 'alphanumeric';\r\n /** Current value */\r\n value: string;\r\n /** Change handler */\r\n onChange: (value: string) => void;\r\n /** Label text or ReactNode (supports rich content like tooltip icons) */\r\n label?: React.ReactNode;\r\n /** Helper text */\r\n helperText?: string;\r\n /** Error state */\r\n error?: boolean | string;\r\n /** Disabled */\r\n disabled?: boolean;\r\n /** Mask characters (password mode) */\r\n mask?: boolean;\r\n /** Size */\r\n size?: 'small' | 'medium' | 'large';\r\n /** Auto-focus first cell on mount */\r\n autoFocus?: boolean;\r\n /** Callback when all cells filled */\r\n onComplete?: (value: string) => void;\r\n /**\r\n * Label placement style.\r\n * - `'outlined'` — label sits on the border of a surrounding container. **Default.**\r\n * - `'above'` — label sits above the cells with a gap (classic stack).\r\n */\r\n labelPlacement?: LabelPlacement;\r\n /** Required indicator */\r\n required?: boolean;\r\n /** Stretch to full width of container (cells share width equally, same as standard inputs) */\r\n fullWidth?: boolean;\r\n}\r\n\r\nexport const PinInput = memo(function PinInput({\r\n length = 6,\r\n type = 'alphanumeric',\r\n value,\r\n onChange,\r\n label,\r\n helperText,\r\n error,\r\n disabled = false,\r\n mask = false,\r\n size = 'medium',\r\n autoFocus = false,\r\n onComplete,\r\n labelPlacement = 'outlined',\r\n required,\r\n fullWidth = false,\r\n}: PinInputProps): React.ReactElement {\r\n const { tokens, theme } = useTheme();\r\n const { isMobile } = useBreakpoint();\r\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\r\n const refs = useRef<(HTMLInputElement | null)[]>([]);\r\n const [focusedIndex, setFocusedIndex] = useState<number | null>(null);\r\n \r\n const chars = value.split('').concat(Array(length).fill('')).slice(0, length);\r\n \r\n useEffect(() => {\r\n if (autoFocus && refs.current[0]) {\r\n refs.current[0].focus();\r\n }\r\n }, [autoFocus]);\r\n \r\n // Between original tokens and the reduced set: slightly more height than 24/32/40, still less than 28/36/44\r\n const reducedHeight = size === 'small' ? '26px' : size === 'medium' ? '34px' : '42px';\r\n const controlHeight = isMobile ? '44px' : reducedHeight;\r\n const sizeConfig = {\r\n small: { fontSize: tokens.typography.fontSize.xs },\r\n medium: { fontSize: tokens.typography.fontSize.sm },\r\n large: { fontSize: tokens.typography.fontSize.base },\r\n };\r\n const config = { ...sizeConfig[size], height: controlHeight } as { height: string; fontSize: string };\r\n \r\n const isValid = (char: string): boolean => {\r\n if (type === 'numeric') return /^[0-9]$/.test(char);\r\n return /^[a-zA-Z0-9]$/.test(char);\r\n };\r\n \r\n const handleChange = useCallback((index: number, inputValue: string) => {\r\n // Handle paste (multiple characters). Strip spaces so pasted codes like \"12 34 56\" work.\r\n if (inputValue.length > 1) {\r\n const normalized = inputValue.replace(/\\s/g, '');\r\n const filtered = normalized.split('').filter(isValid).slice(0, length);\r\n const newValue = filtered.join('');\r\n onChange(newValue);\r\n const nextIndex = Math.min(filtered.length, length - 1);\r\n refs.current[nextIndex]?.focus();\r\n if (filtered.length === length) onComplete?.(newValue);\r\n return;\r\n }\r\n \r\n const char = inputValue;\r\n if (char && !isValid(char)) return;\r\n \r\n const newChars = [...chars];\r\n newChars[index] = char.toUpperCase();\r\n const newValue = newChars.join('').replace(/\\s/g, '');\r\n onChange(newValue);\r\n \r\n // Auto-advance\r\n if (char && index < length - 1) {\r\n refs.current[index + 1]?.focus();\r\n }\r\n \r\n if (newValue.length === length) {\r\n onComplete?.(newValue);\r\n }\r\n }, [chars, length, onChange, onComplete, type]);\r\n \r\n const handleKeyDown = useCallback((index: number, e: React.KeyboardEvent) => {\r\n if (e.key === 'Backspace') {\r\n if (!chars[index] && index > 0) {\r\n refs.current[index - 1]?.focus();\r\n const newChars = [...chars];\r\n newChars[index - 1] = '';\r\n onChange(newChars.join(''));\r\n }\r\n } else if (e.key === 'ArrowLeft' && index > 0) {\r\n refs.current[index - 1]?.focus();\r\n } else if (e.key === 'ArrowRight' && index < length - 1) {\r\n refs.current[index + 1]?.focus();\r\n }\r\n }, [chars, length, onChange]);\r\n \r\n const hasError = !!error;\r\n const errorMessage = typeof error === 'string' ? error : undefined;\r\n \r\n const inputBg = isTransparentTheme\r\n ? (tokens.colors.interactive.transparentInputBg || 'rgba(139, 92, 246, 0.08)')\r\n : tokens.colors.background.surface;\r\n \r\n const isOutlined = labelPlacement === 'outlined';\r\n const isFocused = focusedIndex !== null;\r\n \r\n // Background for the outlined label \"notch\"\r\n const labelBg = isTransparentTheme\r\n ? tokens.colors.background.base\r\n : tokens.colors.background.surface;\r\n \r\n // Outlined label font sizes\r\n const outlinedLabelSizeMap = { small: '0.625rem', medium: '0.6875rem', large: '0.75rem' };\r\n // Container always uses spacing.sm (8px) horizontal padding, so label left is always 8-6=2px\r\n const outlinedLabelLeftMap = { small: '2px', medium: '2px', large: '2px' };\r\n \r\n // Shared label content\r\n const labelContent = (\r\n <>\r\n {label}\r\n {required && (\r\n <span style={{ color: tokens.colors.status.critical, marginLeft: '2px' }}>*</span>\r\n )}\r\n </>\r\n );\r\n \r\n // Cells renderer: fullWidth = cells share space (same total width as standard inputs); otherwise fixed square cells\r\n const cellsEl = (\r\n <div style={{\r\n display: 'flex',\r\n gap: tokens.spacing.xs,\r\n width: fullWidth ? '100%' : undefined,\r\n }}>\r\n {Array.from({ length }, (_, i) => (\r\n <input\r\n key={i}\r\n ref={el => { refs.current[i] = el; }}\r\n type={mask ? 'password' : 'text'}\r\n inputMode={type === 'numeric' ? 'numeric' : 'text'}\r\n maxLength={1}\r\n value={chars[i] || ''}\r\n onChange={e => handleChange(i, e.target.value)}\r\n onKeyDown={e => handleKeyDown(i, e)}\r\n onFocus={() => setFocusedIndex(i)}\r\n onBlur={() => setFocusedIndex(null)}\r\n onPaste={e => {\r\n e.preventDefault();\r\n handleChange(i, e.clipboardData.getData('text'));\r\n }}\r\n disabled={disabled}\r\n aria-label={`Character ${i + 1} of ${length}`}\r\n aria-invalid={hasError || undefined}\r\n aria-describedby={errorMessage ? 'zendir-pin-error' : helperText ? 'zendir-pin-helper' : undefined}\r\n style={{\r\n ...(fullWidth ? { flex: 1, minWidth: 0 } : { width: controlHeight }),\r\n height: config.height,\r\n textAlign: 'center',\r\n fontSize: config.fontSize,\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: 'tabular-nums',\r\n color: tokens.colors.text.primary,\r\n backgroundColor: isOutlined ? 'transparent' : inputBg,\r\n border: isOutlined ? 'none' : (\r\n hasError\r\n ? `${tokens.borders.width.medium} solid ${tokens.colors.status.critical}`\r\n : focusedIndex === i\r\n ? `${tokens.borders.width.medium} solid ${tokens.colors.accent.primary}`\r\n : chars[i]\r\n ? `${tokens.borders.width.medium} solid ${tokens.colors.border.default}`\r\n : `${tokens.borders.width.medium} solid ${tokens.colors.border.muted}`\r\n ),\r\n borderRadius: isOutlined ? 0 : tokens.borderRadius.md,\r\n outline: 'none',\r\n transition: tokens.animation.fast,\r\n opacity: disabled ? 0.5 : 1,\r\n cursor: disabled ? 'not-allowed' : 'text',\r\n ...(!isOutlined && focusedIndex === i ? {\r\n boxShadow: tokens.borders.focusRing.subtle,\r\n } : {}),\r\n }}\r\n />\r\n ))}\r\n </div>\r\n );\r\n \r\n return (\r\n <div style={{\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n width: fullWidth ? '100%' : undefined,\r\n }}>\r\n {/* Label: 'above' variant */}\r\n {label && !isOutlined && (\r\n <div style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: tokens.colors.text.secondary,\r\n letterSpacing: tokens.typography.letterSpacing.wide,\r\n marginBottom: tokens.spacing.xs,\r\n }}>\r\n {labelContent}\r\n </div>\r\n )}\r\n \r\n {/* Outlined variant: wrap cells in a bordered container with the label on the border */}\r\n {isOutlined ? (\r\n <div style={{\r\n position: 'relative',\r\n width: fullWidth ? '100%' : undefined,\r\n minHeight: controlHeight,\r\n border: hasError\r\n ? tokens.borders.input.error\r\n : isFocused\r\n ? tokens.borders.input.focus\r\n : tokens.borders.input.default,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `0 ${tokens.spacing.sm}`,\r\n display: 'flex',\r\n alignItems: 'center',\r\n backgroundColor: inputBg,\r\n transition: tokens.animation.fast,\r\n boxSizing: 'border-box',\r\n ...(isFocused ? {\r\n boxShadow: tokens.borders.focusRing.subtle,\r\n } : {}),\r\n }}>\r\n {label && (\r\n <div style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: outlinedLabelLeftMap[size],\r\n transform: 'translateY(-50%)',\r\n backgroundColor: labelBg,\r\n padding: `0 ${tokens.spacing.xs}`,\r\n fontSize: outlinedLabelSizeMap[size],\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: isFocused\r\n ? (hasError ? tokens.colors.status.critical : tokens.colors.accent.primary)\r\n : hasError\r\n ? tokens.colors.status.critical\r\n : tokens.colors.text.secondary,\r\n letterSpacing: tokens.typography.letterSpacing.wide,\r\n zIndex: 1,\r\n pointerEvents: 'none',\r\n transition: tokens.animation.fast,\r\n lineHeight: 1.2,\r\n whiteSpace: 'nowrap',\r\n }}>\r\n {labelContent}\r\n </div>\r\n )}\r\n {cellsEl}\r\n </div>\r\n ) : (\r\n cellsEl\r\n )}\r\n \r\n {(helperText || errorMessage) && (\r\n <div\r\n id={errorMessage ? 'zendir-pin-error' : 'zendir-pin-helper'}\r\n role={errorMessage ? 'alert' : undefined}\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: hasError ? tokens.colors.status.critical : tokens.colors.text.tertiary,\r\n marginTop: tokens.spacing.xs,\r\n }}\r\n >\r\n {errorMessage || helperText}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nexport default PinInput;\r\n"],"names":["PinInput","newValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PinInput.js","names":[],"sources":["../../../../src/react/core/inputs/PinInput.tsx"],"sourcesContent":["/**\n * @zendir/ui - PinInput Component\n *\n * Multi-character code entry for passwords, verification codes, and team IDs.\n * Auto-advances focus between cells. Supports numeric and alphanumeric modes.\n *\n * Astro UX Compliance:\n * - Consistent styling with Input component\n * - Focus ring for accessibility\n * - Monospace tabular numbers\n *\n * @example\n * ```tsx\n * <PinInput length={6} type=\"alphanumeric\" value={password} onChange={setPassword} label=\"Team Password\" />\n * <PinInput length={4} type=\"numeric\" value={code} onChange={setCode} label=\"Verification Code\" />\n * <PinInput length={8} value={token} onChange={setToken} label=\"API Token\" />\n * ```\n */\n\nimport React, { memo, useState, useRef, useCallback, useEffect } from \"react\";\nimport { useTheme } from \"../../theme\";\nimport type { LabelPlacement } from \"./Input\";\nimport { useBreakpoint } from \"../layout/useBreakpoint\";\n\nexport interface PinInputProps {\n /** Number of character cells (default 6; any positive number, e.g. 4, 6, 8) */\n length?: number;\n /** Input type */\n type?: \"numeric\" | \"alphanumeric\";\n /** Current value */\n value: string;\n /** Change handler */\n onChange: (value: string) => void;\n /** Label text or ReactNode (supports rich content like tooltip icons) */\n label?: React.ReactNode;\n /** Helper text */\n helperText?: string;\n /** Error state */\n error?: boolean | string;\n /** Disabled */\n disabled?: boolean;\n /** Mask characters (password mode) */\n mask?: boolean;\n /** Size */\n size?: \"small\" | \"medium\" | \"large\";\n /** Auto-focus first cell on mount */\n autoFocus?: boolean;\n /** Callback when all cells filled */\n onComplete?: (value: string) => void;\n /**\n * Label placement style.\n * - `'outlined'` — label sits on the border of a surrounding container. **Default.**\n * - `'above'` — label sits above the cells with a gap (classic stack).\n */\n labelPlacement?: LabelPlacement;\n /** Required indicator */\n required?: boolean;\n /** Stretch to full width of container (cells share width equally, same as standard inputs) */\n fullWidth?: boolean;\n}\n\nexport const PinInput = memo(function PinInput({\n length = 6,\n type = \"alphanumeric\",\n value,\n onChange,\n label,\n helperText,\n error,\n disabled = false,\n mask = false,\n size = \"medium\",\n autoFocus = false,\n onComplete,\n labelPlacement = \"outlined\",\n required,\n fullWidth = false,\n}: PinInputProps): React.ReactElement {\n const { tokens, theme } = useTheme();\n const { isMobile } = useBreakpoint();\n const isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const refs = useRef<(HTMLInputElement | null)[]>([]);\n const [focusedIndex, setFocusedIndex] = useState<number | null>(null);\n\n const chars = value.split(\"\").concat(Array(length).fill(\"\")).slice(0, length);\n\n useEffect(() => {\n if (autoFocus && refs.current[0]) {\n refs.current[0].focus();\n }\n }, [autoFocus]);\n\n // Between original tokens and the reduced set: slightly more height than 24/32/40, still less than 28/36/44\n const reducedHeight =\n size === \"small\" ? \"26px\" : size === \"medium\" ? \"34px\" : \"42px\";\n const controlHeight = isMobile ? \"44px\" : reducedHeight;\n const sizeConfig = {\n small: { fontSize: tokens.typography.fontSize.xs },\n medium: { fontSize: tokens.typography.fontSize.sm },\n large: { fontSize: tokens.typography.fontSize.base },\n };\n const config = { ...sizeConfig[size], height: controlHeight } as {\n height: string;\n fontSize: string;\n };\n\n const isValid = (char: string): boolean => {\n if (type === \"numeric\") return /^[0-9]$/.test(char);\n return /^[a-zA-Z0-9]$/.test(char);\n };\n\n const handleChange = useCallback(\n (index: number, inputValue: string) => {\n // Handle paste (multiple characters). Strip spaces so pasted codes like \"12 34 56\" work.\n if (inputValue.length > 1) {\n const normalized = inputValue.replace(/\\s/g, \"\");\n const filtered = normalized.split(\"\").filter(isValid).slice(0, length);\n const newValue = filtered.join(\"\");\n onChange(newValue);\n const nextIndex = Math.min(filtered.length, length - 1);\n refs.current[nextIndex]?.focus();\n if (filtered.length === length) onComplete?.(newValue);\n return;\n }\n\n const char = inputValue;\n if (char && !isValid(char)) return;\n\n const newChars = [...chars];\n newChars[index] = char.toUpperCase();\n const newValue = newChars.join(\"\").replace(/\\s/g, \"\");\n onChange(newValue);\n\n // Auto-advance\n if (char && index < length - 1) {\n refs.current[index + 1]?.focus();\n }\n\n if (newValue.length === length) {\n onComplete?.(newValue);\n }\n },\n [chars, length, onChange, onComplete, type],\n );\n\n const handleKeyDown = useCallback(\n (index: number, e: React.KeyboardEvent) => {\n if (e.key === \"Backspace\") {\n if (!chars[index] && index > 0) {\n refs.current[index - 1]?.focus();\n const newChars = [...chars];\n newChars[index - 1] = \"\";\n onChange(newChars.join(\"\"));\n }\n } else if (e.key === \"ArrowLeft\" && index > 0) {\n refs.current[index - 1]?.focus();\n } else if (e.key === \"ArrowRight\" && index < length - 1) {\n refs.current[index + 1]?.focus();\n }\n },\n [chars, length, onChange],\n );\n\n const hasError = !!error;\n const errorMessage = typeof error === \"string\" ? error : undefined;\n\n const inputBg = isTransparentTheme\n ? tokens.colors.interactive.transparentInputBg || \"rgba(139, 92, 246, 0.08)\"\n : tokens.colors.background.surface;\n\n const isOutlined = labelPlacement === \"outlined\";\n const isFocused = focusedIndex !== null;\n\n // Background for the outlined label \"notch\"\n const labelBg = isTransparentTheme\n ? tokens.colors.background.base\n : tokens.colors.background.surface;\n\n // Outlined label font sizes\n const outlinedLabelSizeMap = {\n small: \"0.625rem\",\n medium: \"0.6875rem\",\n large: \"0.75rem\",\n };\n // Container always uses spacing.sm (8px) horizontal padding, so label left is always 8-6=2px\n const outlinedLabelLeftMap = { small: \"2px\", medium: \"2px\", large: \"2px\" };\n\n // Shared label content\n const labelContent = (\n <>\n {label}\n {required && (\n <span\n style={{ color: tokens.colors.status.critical, marginLeft: \"2px\" }}\n >\n *\n </span>\n )}\n </>\n );\n\n // Cells renderer: fullWidth = cells share space (same total width as standard inputs); otherwise fixed square cells\n const cellsEl = (\n <div\n style={{\n display: \"flex\",\n gap: tokens.spacing.xs,\n width: fullWidth ? \"100%\" : undefined,\n }}\n >\n {Array.from({ length }, (_, i) => (\n <input\n key={i}\n ref={(el) => {\n refs.current[i] = el;\n }}\n type={mask ? \"password\" : \"text\"}\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n maxLength={1}\n value={chars[i] || \"\"}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onFocus={() => setFocusedIndex(i)}\n onBlur={() => setFocusedIndex(null)}\n onPaste={(e) => {\n e.preventDefault();\n handleChange(i, e.clipboardData.getData(\"text\"));\n }}\n disabled={disabled}\n aria-label={`Character ${i + 1} of ${length}`}\n aria-invalid={hasError || undefined}\n aria-describedby={\n errorMessage\n ? \"zendir-pin-error\"\n : helperText\n ? \"zendir-pin-helper\"\n : undefined\n }\n style={{\n ...(fullWidth\n ? { flex: 1, minWidth: 0 }\n : { width: controlHeight }),\n height: config.height,\n textAlign: \"center\",\n fontSize: config.fontSize,\n fontWeight: tokens.typography.fontWeight.bold,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n color: tokens.colors.text.primary,\n backgroundColor: isOutlined ? \"transparent\" : inputBg,\n border: isOutlined\n ? \"none\"\n : hasError\n ? `${tokens.borders.width.medium} solid ${tokens.colors.status.critical}`\n : focusedIndex === i\n ? `${tokens.borders.width.medium} solid ${tokens.colors.accent.primary}`\n : chars[i]\n ? `${tokens.borders.width.medium} solid ${tokens.colors.border.default}`\n : `${tokens.borders.width.medium} solid ${tokens.colors.border.muted}`,\n borderRadius: isOutlined ? 0 : tokens.borderRadius.md,\n outline: \"none\",\n transition: tokens.animation.fast,\n opacity: disabled ? 0.5 : 1,\n cursor: disabled ? \"not-allowed\" : \"text\",\n ...(!isOutlined && focusedIndex === i\n ? {\n boxShadow: tokens.borders.focusRing.subtle,\n }\n : {}),\n }}\n />\n ))}\n </div>\n );\n\n return (\n <div\n style={{\n fontFamily: tokens.typography.fontFamily.primary,\n width: fullWidth ? \"100%\" : undefined,\n }}\n >\n {/* Label: 'above' variant */}\n {label && !isOutlined && (\n <div\n style={{\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n color: tokens.colors.text.secondary,\n letterSpacing: tokens.typography.letterSpacing.wide,\n marginBottom: tokens.spacing.xs,\n }}\n >\n {labelContent}\n </div>\n )}\n\n {/* Outlined variant: wrap cells in a bordered container with the label on the border */}\n {isOutlined ? (\n <div\n style={{\n position: \"relative\",\n width: fullWidth ? \"100%\" : undefined,\n minHeight: controlHeight,\n border: hasError\n ? tokens.borders.input.error\n : isFocused\n ? tokens.borders.input.focus\n : tokens.borders.input.default,\n borderRadius: tokens.borderRadius.md,\n padding: `0 ${tokens.spacing.sm}`,\n display: \"flex\",\n alignItems: \"center\",\n backgroundColor: inputBg,\n transition: tokens.animation.fast,\n boxSizing: \"border-box\",\n ...(isFocused\n ? {\n boxShadow: tokens.borders.focusRing.subtle,\n }\n : {}),\n }}\n >\n {label && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: outlinedLabelLeftMap[size],\n transform: \"translateY(-50%)\",\n backgroundColor: labelBg,\n padding: `0 ${tokens.spacing.xs}`,\n fontSize: outlinedLabelSizeMap[size],\n fontWeight: tokens.typography.fontWeight.medium,\n color: isFocused\n ? hasError\n ? tokens.colors.status.critical\n : tokens.colors.accent.primary\n : hasError\n ? tokens.colors.status.critical\n : tokens.colors.text.secondary,\n letterSpacing: tokens.typography.letterSpacing.wide,\n zIndex: 1,\n pointerEvents: \"none\",\n transition: tokens.animation.fast,\n lineHeight: 1.2,\n whiteSpace: \"nowrap\",\n }}\n >\n {labelContent}\n </div>\n )}\n {cellsEl}\n </div>\n ) : (\n cellsEl\n )}\n\n {(helperText || errorMessage) && (\n <div\n id={errorMessage ? \"zendir-pin-error\" : \"zendir-pin-helper\"}\n role={errorMessage ? \"alert\" : undefined}\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: hasError\n ? tokens.colors.status.critical\n : tokens.colors.text.tertiary,\n marginTop: tokens.spacing.xs,\n }}\n >\n {errorMessage || helperText}\n </div>\n )}\n </div>\n );\n});\n\nexport default PinInput;\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { LabelPlacement } from './Input';
|
|
3
|
-
|
|
4
3
|
export interface SelectOption {
|
|
5
4
|
value: string;
|
|
6
5
|
label: string;
|
|
@@ -26,7 +25,7 @@ export interface SelectProps {
|
|
|
26
25
|
/** Full width */
|
|
27
26
|
fullWidth?: boolean;
|
|
28
27
|
/** Size variant */
|
|
29
|
-
size?:
|
|
28
|
+
size?: "small" | "medium" | "large";
|
|
30
29
|
/** Custom className */
|
|
31
30
|
className?: string;
|
|
32
31
|
/**
|