@zendir/ui 0.5.0 → 0.6.1
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 +419 -386
- 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 +313 -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 +26 -3
- 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 +533 -155
- 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","sources":["../../../../src/react/core/overlays/Popover.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - Popover & Menu Components\r\n * \r\n * General-purpose popover for dropdown menus, sort controls, action menus,\r\n * and contextual information. Portal-rendered with auto-positioning.\r\n * \r\n * Astro UX Compliance:\r\n * - Consistent with Dialog/Tooltip styling\r\n * - Focus trap for keyboard navigation\r\n * - Escape to close\r\n * - Click outside to close\r\n * - Reduced motion support\r\n * \r\n * @example\r\n * ```tsx\r\n * <Popover\r\n * trigger={<Button variant=\"secondary\">Sort</Button>}\r\n * placement=\"bottom-start\"\r\n * >\r\n * <Menu>\r\n * <Menu.Item onClick={...}>Sort by Time</Menu.Item>\r\n * <Menu.Item onClick={...}>Sort by Name</Menu.Item>\r\n * <Menu.Divider />\r\n * <Menu.Item onClick={...} destructive>Clear All</Menu.Item>\r\n * </Menu>\r\n * </Popover>\r\n * ```\r\n */\r\n\r\nimport React, { memo, useState, useRef, useEffect, useCallback, createContext, useContext } from 'react';\r\nimport { useTheme } from '../../theme';\r\n\r\n// ─── Popover ─────────────────────────────────────────────────────────────────\r\n\r\nexport type PopoverPlacement = \r\n | 'top' | 'top-start' | 'top-end'\r\n | 'bottom' | 'bottom-start' | 'bottom-end'\r\n | 'left' | 'left-start' | 'left-end'\r\n | 'right' | 'right-start' | 'right-end';\r\n\r\nexport interface PopoverProps {\r\n /** Trigger element */\r\n trigger: React.ReactElement;\r\n /** Popover content */\r\n children: React.ReactNode;\r\n /** Placement relative to trigger */\r\n placement?: PopoverPlacement;\r\n /** Open on hover instead of click */\r\n hover?: boolean;\r\n /** Controlled open state */\r\n open?: boolean;\r\n /** Controlled open change */\r\n onOpenChange?: (open: boolean) => void;\r\n /** Close on content click */\r\n closeOnClick?: boolean;\r\n /** Width: 'trigger' matches trigger width, number for px, 'auto' */\r\n width?: 'trigger' | 'auto' | number;\r\n /** Custom style for popover panel */\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst PopoverContext = createContext<{ close: () => void }>({ close: () => {} });\r\n\r\nexport const Popover = memo(function Popover({\r\n trigger,\r\n children,\r\n placement = 'bottom-start',\r\n hover = false,\r\n open: controlledOpen,\r\n onOpenChange,\r\n closeOnClick = true,\r\n width = 'auto',\r\n style,\r\n}: PopoverProps): React.ReactElement {\r\n const { tokens, theme } = useTheme();\r\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\r\n const [internalOpen, setInternalOpen] = useState(false);\r\n const triggerRef = useRef<HTMLDivElement>(null);\r\n const popoverRef = useRef<HTMLDivElement>(null);\r\n const hoverTimeout = useRef<ReturnType<typeof setTimeout>>();\r\n \r\n const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;\r\n \r\n const setOpen = useCallback((val: boolean) => {\r\n if (controlledOpen === undefined) setInternalOpen(val);\r\n onOpenChange?.(val);\r\n }, [controlledOpen, onOpenChange]);\r\n \r\n const close = useCallback(() => setOpen(false), [setOpen]);\r\n \r\n // Click outside\r\n useEffect(() => {\r\n if (!isOpen) return;\r\n const handler = (e: MouseEvent) => {\r\n if (\r\n triggerRef.current && !triggerRef.current.contains(e.target as Node) &&\r\n popoverRef.current && !popoverRef.current.contains(e.target as Node)\r\n ) {\r\n close();\r\n }\r\n };\r\n document.addEventListener('mousedown', handler);\r\n return () => document.removeEventListener('mousedown', handler);\r\n }, [isOpen, close]);\r\n \r\n // Escape key + cleanup hoverTimeout on unmount\r\n useEffect(() => {\r\n if (!isOpen) return;\r\n const handler = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') close();\r\n };\r\n document.addEventListener('keydown', handler);\r\n return () => document.removeEventListener('keydown', handler);\r\n }, [isOpen, close]);\r\n \r\n useEffect(() => {\r\n return () => { clearTimeout(hoverTimeout.current); };\r\n }, []);\r\n \r\n // Position calculation — `positioned` gates visibility so the panel is never\r\n // painted in document flow before the first RAF resolves coordinates.\r\n // Initializing with position: 'fixed' ensures that the hidden first-frame\r\n // measurement doesn't get constrained by the trigger's parent container.\r\n const [position, setPosition] = useState<React.CSSProperties>({ position: 'fixed', left: 0, top: 0 });\r\n const [positioned, setPositioned] = useState(false);\r\n\r\n // Reset visibility guard whenever the popover closes so the next open starts\r\n // hidden again rather than flashing the stale coordinates for one frame.\r\n useEffect(() => {\r\n if (!isOpen) setPositioned(false);\r\n }, [isOpen]);\r\n\r\n useEffect(() => {\r\n if (!isOpen || !triggerRef.current) return;\r\n const gap = 8;\r\n const viewportPadding = 8;\r\n\r\n const updatePosition = () => {\r\n const rect = triggerRef.current?.getBoundingClientRect();\r\n if (!rect) return;\r\n\r\n const panelWidth = width === 'trigger'\r\n ? rect.width\r\n : typeof width === 'number'\r\n ? width\r\n : (popoverRef.current?.offsetWidth ?? 220);\r\n const panelHeight = popoverRef.current?.offsetHeight ?? 220;\r\n\r\n let left = rect.left;\r\n let top = rect.bottom + gap;\r\n\r\n if (placement.startsWith('top')) {\r\n top = rect.top - panelHeight - gap;\r\n } else if (placement.startsWith('bottom')) {\r\n top = rect.bottom + gap;\r\n } else if (placement.startsWith('left')) {\r\n left = rect.left - panelWidth - gap;\r\n } else if (placement.startsWith('right')) {\r\n left = rect.right + gap;\r\n }\r\n\r\n if (placement.startsWith('top') || placement.startsWith('bottom')) {\r\n if (placement.endsWith('-start')) {\r\n left = rect.left;\r\n } else if (placement.endsWith('-end')) {\r\n left = rect.right - panelWidth;\r\n } else {\r\n left = rect.left + (rect.width - panelWidth) / 2;\r\n }\r\n } else {\r\n if (placement.endsWith('-start')) {\r\n top = rect.top;\r\n } else if (placement.endsWith('-end')) {\r\n top = rect.bottom - panelHeight;\r\n } else {\r\n top = rect.top + (rect.height - panelHeight) / 2;\r\n }\r\n }\r\n\r\n left = Math.max(viewportPadding, Math.min(left, window.innerWidth - panelWidth - viewportPadding));\r\n top = Math.max(viewportPadding, Math.min(top, window.innerHeight - panelHeight - viewportPadding));\r\n\r\n const pos: React.CSSProperties = {\r\n position: 'fixed',\r\n zIndex: 9990,\r\n left,\r\n top,\r\n };\r\n\r\n if (width === 'trigger') {\r\n pos.width = rect.width;\r\n pos.minWidth = rect.width;\r\n } else if (typeof width === 'number') {\r\n pos.width = width;\r\n }\r\n\r\n setPosition(pos);\r\n setPositioned(true);\r\n };\r\n\r\n const raf = requestAnimationFrame(updatePosition);\r\n window.addEventListener('resize', updatePosition);\r\n window.addEventListener('scroll', updatePosition, true);\r\n return () => {\r\n cancelAnimationFrame(raf);\r\n window.removeEventListener('resize', updatePosition);\r\n window.removeEventListener('scroll', updatePosition, true);\r\n };\r\n }, [isOpen, placement, width]);\r\n \r\n const triggerProps: Record<string, (() => void) | undefined> = {};\r\n if (hover) {\r\n triggerProps.onMouseEnter = () => {\r\n clearTimeout(hoverTimeout.current);\r\n setOpen(true);\r\n };\r\n triggerProps.onMouseLeave = () => {\r\n hoverTimeout.current = setTimeout(close, 150);\r\n };\r\n } else {\r\n triggerProps.onClick = () => setOpen(!isOpen);\r\n }\r\n \r\n const popoverHoverProps = hover ? {\r\n onMouseEnter: () => clearTimeout(hoverTimeout.current),\r\n onMouseLeave: () => { hoverTimeout.current = setTimeout(close, 150); },\r\n } : {};\r\n \r\n return (\r\n <PopoverContext.Provider value={{ close }}>\r\n <div ref={triggerRef} style={{ display: 'inline-flex' }} aria-expanded={isOpen} aria-haspopup=\"true\" {...triggerProps}>\r\n {trigger}\r\n </div>\r\n \r\n {isOpen && (\r\n <div\r\n ref={popoverRef}\r\n role=\"dialog\"\r\n onClick={closeOnClick ? close : undefined}\r\n {...popoverHoverProps}\r\n style={{\r\n ...position,\r\n visibility: positioned ? 'visible' : 'hidden',\r\n backgroundColor: isTransparentTheme\r\n ? 'rgba(15, 12, 30, 0.85)'\r\n : tokens.colors.background.elevated,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n boxShadow: tokens.shadows.lg,\r\n padding: tokens.spacing.xs,\r\n maxWidth: 'min(320px, calc(100vw - 16px))',\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n animation: `zendir-popover-enter 150ms ${tokens.animation.easing.default}`,\r\n ...(isTransparentTheme ? {\r\n backdropFilter: 'blur(16px)',\r\n WebkitBackdropFilter: 'blur(16px)',\r\n } : {}),\r\n ...style,\r\n }}\r\n >\r\n {children}\r\n </div>\r\n )}\r\n \r\n <style>{`\r\n @keyframes zendir-popover-enter {\r\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n `}</style>\r\n </PopoverContext.Provider>\r\n );\r\n});\r\n\r\n// ─── Menu ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface MenuProps {\r\n children: React.ReactNode;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst MenuRoot = memo(function Menu({ children, style }: MenuProps): React.ReactElement {\r\n return (\r\n <div role=\"menu\" style={{ minWidth: 'min(160px, calc(100vw - 32px))', ...style }}>\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Menu.Item ───────────────────────────────────────────────────────────────\r\n\r\nexport interface MenuItemProps {\r\n /** Click handler */\r\n onClick?: () => void;\r\n /** Icon (ReactNode or IconName string) */\r\n icon?: React.ReactNode;\r\n /** Label text */\r\n children: React.ReactNode;\r\n /** Disabled state */\r\n disabled?: boolean;\r\n /** Destructive action (red text) */\r\n destructive?: boolean;\r\n /** Keyboard shortcut hint */\r\n shortcut?: string;\r\n}\r\n\r\nconst MenuItem = memo(function MenuItem({\r\n onClick,\r\n icon,\r\n children,\r\n disabled = false,\r\n destructive = false,\r\n shortcut,\r\n}: MenuItemProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { close } = useContext(PopoverContext);\r\n const [isHovered, setIsHovered] = useState(false);\r\n \r\n const handleClick = useCallback(() => {\r\n if (disabled) return;\r\n onClick?.();\r\n close();\r\n }, [disabled, onClick, close]);\r\n \r\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\r\n const item = e.currentTarget;\r\n const siblings = item.parentElement?.querySelectorAll('[role=\"menuitem\"]:not([disabled])');\r\n if (!siblings) return;\r\n const items = Array.from(siblings) as HTMLElement[];\r\n const idx = items.indexOf(item as HTMLElement);\r\n \r\n if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n items[(idx + 1) % items.length]?.focus();\r\n } else if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n items[(idx - 1 + items.length) % items.length]?.focus();\r\n } else if (e.key === 'Home') {\r\n e.preventDefault();\r\n items[0]?.focus();\r\n } else if (e.key === 'End') {\r\n e.preventDefault();\r\n items[items.length - 1]?.focus();\r\n }\r\n }, []);\r\n \r\n const color = destructive\r\n ? tokens.colors.status.critical\r\n : disabled\r\n ? tokens.colors.text.tertiary\r\n : tokens.colors.text.primary;\r\n \r\n return (\r\n <button\r\n role=\"menuitem\"\r\n tabIndex={disabled ? -1 : 0}\r\n onClick={handleClick}\r\n onKeyDown={handleKeyDown}\r\n disabled={disabled}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => setIsHovered(false)}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: tokens.spacing.sm,\r\n width: '100%',\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.sm}`,\r\n minHeight: 44,\r\n border: 'none',\r\n background: isHovered && !disabled\r\n ? `${destructive ? tokens.colors.status.critical : tokens.colors.accent.primary}12`\r\n : 'transparent',\r\n color,\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontWeight: tokens.typography.fontWeight.normal,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n borderRadius: tokens.borderRadius.sm,\r\n textAlign: 'left',\r\n transition: tokens.animation.fast,\r\n opacity: disabled ? 0.5 : 1,\r\n outline: 'none',\r\n }}\r\n >\r\n {icon && <span style={{ flexShrink: 0, display: 'flex' }}>{icon}</span>}\r\n <span style={{ flex: 1 }}>{children}</span>\r\n {shortcut && (\r\n <span style={{\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n flexShrink: 0,\r\n }}>\r\n {shortcut}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n});\r\n\r\n// ─── Menu.Divider ────────────────────────────────────────────────────────────\r\n\r\nconst MenuDivider = memo(function MenuDivider(): React.ReactElement {\r\n const { tokens } = useTheme();\r\n return (\r\n <div\r\n role=\"separator\"\r\n style={{\r\n height: '1px',\r\n backgroundColor: tokens.colors.border.muted,\r\n margin: `${tokens.spacing.xs} 0`,\r\n }}\r\n />\r\n );\r\n});\r\n\r\n// ─── Menu.Label ──────────────────────────────────────────────────────────────\r\n\r\nconst MenuLabel = memo(function MenuLabel({ children }: { children: React.ReactNode }): React.ReactElement {\r\n const { tokens } = useTheme();\r\n return (\r\n <div style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: tokens.colors.text.tertiary,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.06em',\r\n }}>\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Compound Export ─────────────────────────────────────────────────────────\r\n\r\ntype MenuComponent = typeof MenuRoot & {\r\n Item: typeof MenuItem;\r\n Divider: typeof MenuDivider;\r\n Label: typeof MenuLabel;\r\n};\r\n\r\nexport const Menu: MenuComponent = Object.assign(MenuRoot, {\r\n Item: MenuItem,\r\n Divider: MenuDivider,\r\n Label: MenuLabel,\r\n});\r\n\r\nexport default Popover;\r\n"],"names":["Popover","Menu","MenuItem","MenuDivider","MenuLabel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover.js","names":[],"sources":["../../../../src/react/core/overlays/Popover.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - Popover & Menu Components\r\n *\r\n * General-purpose popover for dropdown menus, sort controls, action menus,\r\n * and contextual information. Portal-rendered with auto-positioning.\r\n *\r\n * Astro UX Compliance:\r\n * - Consistent with Dialog/Tooltip styling\r\n * - Focus trap for keyboard navigation\r\n * - Escape to close\r\n * - Click outside to close\r\n * - Reduced motion support\r\n *\r\n * @example\r\n * ```tsx\r\n * <Popover\r\n * trigger={<Button variant=\"secondary\">Sort</Button>}\r\n * placement=\"bottom-start\"\r\n * >\r\n * <Menu>\r\n * <Menu.Item onClick={...}>Sort by Time</Menu.Item>\r\n * <Menu.Item onClick={...}>Sort by Name</Menu.Item>\r\n * <Menu.Divider />\r\n * <Menu.Item onClick={...} destructive>Clear All</Menu.Item>\r\n * </Menu>\r\n * </Popover>\r\n * ```\r\n */\r\n\r\nimport React, {\r\n memo,\r\n useState,\r\n useRef,\r\n useEffect,\r\n useCallback,\r\n createContext,\r\n useContext,\r\n} from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\n\r\n// ─── Popover ─────────────────────────────────────────────────────────────────\r\n\r\nexport type PopoverPlacement =\r\n | \"top\"\r\n | \"top-start\"\r\n | \"top-end\"\r\n | \"bottom\"\r\n | \"bottom-start\"\r\n | \"bottom-end\"\r\n | \"left\"\r\n | \"left-start\"\r\n | \"left-end\"\r\n | \"right\"\r\n | \"right-start\"\r\n | \"right-end\";\r\n\r\nexport interface PopoverProps {\r\n /** Trigger element */\r\n trigger: React.ReactElement;\r\n /** Popover content */\r\n children: React.ReactNode;\r\n /** Placement relative to trigger */\r\n placement?: PopoverPlacement;\r\n /** Open on hover instead of click */\r\n hover?: boolean;\r\n /** Controlled open state */\r\n open?: boolean;\r\n /** Controlled open change */\r\n onOpenChange?: (open: boolean) => void;\r\n /** Close on content click */\r\n closeOnClick?: boolean;\r\n /** Width: 'trigger' matches trigger width, number for px, 'auto' */\r\n width?: \"trigger\" | \"auto\" | number;\r\n /** Custom style for popover panel */\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst PopoverContext = createContext<{ close: () => void }>({\r\n close: () => {},\r\n});\r\n\r\nexport const Popover = memo(function Popover({\r\n trigger,\r\n children,\r\n placement = \"bottom-start\",\r\n hover = false,\r\n open: controlledOpen,\r\n onOpenChange,\r\n closeOnClick = true,\r\n width = \"auto\",\r\n style,\r\n}: PopoverProps): React.ReactElement {\r\n const { tokens, theme } = useTheme();\r\n const isTransparentTheme =\r\n theme === \"transparent\" ||\r\n theme === \"transparent-bold\" ||\r\n theme === \"transparent-minimal\";\r\n const [internalOpen, setInternalOpen] = useState(false);\r\n const triggerRef = useRef<HTMLDivElement>(null);\r\n const popoverRef = useRef<HTMLDivElement>(null);\r\n const hoverTimeout = useRef<ReturnType<typeof setTimeout>>();\r\n\r\n const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;\r\n\r\n const setOpen = useCallback(\r\n (val: boolean) => {\r\n if (controlledOpen === undefined) setInternalOpen(val);\r\n onOpenChange?.(val);\r\n },\r\n [controlledOpen, onOpenChange],\r\n );\r\n\r\n const close = useCallback(() => setOpen(false), [setOpen]);\r\n\r\n // Click outside\r\n useEffect(() => {\r\n if (!isOpen) return;\r\n const handler = (e: MouseEvent) => {\r\n if (\r\n triggerRef.current &&\r\n !triggerRef.current.contains(e.target as Node) &&\r\n popoverRef.current &&\r\n !popoverRef.current.contains(e.target as Node)\r\n ) {\r\n close();\r\n }\r\n };\r\n document.addEventListener(\"mousedown\", handler);\r\n return () => document.removeEventListener(\"mousedown\", handler);\r\n }, [isOpen, close]);\r\n\r\n // Escape key + cleanup hoverTimeout on unmount\r\n useEffect(() => {\r\n if (!isOpen) return;\r\n const handler = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") close();\r\n };\r\n document.addEventListener(\"keydown\", handler);\r\n return () => document.removeEventListener(\"keydown\", handler);\r\n }, [isOpen, close]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n clearTimeout(hoverTimeout.current);\r\n };\r\n }, []);\r\n\r\n // Position calculation — `positioned` gates visibility so the panel is never\r\n // painted in document flow before the first RAF resolves coordinates.\r\n // Initializing with position: 'fixed' ensures that the hidden first-frame\r\n // measurement doesn't get constrained by the trigger's parent container.\r\n const [position, setPosition] = useState<React.CSSProperties>({\r\n position: \"fixed\",\r\n left: 0,\r\n top: 0,\r\n });\r\n const [positioned, setPositioned] = useState(false);\r\n\r\n // Reset visibility guard whenever the popover closes so the next open starts\r\n // hidden again rather than flashing the stale coordinates for one frame.\r\n useEffect(() => {\r\n if (!isOpen) setPositioned(false);\r\n }, [isOpen]);\r\n\r\n useEffect(() => {\r\n if (!isOpen || !triggerRef.current) return;\r\n const gap = 8;\r\n const viewportPadding = 8;\r\n\r\n const updatePosition = () => {\r\n const rect = triggerRef.current?.getBoundingClientRect();\r\n if (!rect) return;\r\n\r\n const panelWidth =\r\n width === \"trigger\"\r\n ? rect.width\r\n : typeof width === \"number\"\r\n ? width\r\n : (popoverRef.current?.offsetWidth ?? 220);\r\n const panelHeight = popoverRef.current?.offsetHeight ?? 220;\r\n\r\n let left = rect.left;\r\n let top = rect.bottom + gap;\r\n\r\n if (placement.startsWith(\"top\")) {\r\n top = rect.top - panelHeight - gap;\r\n } else if (placement.startsWith(\"bottom\")) {\r\n top = rect.bottom + gap;\r\n } else if (placement.startsWith(\"left\")) {\r\n left = rect.left - panelWidth - gap;\r\n } else if (placement.startsWith(\"right\")) {\r\n left = rect.right + gap;\r\n }\r\n\r\n if (placement.startsWith(\"top\") || placement.startsWith(\"bottom\")) {\r\n if (placement.endsWith(\"-start\")) {\r\n left = rect.left;\r\n } else if (placement.endsWith(\"-end\")) {\r\n left = rect.right - panelWidth;\r\n } else {\r\n left = rect.left + (rect.width - panelWidth) / 2;\r\n }\r\n } else {\r\n if (placement.endsWith(\"-start\")) {\r\n top = rect.top;\r\n } else if (placement.endsWith(\"-end\")) {\r\n top = rect.bottom - panelHeight;\r\n } else {\r\n top = rect.top + (rect.height - panelHeight) / 2;\r\n }\r\n }\r\n\r\n left = Math.max(\r\n viewportPadding,\r\n Math.min(left, window.innerWidth - panelWidth - viewportPadding),\r\n );\r\n top = Math.max(\r\n viewportPadding,\r\n Math.min(top, window.innerHeight - panelHeight - viewportPadding),\r\n );\r\n\r\n const pos: React.CSSProperties = {\r\n position: \"fixed\",\r\n zIndex: 9990,\r\n left,\r\n top,\r\n };\r\n\r\n if (width === \"trigger\") {\r\n pos.width = rect.width;\r\n pos.minWidth = rect.width;\r\n } else if (typeof width === \"number\") {\r\n pos.width = width;\r\n }\r\n\r\n setPosition(pos);\r\n setPositioned(true);\r\n };\r\n\r\n const raf = requestAnimationFrame(updatePosition);\r\n window.addEventListener(\"resize\", updatePosition);\r\n window.addEventListener(\"scroll\", updatePosition, true);\r\n return () => {\r\n cancelAnimationFrame(raf);\r\n window.removeEventListener(\"resize\", updatePosition);\r\n window.removeEventListener(\"scroll\", updatePosition, true);\r\n };\r\n }, [isOpen, placement, width]);\r\n\r\n const triggerProps: Record<string, (() => void) | undefined> = {};\r\n if (hover) {\r\n triggerProps.onMouseEnter = () => {\r\n clearTimeout(hoverTimeout.current);\r\n setOpen(true);\r\n };\r\n triggerProps.onMouseLeave = () => {\r\n hoverTimeout.current = setTimeout(close, 150);\r\n };\r\n } else {\r\n triggerProps.onClick = () => setOpen(!isOpen);\r\n }\r\n\r\n const popoverHoverProps = hover\r\n ? {\r\n onMouseEnter: () => clearTimeout(hoverTimeout.current),\r\n onMouseLeave: () => {\r\n hoverTimeout.current = setTimeout(close, 150);\r\n },\r\n }\r\n : {};\r\n\r\n return (\r\n <PopoverContext.Provider value={{ close }}>\r\n <div\r\n ref={triggerRef}\r\n style={{ display: \"inline-flex\" }}\r\n aria-expanded={isOpen}\r\n aria-haspopup=\"true\"\r\n {...triggerProps}\r\n >\r\n {trigger}\r\n </div>\r\n\r\n {isOpen && (\r\n <div\r\n ref={popoverRef}\r\n role=\"dialog\"\r\n onClick={closeOnClick ? close : undefined}\r\n {...popoverHoverProps}\r\n style={{\r\n ...position,\r\n visibility: positioned ? \"visible\" : \"hidden\",\r\n backgroundColor: isTransparentTheme\r\n ? \"rgba(15, 12, 30, 0.85)\"\r\n : tokens.colors.background.elevated,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n boxShadow: tokens.shadows.lg,\r\n padding: tokens.spacing.xs,\r\n maxWidth: \"min(320px, calc(100vw - 16px))\",\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n animation: `zendir-popover-enter 150ms ${tokens.animation.easing.default}`,\r\n ...(isTransparentTheme\r\n ? {\r\n backdropFilter: \"blur(16px)\",\r\n WebkitBackdropFilter: \"blur(16px)\",\r\n }\r\n : {}),\r\n ...style,\r\n }}\r\n >\r\n {children}\r\n </div>\r\n )}\r\n\r\n <style>{`\r\n @keyframes zendir-popover-enter {\r\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n `}</style>\r\n </PopoverContext.Provider>\r\n );\r\n});\r\n\r\n// ─── Menu ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface MenuProps {\r\n children: React.ReactNode;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst MenuRoot = memo(function Menu({\r\n children,\r\n style,\r\n}: MenuProps): React.ReactElement {\r\n return (\r\n <div\r\n role=\"menu\"\r\n style={{ minWidth: \"min(160px, calc(100vw - 32px))\", ...style }}\r\n >\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Menu.Item ───────────────────────────────────────────────────────────────\r\n\r\nexport interface MenuItemProps {\r\n /** Click handler */\r\n onClick?: () => void;\r\n /** Icon (ReactNode or IconName string) */\r\n icon?: React.ReactNode;\r\n /** Label text */\r\n children: React.ReactNode;\r\n /** Disabled state */\r\n disabled?: boolean;\r\n /** Destructive action (red text) */\r\n destructive?: boolean;\r\n /** Keyboard shortcut hint */\r\n shortcut?: string;\r\n}\r\n\r\nconst MenuItem = memo(function MenuItem({\r\n onClick,\r\n icon,\r\n children,\r\n disabled = false,\r\n destructive = false,\r\n shortcut,\r\n}: MenuItemProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { close } = useContext(PopoverContext);\r\n const [isHovered, setIsHovered] = useState(false);\r\n\r\n const handleClick = useCallback(() => {\r\n if (disabled) return;\r\n onClick?.();\r\n close();\r\n }, [disabled, onClick, close]);\r\n\r\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\r\n const item = e.currentTarget;\r\n const siblings = item.parentElement?.querySelectorAll(\r\n '[role=\"menuitem\"]:not([disabled])',\r\n );\r\n if (!siblings) return;\r\n const items = Array.from(siblings) as HTMLElement[];\r\n const idx = items.indexOf(item as HTMLElement);\r\n\r\n if (e.key === \"ArrowDown\") {\r\n e.preventDefault();\r\n items[(idx + 1) % items.length]?.focus();\r\n } else if (e.key === \"ArrowUp\") {\r\n e.preventDefault();\r\n items[(idx - 1 + items.length) % items.length]?.focus();\r\n } else if (e.key === \"Home\") {\r\n e.preventDefault();\r\n items[0]?.focus();\r\n } else if (e.key === \"End\") {\r\n e.preventDefault();\r\n items[items.length - 1]?.focus();\r\n }\r\n }, []);\r\n\r\n const color = destructive\r\n ? tokens.colors.status.critical\r\n : disabled\r\n ? tokens.colors.text.tertiary\r\n : tokens.colors.text.primary;\r\n\r\n return (\r\n <button\r\n role=\"menuitem\"\r\n tabIndex={disabled ? -1 : 0}\r\n onClick={handleClick}\r\n onKeyDown={handleKeyDown}\r\n disabled={disabled}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => setIsHovered(false)}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n width: \"100%\",\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.sm}`,\r\n minHeight: 44,\r\n border: \"none\",\r\n background:\r\n isHovered && !disabled\r\n ? `${destructive ? tokens.colors.status.critical : tokens.colors.accent.primary}12`\r\n : \"transparent\",\r\n color,\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontWeight: tokens.typography.fontWeight.normal,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n cursor: disabled ? \"not-allowed\" : \"pointer\",\r\n borderRadius: tokens.borderRadius.sm,\r\n textAlign: \"left\",\r\n transition: tokens.animation.fast,\r\n opacity: disabled ? 0.5 : 1,\r\n outline: \"none\",\r\n }}\r\n >\r\n {icon && <span style={{ flexShrink: 0, display: \"flex\" }}>{icon}</span>}\r\n <span style={{ flex: 1 }}>{children}</span>\r\n {shortcut && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n flexShrink: 0,\r\n }}\r\n >\r\n {shortcut}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n});\r\n\r\n// ─── Menu.Divider ────────────────────────────────────────────────────────────\r\n\r\nconst MenuDivider = memo(function MenuDivider(): React.ReactElement {\r\n const { tokens } = useTheme();\r\n return (\r\n <div\r\n role=\"separator\"\r\n style={{\r\n height: \"1px\",\r\n backgroundColor: tokens.colors.border.muted,\r\n margin: `${tokens.spacing.xs} 0`,\r\n }}\r\n />\r\n );\r\n});\r\n\r\n// ─── Menu.Label ──────────────────────────────────────────────────────────────\r\n\r\nconst MenuLabel = memo(function MenuLabel({\r\n children,\r\n}: {\r\n children: React.ReactNode;\r\n}): React.ReactElement {\r\n const { tokens } = useTheme();\r\n return (\r\n <div\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: tokens.colors.text.tertiary,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.06em\",\r\n }}\r\n >\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Compound Export ─────────────────────────────────────────────────────────\r\n\r\ntype MenuComponent = typeof MenuRoot & {\r\n Item: typeof MenuItem;\r\n Divider: typeof MenuDivider;\r\n Label: typeof MenuLabel;\r\n};\r\n\r\nexport const Menu: MenuComponent = Object.assign(MenuRoot, {\r\n Item: MenuItem,\r\n Divider: MenuDivider,\r\n Label: MenuLabel,\r\n});\r\n\r\nexport default Popover;\r\n"],"mappings":"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"}
|
|
@@ -1,216 +1,221 @@
|
|
|
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 { classNames } from "../../utils/index.js";
|
|
5
3
|
import { useBreakpoint } from "../layout/useBreakpoint.js";
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
4
|
+
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/react/core/overlays/SidePanel.tsx
|
|
7
|
+
/**
|
|
8
|
+
* @zendir/ui - SidePanel Component
|
|
9
|
+
*
|
|
10
|
+
* A sliding panel that pushes content instead of overlaying it.
|
|
11
|
+
* Designed to be placed as a flex sibling so the parent layout
|
|
12
|
+
* naturally adjusts when the panel opens/closes.
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - Push-content behavior (flex sibling, content adjusts automatically)
|
|
16
|
+
* - Smooth slide-in/out animation
|
|
17
|
+
* - Configurable width, position (left/right)
|
|
18
|
+
* - Optional overlay backdrop (for modal-like behavior)
|
|
19
|
+
* - Theme-integrated via useTheme()
|
|
20
|
+
* - Accessible (focus trap, keyboard support)
|
|
21
|
+
* - Close on escape key
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* // Push-content pattern: SidePanel as flex sibling
|
|
26
|
+
* <div style={{ display: 'flex', height: '100vh' }}>
|
|
27
|
+
* <main style={{ flex: 1, transition: 'all 0.3s ease' }}>
|
|
28
|
+
* {children}
|
|
29
|
+
* </main>
|
|
30
|
+
* <SidePanel
|
|
31
|
+
* open={isChatOpen}
|
|
32
|
+
* onClose={() => setIsChatOpen(false)}
|
|
33
|
+
* title="Chat Assistant"
|
|
34
|
+
* width={380}
|
|
35
|
+
* >
|
|
36
|
+
* <ChatPanel messages={messages} onSend={handleSend} />
|
|
37
|
+
* </SidePanel>
|
|
38
|
+
* </div>
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
var sidePanelInstanceCount = 0;
|
|
42
|
+
var SidePanel = memo(function SidePanel({ open, onClose, title, width = 380, position = "right", showCloseButton = true, closeOnEscape = true, overlay = false, closeOnOverlayClick = true, children, headerActions, headerLeading, onHeaderClick, headerStyle: headerStyleProp, className = "", style: styleProp }) {
|
|
43
|
+
const { tokens, theme } = useTheme();
|
|
44
|
+
const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
|
|
45
|
+
const panelRef = useRef(null);
|
|
46
|
+
const [animState, setAnimState] = useState("closed");
|
|
47
|
+
useRef(++sidePanelInstanceCount);
|
|
48
|
+
const { isMobile } = useBreakpoint();
|
|
49
|
+
const resolvedWidth = isMobile ? "100%" : typeof width === "number" ? `${width}px` : width;
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (open) {
|
|
52
|
+
setAnimState("opening");
|
|
53
|
+
const timer = setTimeout(() => setAnimState("open"), 30);
|
|
54
|
+
return () => clearTimeout(timer);
|
|
55
|
+
} else if (animState === "open" || animState === "opening") {
|
|
56
|
+
setAnimState("closing");
|
|
57
|
+
const timer = setTimeout(() => setAnimState("closed"), 550);
|
|
58
|
+
return () => clearTimeout(timer);
|
|
59
|
+
}
|
|
60
|
+
}, [open]);
|
|
61
|
+
const handleKeyDown = useCallback((e) => {
|
|
62
|
+
if (closeOnEscape && e.key === "Escape") onClose();
|
|
63
|
+
}, [closeOnEscape, onClose]);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (open) {
|
|
66
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
67
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
68
|
+
}
|
|
69
|
+
}, [open, handleKeyDown]);
|
|
70
|
+
if (animState === "closed") return null;
|
|
71
|
+
const isVisible = animState === "open";
|
|
72
|
+
const slideFrom = position === "right" ? "translateX(100%)" : "translateX(-100%)";
|
|
73
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [overlay && /* @__PURE__ */ jsx("div", {
|
|
74
|
+
className: "zendir-sidepanel-overlay",
|
|
75
|
+
onClick: closeOnOverlayClick ? onClose : void 0,
|
|
76
|
+
style: {
|
|
77
|
+
position: "fixed",
|
|
78
|
+
inset: 0,
|
|
79
|
+
backgroundColor: isTransparentTheme ? `${tokens.colors.background.base}4D` : `${tokens.colors.background.base}66`,
|
|
80
|
+
backdropFilter: isTransparentTheme ? "blur(2px)" : void 0,
|
|
81
|
+
WebkitBackdropFilter: isTransparentTheme ? "blur(2px)" : void 0,
|
|
82
|
+
zIndex: 999,
|
|
83
|
+
opacity: isVisible ? 1 : 0,
|
|
84
|
+
transition: "opacity 0.3s ease",
|
|
85
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
86
|
+
}
|
|
87
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
88
|
+
ref: panelRef,
|
|
89
|
+
className: classNames("zendir-sidepanel", className),
|
|
90
|
+
style: {
|
|
91
|
+
width: isVisible ? resolvedWidth : "0px",
|
|
92
|
+
minWidth: isVisible ? resolvedWidth : "0px",
|
|
93
|
+
maxWidth: resolvedWidth,
|
|
94
|
+
height: "100%",
|
|
95
|
+
overflow: "hidden",
|
|
96
|
+
transition: "width 0.6s cubic-bezier(0.2, 0.8, 0.2, 1), min-width 0.6s cubic-bezier(0.2, 0.8, 0.2, 1)",
|
|
97
|
+
flexShrink: 0,
|
|
98
|
+
position: "relative",
|
|
99
|
+
zIndex: overlay ? 1e3 : "auto",
|
|
100
|
+
...overlay && {
|
|
101
|
+
position: "fixed",
|
|
102
|
+
top: 0,
|
|
103
|
+
[position]: 0
|
|
104
|
+
},
|
|
105
|
+
...styleProp
|
|
106
|
+
},
|
|
107
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
108
|
+
style: {
|
|
109
|
+
width: resolvedWidth,
|
|
110
|
+
height: "100%",
|
|
111
|
+
display: "flex",
|
|
112
|
+
flexDirection: "column",
|
|
113
|
+
backgroundColor: isTransparentTheme ? "rgba(15, 15, 35, 0.85)" : tokens.colors.background.surface,
|
|
114
|
+
...isTransparentTheme && {
|
|
115
|
+
backdropFilter: "blur(16px)",
|
|
116
|
+
WebkitBackdropFilter: "blur(16px)"
|
|
117
|
+
},
|
|
118
|
+
borderLeft: position === "right" ? tokens.borders.divider : void 0,
|
|
119
|
+
borderRight: position === "left" ? tokens.borders.divider : void 0,
|
|
120
|
+
transform: isVisible ? "translateX(0)" : slideFrom,
|
|
121
|
+
transition: "transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1)",
|
|
122
|
+
overflow: "hidden"
|
|
123
|
+
},
|
|
124
|
+
children: [(title || showCloseButton || headerActions || headerLeading) && /* @__PURE__ */ jsxs("div", {
|
|
125
|
+
onClick: onHeaderClick,
|
|
126
|
+
role: onHeaderClick ? "button" : void 0,
|
|
127
|
+
tabIndex: onHeaderClick ? 0 : void 0,
|
|
128
|
+
onKeyDown: onHeaderClick ? (e) => {
|
|
129
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
onHeaderClick();
|
|
132
|
+
}
|
|
133
|
+
} : void 0,
|
|
134
|
+
style: {
|
|
135
|
+
display: "flex",
|
|
136
|
+
alignItems: "center",
|
|
137
|
+
justifyContent: "space-between",
|
|
138
|
+
padding: `${tokens.spacing.md} ${tokens.spacing.md}`,
|
|
139
|
+
borderBottom: tokens.borders.divider,
|
|
140
|
+
flexShrink: 0,
|
|
141
|
+
gap: tokens.spacing.sm,
|
|
142
|
+
...onHeaderClick && { cursor: "pointer" },
|
|
143
|
+
...headerStyleProp
|
|
144
|
+
},
|
|
145
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
146
|
+
style: {
|
|
147
|
+
display: "flex",
|
|
148
|
+
alignItems: "center",
|
|
149
|
+
gap: tokens.spacing.sm,
|
|
150
|
+
flex: 1,
|
|
151
|
+
minWidth: 0
|
|
152
|
+
},
|
|
153
|
+
children: [headerLeading, title && /* @__PURE__ */ jsx("h3", {
|
|
154
|
+
style: {
|
|
155
|
+
margin: 0,
|
|
156
|
+
fontSize: tokens.typography.fontSize.base,
|
|
157
|
+
fontWeight: tokens.typography.fontWeight.semibold,
|
|
158
|
+
color: tokens.colors.text.primary,
|
|
159
|
+
whiteSpace: "nowrap",
|
|
160
|
+
overflow: "hidden",
|
|
161
|
+
textOverflow: "ellipsis"
|
|
162
|
+
},
|
|
163
|
+
children: title
|
|
164
|
+
})]
|
|
165
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
166
|
+
style: {
|
|
167
|
+
display: "flex",
|
|
168
|
+
alignItems: "center",
|
|
169
|
+
gap: tokens.spacing.xs,
|
|
170
|
+
flexShrink: 0
|
|
171
|
+
},
|
|
172
|
+
children: [headerActions, showCloseButton && /* @__PURE__ */ jsx("button", {
|
|
173
|
+
type: "button",
|
|
174
|
+
onClick: onClose,
|
|
175
|
+
"aria-label": "Close panel",
|
|
176
|
+
style: {
|
|
177
|
+
padding: tokens.spacing.sm,
|
|
178
|
+
minWidth: 44,
|
|
179
|
+
minHeight: 44,
|
|
180
|
+
backgroundColor: "transparent",
|
|
181
|
+
border: "none",
|
|
182
|
+
borderRadius: tokens.borderRadius.sm,
|
|
183
|
+
cursor: "pointer",
|
|
184
|
+
color: tokens.colors.text.muted ?? tokens.colors.text.tertiary,
|
|
185
|
+
display: "flex",
|
|
186
|
+
alignItems: "center",
|
|
187
|
+
justifyContent: "center",
|
|
188
|
+
transition: `color 0.15s ease, background-color 0.15s ease`
|
|
189
|
+
},
|
|
190
|
+
onMouseEnter: (e) => {
|
|
191
|
+
e.currentTarget.style.color = tokens.colors.text.primary;
|
|
192
|
+
e.currentTarget.style.backgroundColor = tokens.colors.background.base;
|
|
193
|
+
},
|
|
194
|
+
onMouseLeave: (e) => {
|
|
195
|
+
e.currentTarget.style.color = tokens.colors.text.muted ?? tokens.colors.text.tertiary;
|
|
196
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
197
|
+
},
|
|
198
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
199
|
+
width: "20",
|
|
200
|
+
height: "20",
|
|
201
|
+
viewBox: "0 0 24 24",
|
|
202
|
+
fill: "currentColor",
|
|
203
|
+
children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })
|
|
204
|
+
})
|
|
205
|
+
})]
|
|
206
|
+
})]
|
|
207
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
208
|
+
style: {
|
|
209
|
+
flex: 1,
|
|
210
|
+
overflow: "auto",
|
|
211
|
+
minHeight: 0
|
|
212
|
+
},
|
|
213
|
+
children
|
|
214
|
+
})]
|
|
215
|
+
})
|
|
216
|
+
})] });
|
|
212
217
|
});
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
//# sourceMappingURL=SidePanel.js.map
|
|
218
|
+
//#endregion
|
|
219
|
+
export { SidePanel, SidePanel as default };
|
|
220
|
+
|
|
221
|
+
//# sourceMappingURL=SidePanel.js.map
|