@zendir/ui 0.1.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 +19 -0
- package/LICENSE +21 -0
- package/README.md +589 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +421 -0
- package/dist/index.js.map +1 -0
- package/dist/react/3d/EarthViewer.d.ts +46 -0
- package/dist/react/3d/EarthViewer.js +836 -0
- package/dist/react/3d/EarthViewer.js.map +1 -0
- package/dist/react/3d/SolarSystemViewer.d.ts +43 -0
- package/dist/react/3d/SolarSystemViewer.js +372 -0
- package/dist/react/3d/SolarSystemViewer.js.map +1 -0
- package/dist/react/3d/ZenSpace3D.d.ts +16 -0
- package/dist/react/3d/ZenSpace3D.js +1253 -0
- package/dist/react/3d/ZenSpace3D.js.map +1 -0
- package/dist/react/3d/ZenSpace3DCesium.d.ts +9 -0
- package/dist/react/3d/ZenSpace3DCesium.js +186 -0
- package/dist/react/3d/ZenSpace3DCesium.js.map +1 -0
- package/dist/react/3d/ZenSpace3DShaders.d.ts +78 -0
- package/dist/react/3d/ZenSpace3DShaders.js +94 -0
- package/dist/react/3d/ZenSpace3DShaders.js.map +1 -0
- package/dist/react/3d/ZenSpace3DTypes.d.ts +614 -0
- package/dist/react/3d/ZenSpace3DUtils.d.ts +183 -0
- package/dist/react/3d/ZenSpace3DUtils.js +213 -0
- package/dist/react/3d/ZenSpace3DUtils.js.map +1 -0
- package/dist/react/3d/index.d.ts +23 -0
- package/dist/react/3d/threeLoader.d.ts +22 -0
- package/dist/react/3d/threeLoader.js +18 -0
- package/dist/react/3d/threeLoader.js.map +1 -0
- package/dist/react/astro/ClassificationBanner.d.ts +25 -0
- package/dist/react/astro/ClassificationBanner.js +83 -0
- package/dist/react/astro/ClassificationBanner.js.map +1 -0
- package/dist/react/astro/GlobalStatusBar.d.ts +42 -0
- package/dist/react/astro/GlobalStatusBar.js +165 -0
- package/dist/react/astro/GlobalStatusBar.js.map +1 -0
- package/dist/react/astro/MissionClock.d.ts +169 -0
- package/dist/react/astro/MissionClock.js +411 -0
- package/dist/react/astro/MissionClock.js.map +1 -0
- package/dist/react/astro/MonitoringIcon.d.ts +60 -0
- package/dist/react/astro/MonitoringIcon.js +369 -0
- package/dist/react/astro/MonitoringIcon.js.map +1 -0
- package/dist/react/astro/Notification.d.ts +42 -0
- package/dist/react/astro/Notification.js +156 -0
- package/dist/react/astro/Notification.js.map +1 -0
- package/dist/react/astro/Progress.d.ts +39 -0
- package/dist/react/astro/Progress.js +149 -0
- package/dist/react/astro/Progress.js.map +1 -0
- package/dist/react/astro/SimulationControls.d.ts +136 -0
- package/dist/react/astro/SimulationControls.js +668 -0
- package/dist/react/astro/SimulationControls.js.map +1 -0
- package/dist/react/astro/StatusIndicator.d.ts +34 -0
- package/dist/react/astro/StatusIndicator.js +189 -0
- package/dist/react/astro/StatusIndicator.js.map +1 -0
- package/dist/react/astro/UnifiedTimeline.d.ts +106 -0
- package/dist/react/astro/UnifiedTimeline.js +1768 -0
- package/dist/react/astro/UnifiedTimeline.js.map +1 -0
- package/dist/react/astro/index.d.ts +63 -0
- package/dist/react/cards/AccessCard.d.ts +37 -0
- package/dist/react/cards/AccessCard.js +410 -0
- package/dist/react/cards/AccessCard.js.map +1 -0
- package/dist/react/cards/OrbitCard.d.ts +31 -0
- package/dist/react/cards/OrbitCard.js +372 -0
- package/dist/react/cards/OrbitCard.js.map +1 -0
- package/dist/react/cards/SpacecraftCard.d.ts +54 -0
- package/dist/react/cards/SpacecraftCard.js +941 -0
- package/dist/react/cards/SpacecraftCard.js.map +1 -0
- package/dist/react/cards/TelemetryCard.d.ts +40 -0
- package/dist/react/cards/TelemetryCard.js +742 -0
- package/dist/react/cards/TelemetryCard.js.map +1 -0
- package/dist/react/cards/TelemetryStreamCard.d.ts +59 -0
- package/dist/react/cards/TelemetryStreamCard.js +309 -0
- package/dist/react/cards/TelemetryStreamCard.js.map +1 -0
- package/dist/react/cards/index.d.ts +13 -0
- package/dist/react/charts/GroundTrackMap.d.ts +112 -0
- package/dist/react/charts/GroundTrackMap.js +1123 -0
- package/dist/react/charts/GroundTrackMap.js.map +1 -0
- package/dist/react/charts/GroundTrackMapLeaflet.d.ts +26 -0
- package/dist/react/charts/GroundTrackMapLeaflet.js +571 -0
- package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -0
- package/dist/react/charts/groundTrackMapLeafletTiles.d.ts +22 -0
- package/dist/react/charts/groundTrackMapLeafletTiles.js +11 -0
- package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -0
- package/dist/react/charts/groundTrackMapLeafletUtils.d.ts +24 -0
- package/dist/react/charts/groundTrackMapLeafletUtils.js +109 -0
- package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -0
- package/dist/react/charts/index.d.ts +10 -0
- package/dist/react/charts/unified/AstroChart.d.ts +24 -0
- package/dist/react/charts/unified/AstroChart.js +1405 -0
- package/dist/react/charts/unified/AstroChart.js.map +1 -0
- package/dist/react/charts/unified/PowerOverviewChart.d.ts +73 -0
- package/dist/react/charts/unified/PowerOverviewChart.js +488 -0
- package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -0
- package/dist/react/charts/unified/domain.d.ts +845 -0
- package/dist/react/charts/unified/domain.js +3168 -0
- package/dist/react/charts/unified/domain.js.map +1 -0
- package/dist/react/charts/unified/generators.d.ts +276 -0
- package/dist/react/charts/unified/generators.js +518 -0
- package/dist/react/charts/unified/generators.js.map +1 -0
- package/dist/react/charts/unified/index.d.ts +55 -0
- package/dist/react/charts/unified/presets.d.ts +290 -0
- package/dist/react/charts/unified/presets.js +999 -0
- package/dist/react/charts/unified/presets.js.map +1 -0
- package/dist/react/charts/unified/sync.d.ts +69 -0
- package/dist/react/charts/unified/sync.js +219 -0
- package/dist/react/charts/unified/sync.js.map +1 -0
- package/dist/react/charts/unified/theme.d.ts +447 -0
- package/dist/react/charts/unified/theme.js +562 -0
- package/dist/react/charts/unified/theme.js.map +1 -0
- package/dist/react/charts/unified/types.d.ts +826 -0
- package/dist/react/charts/unified/useChartStream.d.ts +58 -0
- package/dist/react/charts/unified/useChartStream.js +226 -0
- package/dist/react/charts/unified/useChartStream.js.map +1 -0
- package/dist/react/chatgpt/AppCard.d.ts +59 -0
- package/dist/react/chatgpt/AppCard.js +306 -0
- package/dist/react/chatgpt/AppCard.js.map +1 -0
- package/dist/react/chatgpt/ChatGPTCard.d.ts +6 -0
- package/dist/react/chatgpt/index.d.ts +167 -0
- package/dist/react/chatgpt/index.js +166 -0
- package/dist/react/chatgpt/index.js.map +1 -0
- package/dist/react/context/DisplaySettingsContext.d.ts +107 -0
- package/dist/react/context/DisplaySettingsContext.js +169 -0
- package/dist/react/context/DisplaySettingsContext.js.map +1 -0
- package/dist/react/context/index.d.ts +5 -0
- package/dist/react/core/ActivityPlanner.d.ts +45 -0
- package/dist/react/core/ActivityPlanner.js +532 -0
- package/dist/react/core/ActivityPlanner.js.map +1 -0
- package/dist/react/core/AppBar.d.ts +71 -0
- package/dist/react/core/AppBar.js +817 -0
- package/dist/react/core/AppBar.js.map +1 -0
- package/dist/react/core/AstroIcon.d.ts +84 -0
- package/dist/react/core/AstroIcon.js +1243 -0
- package/dist/react/core/AstroIcon.js.map +1 -0
- package/dist/react/core/Badge.d.ts +27 -0
- package/dist/react/core/Badge.js +134 -0
- package/dist/react/core/Badge.js.map +1 -0
- package/dist/react/core/Button.d.ts +26 -0
- package/dist/react/core/Button.js +306 -0
- package/dist/react/core/Button.js.map +1 -0
- package/dist/react/core/CardHeader.d.ts +34 -0
- package/dist/react/core/CardHeader.js +316 -0
- package/dist/react/core/CardHeader.js.map +1 -0
- package/dist/react/core/ChatPanel.d.ts +627 -0
- package/dist/react/core/ChatPanel.js +1144 -0
- package/dist/react/core/ChatPanel.js.map +1 -0
- package/dist/react/core/Checkbox.d.ts +26 -0
- package/dist/react/core/Checkbox.js +130 -0
- package/dist/react/core/Checkbox.js.map +1 -0
- package/dist/react/core/ColorPickerPanel.d.ts +25 -0
- package/dist/react/core/ColorPickerPanel.js +293 -0
- package/dist/react/core/ColorPickerPanel.js.map +1 -0
- package/dist/react/core/CommandBuilder.d.ts +74 -0
- package/dist/react/core/CommandBuilder.js +518 -0
- package/dist/react/core/CommandBuilder.js.map +1 -0
- package/dist/react/core/ConfirmDialog.d.ts +45 -0
- package/dist/react/core/ConfirmDialog.js +315 -0
- package/dist/react/core/ConfirmDialog.js.map +1 -0
- package/dist/react/core/ConnectionForm.d.ts +57 -0
- package/dist/react/core/ConnectionForm.js +496 -0
- package/dist/react/core/ConnectionForm.js.map +1 -0
- package/dist/react/core/Container.d.ts +51 -0
- package/dist/react/core/Container.js +670 -0
- package/dist/react/core/Container.js.map +1 -0
- package/dist/react/core/CopyButton.d.ts +39 -0
- package/dist/react/core/CopyButton.js +105 -0
- package/dist/react/core/CopyButton.js.map +1 -0
- package/dist/react/core/DataTable.d.ts +113 -0
- package/dist/react/core/DataTable.js +446 -0
- package/dist/react/core/DataTable.js.map +1 -0
- package/dist/react/core/DataValue.d.ts +64 -0
- package/dist/react/core/DataValue.js +545 -0
- package/dist/react/core/DataValue.js.map +1 -0
- package/dist/react/core/Dialog.d.ts +32 -0
- package/dist/react/core/Dialog.js +201 -0
- package/dist/react/core/Dialog.js.map +1 -0
- package/dist/react/core/FileExplorer.d.ts +65 -0
- package/dist/react/core/FileExplorer.js +520 -0
- package/dist/react/core/FileExplorer.js.map +1 -0
- package/dist/react/core/GlassCard.d.ts +129 -0
- package/dist/react/core/GlassCard.js +375 -0
- package/dist/react/core/GlassCard.js.map +1 -0
- package/dist/react/core/HeaderIconWithStatus.d.ts +39 -0
- package/dist/react/core/HeaderIconWithStatus.js +157 -0
- package/dist/react/core/HeaderIconWithStatus.js.map +1 -0
- package/dist/react/core/HexViewer.d.ts +143 -0
- package/dist/react/core/HexViewer.js +1106 -0
- package/dist/react/core/HexViewer.js.map +1 -0
- package/dist/react/core/Icon.d.ts +32 -0
- package/dist/react/core/Icon.js +142 -0
- package/dist/react/core/Icon.js.map +1 -0
- package/dist/react/core/ImageGallery.d.ts +41 -0
- package/dist/react/core/ImageGallery.js +320 -0
- package/dist/react/core/ImageGallery.js.map +1 -0
- package/dist/react/core/Input.d.ts +38 -0
- package/dist/react/core/Input.js +288 -0
- package/dist/react/core/Input.js.map +1 -0
- package/dist/react/core/LimitsBar.d.ts +51 -0
- package/dist/react/core/LimitsBar.js +200 -0
- package/dist/react/core/LimitsBar.js.map +1 -0
- package/dist/react/core/LogViewer.d.ts +61 -0
- package/dist/react/core/LogViewer.js +599 -0
- package/dist/react/core/LogViewer.js.map +1 -0
- package/dist/react/core/MessageStream.d.ts +58 -0
- package/dist/react/core/MessageStream.js +455 -0
- package/dist/react/core/MessageStream.js.map +1 -0
- package/dist/react/core/MissionCalendar.d.ts +81 -0
- package/dist/react/core/MissionCalendar.js +1049 -0
- package/dist/react/core/MissionCalendar.js.map +1 -0
- package/dist/react/core/NumberInput.d.ts +85 -0
- package/dist/react/core/NumberInput.js +507 -0
- package/dist/react/core/NumberInput.js.map +1 -0
- package/dist/react/core/PacketViewer.d.ts +73 -0
- package/dist/react/core/PacketViewer.js +431 -0
- package/dist/react/core/PacketViewer.js.map +1 -0
- package/dist/react/core/Pagination.d.ts +30 -0
- package/dist/react/core/Pagination.js +190 -0
- package/dist/react/core/Pagination.js.map +1 -0
- package/dist/react/core/PinInput.d.ts +41 -0
- package/dist/react/core/PinInput.js +210 -0
- package/dist/react/core/PinInput.js.map +1 -0
- package/dist/react/core/Popover.d.ts +55 -0
- package/dist/react/core/Popover.js +288 -0
- package/dist/react/core/Popover.js.map +1 -0
- package/dist/react/core/Select.d.ts +42 -0
- package/dist/react/core/Select.js +303 -0
- package/dist/react/core/Select.js.map +1 -0
- package/dist/react/core/SideNav.d.ts +103 -0
- package/dist/react/core/SideNav.js +551 -0
- package/dist/react/core/SideNav.js.map +1 -0
- package/dist/react/core/SidePanel.d.ts +33 -0
- package/dist/react/core/SidePanel.js +199 -0
- package/dist/react/core/SidePanel.js.map +1 -0
- package/dist/react/core/Tabs.d.ts +47 -0
- package/dist/react/core/Tabs.js +129 -0
- package/dist/react/core/Tabs.js.map +1 -0
- package/dist/react/core/Toast.d.ts +56 -0
- package/dist/react/core/Toast.js +229 -0
- package/dist/react/core/Toast.js.map +1 -0
- package/dist/react/core/Toggle.d.ts +22 -0
- package/dist/react/core/Toggle.js +151 -0
- package/dist/react/core/Toggle.js.map +1 -0
- package/dist/react/core/Tooltip.d.ts +19 -0
- package/dist/react/core/Tooltip.js +179 -0
- package/dist/react/core/Tooltip.js.map +1 -0
- package/dist/react/core/Typography.d.ts +127 -0
- package/dist/react/core/Typography.js +187 -0
- package/dist/react/core/Typography.js.map +1 -0
- package/dist/react/core/index.d.ts +108 -0
- package/dist/react/core/layout/Box.d.ts +77 -0
- package/dist/react/core/layout/Box.js +126 -0
- package/dist/react/core/layout/Box.js.map +1 -0
- package/dist/react/core/layout/Center.d.ts +20 -0
- package/dist/react/core/layout/Center.js +34 -0
- package/dist/react/core/layout/Center.js.map +1 -0
- package/dist/react/core/layout/Divider.d.ts +16 -0
- package/dist/react/core/layout/Divider.js +108 -0
- package/dist/react/core/layout/Divider.js.map +1 -0
- package/dist/react/core/layout/Flex.d.ts +30 -0
- package/dist/react/core/layout/Flex.js +128 -0
- package/dist/react/core/layout/Flex.js.map +1 -0
- package/dist/react/core/layout/Grid.d.ts +36 -0
- package/dist/react/core/layout/Grid.js +142 -0
- package/dist/react/core/layout/Grid.js.map +1 -0
- package/dist/react/core/layout/Spacer.d.ts +8 -0
- package/dist/react/core/layout/Spacer.js +31 -0
- package/dist/react/core/layout/Spacer.js.map +1 -0
- package/dist/react/core/layout/Stack.d.ts +54 -0
- package/dist/react/core/layout/Stack.js +74 -0
- package/dist/react/core/layout/Stack.js.map +1 -0
- package/dist/react/core/layout/index.d.ts +38 -0
- package/dist/react/core/layout/responsive.d.ts +23 -0
- package/dist/react/core/layout/responsive.js +26 -0
- package/dist/react/core/layout/responsive.js.map +1 -0
- package/dist/react/core/layout/useBreakpoint.d.ts +77 -0
- package/dist/react/core/layout/useBreakpoint.js +73 -0
- package/dist/react/core/layout/useBreakpoint.js.map +1 -0
- package/dist/react/core/propertyConfig.d.ts +443 -0
- package/dist/react/core/propertyConfig.js +399 -0
- package/dist/react/core/propertyConfig.js.map +1 -0
- package/dist/react/hooks/index.d.ts +21 -0
- package/dist/react/hooks/useAccessWindows.d.ts +66 -0
- package/dist/react/hooks/useCompactMode.d.ts +82 -0
- package/dist/react/hooks/useCompactMode.js +62 -0
- package/dist/react/hooks/useCompactMode.js.map +1 -0
- package/dist/react/hooks/useLiveSelection.d.ts +57 -0
- package/dist/react/hooks/useSimulationPlayback.d.ts +97 -0
- package/dist/react/hooks/useSimulationTime.d.ts +61 -0
- package/dist/react/hooks/useSpacecraftPosition.d.ts +50 -0
- package/dist/react/hooks/useSpacecraftPosition.js +89 -0
- package/dist/react/hooks/useSpacecraftPosition.js.map +1 -0
- package/dist/react/hooks/useTelemetry.d.ts +55 -0
- package/dist/react/hooks/useTelemetry.js +73 -0
- package/dist/react/hooks/useTelemetry.js.map +1 -0
- package/dist/react/hooks/useZendirSession.d.ts +109 -0
- package/dist/react/hooks/useZendirSession.js +148 -0
- package/dist/react/hooks/useZendirSession.js.map +1 -0
- package/dist/react/index.d.ts +74 -0
- package/dist/react/shared/ErrorBoundary.d.ts +63 -0
- package/dist/react/shared/ErrorBoundary.js +142 -0
- package/dist/react/shared/ErrorBoundary.js.map +1 -0
- package/dist/react/shared/Skeleton.d.ts +110 -0
- package/dist/react/shared/Skeleton.js +324 -0
- package/dist/react/shared/Skeleton.js.map +1 -0
- package/dist/react/shared/index.d.ts +12 -0
- package/dist/react/theme/ThemeProvider.d.ts +385 -0
- package/dist/react/theme/ThemeProvider.js +1096 -0
- package/dist/react/theme/ThemeProvider.js.map +1 -0
- package/dist/react/theme/astro-tokens.d.ts +153 -0
- package/dist/react/theme/cardAccent.d.ts +75 -0
- package/dist/react/theme/cardAccent.js +137 -0
- package/dist/react/theme/cardAccent.js.map +1 -0
- package/dist/react/theme/config.d.ts +39 -0
- package/dist/react/theme/index.d.ts +9 -0
- package/dist/react/types.d.ts +360 -0
- package/dist/react/types.js +58 -0
- package/dist/react/types.js.map +1 -0
- package/dist/react/utils/index.d.ts +247 -0
- package/dist/react/utils/index.js +423 -0
- package/dist/react/utils/index.js.map +1 -0
- package/dist/react/visualizations/EclipseTimerCard.d.ts +17 -0
- package/dist/react/visualizations/EclipseTimerCard.js +250 -0
- package/dist/react/visualizations/EclipseTimerCard.js.map +1 -0
- package/dist/react/visualizations/LinkBudgetCard.d.ts +50 -0
- package/dist/react/visualizations/LinkBudgetCard.js +444 -0
- package/dist/react/visualizations/LinkBudgetCard.js.map +1 -0
- package/dist/react/visualizations/NavBallCard.d.ts +17 -0
- package/dist/react/visualizations/NavBallCard.js +243 -0
- package/dist/react/visualizations/NavBallCard.js.map +1 -0
- package/dist/react/visualizations/PropulsionCard.d.ts +37 -0
- package/dist/react/visualizations/PropulsionCard.js +298 -0
- package/dist/react/visualizations/PropulsionCard.js.map +1 -0
- package/dist/react/visualizations/SensorFootprintCard.d.ts +33 -0
- package/dist/react/visualizations/SensorFootprintCard.js +326 -0
- package/dist/react/visualizations/SensorFootprintCard.js.map +1 -0
- package/dist/react/visualizations/ThermalHeatmapCard.d.ts +38 -0
- package/dist/react/visualizations/ThermalHeatmapCard.js +372 -0
- package/dist/react/visualizations/ThermalHeatmapCard.js.map +1 -0
- package/dist/react/visualizations/index.d.ts +17 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +421 -0
- package/dist/react.js.map +1 -0
- package/dist/shaders/atmosphere.frag.js +5 -0
- package/dist/shaders/atmosphere.frag.js.map +1 -0
- package/dist/shaders/atmosphere.vert.js +5 -0
- package/dist/shaders/atmosphere.vert.js.map +1 -0
- package/dist/shaders/stars.frag.js +5 -0
- package/dist/shaders/stars.frag.js.map +1 -0
- package/dist/shaders/stars.vert.js +5 -0
- package/dist/shaders/stars.vert.js.map +1 -0
- package/dist/style.css +143 -0
- package/dist/tokens/index.d.ts +296 -0
- package/dist/tokens/index.js +263 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/tokens.css +155 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +220 -0
- package/sdk-stub.js +22 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, forwardRef, useState, useId } from "react";
|
|
3
|
+
import { safeAccentText, classNames } from "../utils/index.js";
|
|
4
|
+
import { useBreakpoint } from "./layout/useBreakpoint.js";
|
|
5
|
+
import { useTheme } from "../theme/ThemeProvider.js";
|
|
6
|
+
const Input = memo(forwardRef(function Input2({
|
|
7
|
+
label,
|
|
8
|
+
helperText,
|
|
9
|
+
error,
|
|
10
|
+
size = "medium",
|
|
11
|
+
status,
|
|
12
|
+
icon,
|
|
13
|
+
iconEnd,
|
|
14
|
+
fullWidth = false,
|
|
15
|
+
required,
|
|
16
|
+
optional,
|
|
17
|
+
disabled,
|
|
18
|
+
className = "",
|
|
19
|
+
id: propId,
|
|
20
|
+
style,
|
|
21
|
+
onFocus,
|
|
22
|
+
onBlur,
|
|
23
|
+
labelPlacement = "outlined",
|
|
24
|
+
type = "text",
|
|
25
|
+
autoComplete,
|
|
26
|
+
inputMode,
|
|
27
|
+
onPaste: onPasteUser,
|
|
28
|
+
...rest
|
|
29
|
+
}, ref) {
|
|
30
|
+
const resolvedInputMode = inputMode ?? (type === "email" ? "email" : void 0);
|
|
31
|
+
const { tokens, theme } = useTheme();
|
|
32
|
+
const { isMobile } = useBreakpoint();
|
|
33
|
+
const [focused, setFocused] = useState(false);
|
|
34
|
+
const [hovered, setHovered] = useState(false);
|
|
35
|
+
const generatedId = useId();
|
|
36
|
+
const inputId = propId ?? generatedId;
|
|
37
|
+
const shouldTrimOnPaste = type === "password" || type === "email" || autoComplete === "email" || autoComplete === "username";
|
|
38
|
+
const handlePaste = (e) => {
|
|
39
|
+
var _a;
|
|
40
|
+
if (shouldTrimOnPaste) {
|
|
41
|
+
const pasted = e.clipboardData.getData("text");
|
|
42
|
+
const trimmed = pasted.trim();
|
|
43
|
+
if (trimmed !== pasted) {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
const input = e.currentTarget;
|
|
46
|
+
const start = input.selectionStart ?? 0;
|
|
47
|
+
const end = input.selectionEnd ?? 0;
|
|
48
|
+
const cur = rest.value ?? input.value ?? "";
|
|
49
|
+
const newValue = cur.slice(0, start) + trimmed + cur.slice(end);
|
|
50
|
+
(_a = rest.onChange) == null ? void 0 : _a.call(rest, { target: { ...input, value: newValue } });
|
|
51
|
+
requestAnimationFrame(() => {
|
|
52
|
+
input.setSelectionRange(start + trimmed.length, start + trimmed.length);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
onPasteUser == null ? void 0 : onPasteUser(e);
|
|
57
|
+
};
|
|
58
|
+
const shouldTrimOnBlur = type === "email" || autoComplete === "email" || autoComplete === "username";
|
|
59
|
+
const handleBlur = (e) => {
|
|
60
|
+
if (shouldTrimOnBlur) {
|
|
61
|
+
const input = e.currentTarget;
|
|
62
|
+
const cur = input.value;
|
|
63
|
+
const trimmed = cur.trim();
|
|
64
|
+
if (trimmed !== cur && rest.onChange) {
|
|
65
|
+
rest.onChange({ target: { ...input, value: trimmed } });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
setFocused(false);
|
|
69
|
+
onBlur == null ? void 0 : onBlur(e);
|
|
70
|
+
};
|
|
71
|
+
const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
|
|
72
|
+
tokens.colors.interactive.transparentInputBg;
|
|
73
|
+
const hasError = !!error;
|
|
74
|
+
const isOutlined = labelPlacement === "outlined";
|
|
75
|
+
const getBorder = () => {
|
|
76
|
+
if (hasError) return tokens.borders.input.error;
|
|
77
|
+
if (status) return `${tokens.borders.width.thin} solid ${tokens.colors.status[status]}`;
|
|
78
|
+
if (focused) return tokens.borders.input.focus;
|
|
79
|
+
if (hovered && !disabled) return tokens.borders.input.hover;
|
|
80
|
+
return tokens.borders.input.default;
|
|
81
|
+
};
|
|
82
|
+
const sizeConfig = {
|
|
83
|
+
small: {
|
|
84
|
+
padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,
|
|
85
|
+
fontSize: tokens.typography.fontSize.xs,
|
|
86
|
+
height: tokens.elementSize.sm,
|
|
87
|
+
iconSize: 14,
|
|
88
|
+
labelSize: "0.6875rem",
|
|
89
|
+
outlinedLabelSize: "0.625rem",
|
|
90
|
+
inputPaddingLeft: 10
|
|
91
|
+
},
|
|
92
|
+
medium: {
|
|
93
|
+
padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,
|
|
94
|
+
fontSize: tokens.typography.fontSize.sm,
|
|
95
|
+
height: tokens.elementSize.md,
|
|
96
|
+
iconSize: 18,
|
|
97
|
+
labelSize: "0.75rem",
|
|
98
|
+
outlinedLabelSize: "0.6875rem",
|
|
99
|
+
inputPaddingLeft: 12
|
|
100
|
+
},
|
|
101
|
+
large: {
|
|
102
|
+
padding: `${tokens.spacing.smd} ${tokens.spacing.md}`,
|
|
103
|
+
fontSize: tokens.typography.fontSize.base,
|
|
104
|
+
height: tokens.elementSize.lg,
|
|
105
|
+
iconSize: 20,
|
|
106
|
+
labelSize: "0.875rem",
|
|
107
|
+
outlinedLabelSize: "0.75rem",
|
|
108
|
+
inputPaddingLeft: 16
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const config = sizeConfig[size];
|
|
112
|
+
const controlHeight = isMobile ? "44px" : config.height;
|
|
113
|
+
const focusGlow = focused && !hasError ? tokens.borders.focusRing.default : hasError && focused ? `0 0 0 3px ${tokens.colors.status.critical}20` : "none";
|
|
114
|
+
const labelBg = isTransparentTheme ? tokens.colors.background.base : tokens.colors.background.surface;
|
|
115
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
116
|
+
label,
|
|
117
|
+
required && /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.status.critical, marginLeft: "2px" }, children: "*" }),
|
|
118
|
+
optional && /* @__PURE__ */ jsxs("span", { style: {
|
|
119
|
+
color: tokens.colors.text.tertiary,
|
|
120
|
+
fontWeight: 400,
|
|
121
|
+
fontStyle: "italic"
|
|
122
|
+
}, children: [
|
|
123
|
+
" ",
|
|
124
|
+
"(optional)"
|
|
125
|
+
] })
|
|
126
|
+
] });
|
|
127
|
+
return /* @__PURE__ */ jsxs(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
className: classNames("zendir-input-wrapper", className),
|
|
131
|
+
style: {
|
|
132
|
+
display: "flex",
|
|
133
|
+
flexDirection: "column",
|
|
134
|
+
gap: tokens.spacing.xs,
|
|
135
|
+
width: fullWidth ? "100%" : "auto",
|
|
136
|
+
minWidth: fullWidth ? void 0 : isMobile ? "100%" : "200px",
|
|
137
|
+
...style
|
|
138
|
+
},
|
|
139
|
+
children: [
|
|
140
|
+
label && !isOutlined && /* @__PURE__ */ jsx(
|
|
141
|
+
"label",
|
|
142
|
+
{
|
|
143
|
+
htmlFor: inputId,
|
|
144
|
+
style: {
|
|
145
|
+
display: "flex",
|
|
146
|
+
alignItems: "center",
|
|
147
|
+
gap: tokens.spacing.xs,
|
|
148
|
+
fontSize: config.labelSize,
|
|
149
|
+
fontWeight: 500,
|
|
150
|
+
color: tokens.colors.text.secondary,
|
|
151
|
+
letterSpacing: "0.01em"
|
|
152
|
+
},
|
|
153
|
+
children: labelContent
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
/* @__PURE__ */ jsxs(
|
|
157
|
+
"div",
|
|
158
|
+
{
|
|
159
|
+
style: {
|
|
160
|
+
position: "relative",
|
|
161
|
+
display: "flex",
|
|
162
|
+
alignItems: "center"
|
|
163
|
+
},
|
|
164
|
+
onMouseEnter: () => setHovered(true),
|
|
165
|
+
onMouseLeave: () => setHovered(false),
|
|
166
|
+
children: [
|
|
167
|
+
label && isOutlined && /* @__PURE__ */ jsx(
|
|
168
|
+
"label",
|
|
169
|
+
{
|
|
170
|
+
htmlFor: inputId,
|
|
171
|
+
style: {
|
|
172
|
+
position: "absolute",
|
|
173
|
+
top: 0,
|
|
174
|
+
left: icon ? "34px" : `${config.inputPaddingLeft - 6}px`,
|
|
175
|
+
transform: "translateY(-50%)",
|
|
176
|
+
backgroundColor: labelBg,
|
|
177
|
+
padding: `0 ${tokens.spacing.xs}`,
|
|
178
|
+
fontSize: config.outlinedLabelSize,
|
|
179
|
+
fontWeight: 500,
|
|
180
|
+
color: focused ? hasError ? tokens.colors.status.critical : tokens.colors.accent.primary : hasError ? tokens.colors.status.critical : tokens.colors.text.secondary,
|
|
181
|
+
letterSpacing: "0.01em",
|
|
182
|
+
zIndex: 1,
|
|
183
|
+
pointerEvents: "none",
|
|
184
|
+
transition: "color 200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
185
|
+
lineHeight: 1.2,
|
|
186
|
+
whiteSpace: "nowrap"
|
|
187
|
+
},
|
|
188
|
+
children: labelContent
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
icon && /* @__PURE__ */ jsx(
|
|
192
|
+
"span",
|
|
193
|
+
{
|
|
194
|
+
style: {
|
|
195
|
+
position: "absolute",
|
|
196
|
+
left: tokens.spacing.smd,
|
|
197
|
+
display: "flex",
|
|
198
|
+
alignItems: "center",
|
|
199
|
+
color: focused ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.tertiary,
|
|
200
|
+
pointerEvents: "none",
|
|
201
|
+
transition: tokens.animation.fast
|
|
202
|
+
},
|
|
203
|
+
children: icon
|
|
204
|
+
}
|
|
205
|
+
),
|
|
206
|
+
/* @__PURE__ */ jsx(
|
|
207
|
+
"input",
|
|
208
|
+
{
|
|
209
|
+
ref,
|
|
210
|
+
id: inputId,
|
|
211
|
+
disabled,
|
|
212
|
+
required,
|
|
213
|
+
"aria-invalid": hasError,
|
|
214
|
+
"aria-describedby": helperText || error ? `${inputId}-helper` : void 0,
|
|
215
|
+
onFocus: (e) => {
|
|
216
|
+
setFocused(true);
|
|
217
|
+
onFocus == null ? void 0 : onFocus(e);
|
|
218
|
+
},
|
|
219
|
+
onBlur: handleBlur,
|
|
220
|
+
onPaste: handlePaste,
|
|
221
|
+
type,
|
|
222
|
+
autoComplete,
|
|
223
|
+
inputMode: resolvedInputMode,
|
|
224
|
+
style: {
|
|
225
|
+
width: "100%",
|
|
226
|
+
height: controlHeight,
|
|
227
|
+
padding: config.padding,
|
|
228
|
+
paddingLeft: icon ? "40px" : config.padding,
|
|
229
|
+
paddingRight: iconEnd ? "40px" : config.padding,
|
|
230
|
+
fontSize: config.fontSize,
|
|
231
|
+
fontFamily: tokens.typography.fontFamily.primary,
|
|
232
|
+
color: tokens.colors.text.primary,
|
|
233
|
+
backgroundColor: isTransparentTheme ? "rgba(10, 15, 25, 0.4)" : tokens.colors.background.surface,
|
|
234
|
+
border: getBorder(),
|
|
235
|
+
borderRadius: tokens.borderRadius.md,
|
|
236
|
+
outline: "none",
|
|
237
|
+
transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
238
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
239
|
+
opacity: disabled ? 0.5 : 1,
|
|
240
|
+
boxShadow: focusGlow
|
|
241
|
+
},
|
|
242
|
+
...rest
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
iconEnd && /* @__PURE__ */ jsx(
|
|
246
|
+
"span",
|
|
247
|
+
{
|
|
248
|
+
style: {
|
|
249
|
+
position: "absolute",
|
|
250
|
+
right: tokens.spacing.smd,
|
|
251
|
+
display: "flex",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
color: tokens.colors.text.tertiary,
|
|
254
|
+
cursor: "pointer"
|
|
255
|
+
},
|
|
256
|
+
children: iconEnd
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
(helperText || error) && /* @__PURE__ */ jsxs(
|
|
263
|
+
"span",
|
|
264
|
+
{
|
|
265
|
+
id: `${inputId}-helper`,
|
|
266
|
+
role: hasError ? "alert" : void 0,
|
|
267
|
+
style: {
|
|
268
|
+
fontSize: "0.6875rem",
|
|
269
|
+
fontWeight: hasError ? 500 : 400,
|
|
270
|
+
color: hasError ? tokens.colors.status.critical : tokens.colors.text.tertiary,
|
|
271
|
+
display: "flex",
|
|
272
|
+
alignItems: "center",
|
|
273
|
+
gap: tokens.spacing.xs
|
|
274
|
+
},
|
|
275
|
+
children: [
|
|
276
|
+
hasError && /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: tokens.colors.status.critical, "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) }),
|
|
277
|
+
error || helperText
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
)
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
}));
|
|
285
|
+
export {
|
|
286
|
+
Input
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../src/react/core/Input.tsx"],"sourcesContent":["/**\n * @zendir/ui - Input Component\n * \n * Text input field following Astro UX Design System with Zendir purple accents.\n * \n * Astro UX Compliance:\n * - Stacked inputs left-justified\n * - Consistent spacing\n * - Help text for validation (not placeholder)\n * - Required/optional indicators\n * - States: default, hover, focus, invalid, disabled\n * \n * Zendir Enhancements:\n * - Purple focus glow\n * - Smooth transitions\n * - Modern glassmorphism effects\n * \n * @example\n * ```tsx\n * <Input label=\"Spacecraft ID\" placeholder=\"Enter ID...\" />\n * <Input label=\"Password\" type=\"password\" />\n * <Input label=\"Search\" icon={<Icon name=\"search\" />} />\n * <Input label=\"Email\" error=\"Invalid email format\" />\n * ```\n */\n\nimport React, { memo, forwardRef, useState, useId } from 'react';\nimport { useTheme } from '../theme';\nimport { classNames, safeAccentText, type StatusLevel } from '../utils';\nimport { useBreakpoint } from './layout/useBreakpoint';\n\nexport type InputSize = 'small' | 'medium' | 'large';\n\n/** Label placement relative to the input field */\nexport type LabelPlacement = 'above' | 'outlined';\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\n /** Label text or ReactNode (supports rich content like tooltip icons) */\n label?: React.ReactNode;\n /** Helper text below input */\n helperText?: string;\n /** Error message (shows error state) */\n error?: string;\n /** Size variant */\n size?: InputSize;\n /** Status for styling */\n status?: StatusLevel;\n /** Icon at start of input */\n icon?: React.ReactNode;\n /** Icon at end of input */\n iconEnd?: React.ReactNode;\n /** Full width */\n fullWidth?: boolean;\n /** Required indicator */\n required?: boolean;\n /** Optional indicator (shows \"optional\" text) */\n optional?: boolean;\n /** Custom className */\n className?: string;\n /**\n * Label placement style.\n * - `'outlined'` — label sits on the input border (notched/Material-style). **Default.**\n * - `'above'` — label sits above the input with a gap (classic stack).\n */\n labelPlacement?: LabelPlacement;\n}\n\nexport const Input = memo(forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n label,\n helperText,\n error,\n size = 'medium',\n status,\n icon,\n iconEnd,\n fullWidth = false,\n required,\n optional,\n disabled,\n className = '',\n id: propId,\n style,\n onFocus,\n onBlur,\n labelPlacement = 'outlined',\n type = 'text',\n autoComplete,\n inputMode,\n onPaste: onPasteUser,\n ...rest\n },\n ref\n): React.ReactElement {\n // Mobile: email keyboard when type is email (industry standard).\n const resolvedInputMode = inputMode ?? (type === 'email' ? 'email' : undefined);\n const { tokens, theme } = useTheme();\n const { isMobile } = useBreakpoint();\n const [focused, setFocused] = useState(false);\n const [hovered, setHovered] = useState(false);\n const generatedId = useId();\n const inputId = propId ?? generatedId;\n\n // Trim pasted content for password, email, and username (industry standard: avoid auth/validation failures).\n const shouldTrimOnPaste = type === 'password' || type === 'email' || autoComplete === 'email' || autoComplete === 'username';\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (shouldTrimOnPaste) {\n const pasted = e.clipboardData.getData('text');\n const trimmed = pasted.trim();\n if (trimmed !== pasted) {\n e.preventDefault();\n const input = e.currentTarget;\n const start = input.selectionStart ?? 0;\n const end = input.selectionEnd ?? 0;\n const cur = ((rest as { value?: string }).value ?? input.value) ?? '';\n const newValue = cur.slice(0, start) + trimmed + cur.slice(end);\n rest.onChange?.({ target: { ...input, value: newValue } } as React.ChangeEvent<HTMLInputElement>);\n requestAnimationFrame(() => {\n input.setSelectionRange(start + trimmed.length, start + trimmed.length);\n });\n }\n }\n onPasteUser?.(e);\n };\n\n // Trim on blur for email/username so \" user@example.com \" becomes \"user@example.com\" when leaving the field.\n const shouldTrimOnBlur = type === 'email' || autoComplete === 'email' || autoComplete === 'username';\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n if (shouldTrimOnBlur) {\n const input = e.currentTarget;\n const cur = input.value;\n const trimmed = cur.trim();\n if (trimmed !== cur && rest.onChange) {\n rest.onChange({ target: { ...input, value: trimmed } } as React.ChangeEvent<HTMLInputElement>);\n }\n }\n setFocused(false);\n onBlur?.(e);\n };\n \n // Transparent theme detection (purple-hue transparent bg)\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\n const _transparentInputBg = tokens.colors.interactive.transparentInputBg;\n \n const hasError = !!error;\n const isOutlined = labelPlacement === 'outlined';\n \n // Determine border color based on state\n const getBorder = () => {\n if (hasError) return tokens.borders.input.error;\n if (status) return `${tokens.borders.width.thin} solid ${tokens.colors.status[status]}`;\n if (focused) return tokens.borders.input.focus;\n if (hovered && !disabled) return tokens.borders.input.hover;\n return tokens.borders.input.default;\n };\n \n const sizeConfig = {\n small: {\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n fontSize: tokens.typography.fontSize.xs,\n height: tokens.elementSize.sm,\n iconSize: 14,\n labelSize: '0.6875rem',\n outlinedLabelSize: '0.625rem',\n inputPaddingLeft: 10,\n },\n medium: {\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\n fontSize: tokens.typography.fontSize.sm,\n height: tokens.elementSize.md,\n iconSize: 18,\n labelSize: '0.75rem',\n outlinedLabelSize: '0.6875rem',\n inputPaddingLeft: 12,\n },\n large: {\n padding: `${tokens.spacing.smd} ${tokens.spacing.md}`,\n fontSize: tokens.typography.fontSize.base,\n height: tokens.elementSize.lg,\n iconSize: 20,\n labelSize: '0.875rem',\n outlinedLabelSize: '0.75rem',\n inputPaddingLeft: 16,\n },\n };\n \n const config = sizeConfig[size];\n const controlHeight = isMobile ? '44px' : config.height;\n \n // Focus glow effect\n const focusGlow = focused && !hasError\n ? tokens.borders.focusRing.default\n : hasError && focused\n ? `0 0 0 3px ${tokens.colors.status.critical}20`\n : 'none';\n \n // Background for the outlined label \"notch\" (must be opaque to mask the border)\n const labelBg = isTransparentTheme\n ? tokens.colors.background.base\n : tokens.colors.background.surface;\n \n // Shared label content (text + required/optional indicators)\n const labelContent = (\n <>\n {label}\n {required && (\n <span style={{ color: tokens.colors.status.critical, marginLeft: '2px' }}>*</span>\n )}\n {optional && (\n <span style={{ \n color: tokens.colors.text.tertiary, \n fontWeight: 400,\n fontStyle: 'italic',\n }}>\n {' '}(optional)\n </span>\n )}\n </>\n );\n \n return (\n <div\n className={classNames('zendir-input-wrapper', className)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: tokens.spacing.xs,\n width: fullWidth ? '100%' : 'auto',\n minWidth: fullWidth ? undefined : (isMobile ? '100%' : '200px'),\n ...style,\n }}\n >\n {/* Label: 'above' variant — sits above the input with gap */}\n {label && !isOutlined && (\n <label\n htmlFor={inputId}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: tokens.spacing.xs,\n fontSize: config.labelSize,\n fontWeight: 500,\n color: tokens.colors.text.secondary,\n letterSpacing: '0.01em',\n }}\n >\n {labelContent}\n </label>\n )}\n \n <div\n style={{\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n }}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n {/* Label: 'outlined' variant — positioned on the input border */}\n {label && isOutlined && (\n <label\n htmlFor={inputId}\n style={{\n position: 'absolute',\n top: 0,\n left: icon ? '34px' : `${config.inputPaddingLeft - 6}px`,\n transform: 'translateY(-50%)',\n backgroundColor: labelBg,\n padding: `0 ${tokens.spacing.xs}`,\n fontSize: config.outlinedLabelSize,\n fontWeight: 500,\n color: focused\n ? (hasError ? tokens.colors.status.critical : tokens.colors.accent.primary)\n : hasError\n ? tokens.colors.status.critical\n : tokens.colors.text.secondary,\n letterSpacing: '0.01em',\n zIndex: 1,\n pointerEvents: 'none',\n transition: 'color 200ms cubic-bezier(0.4, 0, 0.2, 1)',\n lineHeight: 1.2,\n whiteSpace: 'nowrap',\n }}\n >\n {labelContent}\n </label>\n )}\n \n {icon && (\n <span\n style={{\n position: 'absolute',\n left: tokens.spacing.smd,\n display: 'flex',\n alignItems: 'center',\n color: focused ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.tertiary,\n pointerEvents: 'none',\n transition: tokens.animation.fast,\n }}\n >\n {icon}\n </span>\n )}\n \n <input\n ref={ref}\n id={inputId}\n disabled={disabled}\n required={required}\n aria-invalid={hasError}\n aria-describedby={helperText || error ? `${inputId}-helper` : undefined}\n onFocus={(e) => {\n setFocused(true);\n onFocus?.(e);\n }}\n onBlur={handleBlur}\n onPaste={handlePaste}\n type={type}\n autoComplete={autoComplete}\n inputMode={resolvedInputMode}\n style={{\n width: '100%',\n height: controlHeight,\n padding: config.padding,\n paddingLeft: icon ? '40px' : config.padding,\n paddingRight: iconEnd ? '40px' : config.padding,\n fontSize: config.fontSize,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n backgroundColor: isTransparentTheme ? 'rgba(10, 15, 25, 0.4)' : tokens.colors.background.surface,\n border: getBorder(),\n borderRadius: tokens.borderRadius.md,\n outline: 'none',\n transition: 'all 200ms cubic-bezier(0.4, 0, 0.2, 1)',\n cursor: disabled ? 'not-allowed' : 'text',\n opacity: disabled ? 0.5 : 1,\n boxShadow: focusGlow,\n }}\n {...rest}\n />\n \n {iconEnd && (\n <span\n style={{\n position: 'absolute',\n right: tokens.spacing.smd,\n display: 'flex',\n alignItems: 'center',\n color: tokens.colors.text.tertiary,\n cursor: 'pointer',\n }}\n >\n {iconEnd}\n </span>\n )}\n </div>\n \n {(helperText || error) && (\n <span\n id={`${inputId}-helper`}\n role={hasError ? 'alert' : undefined}\n style={{\n fontSize: '0.6875rem',\n fontWeight: hasError ? 500 : 400,\n color: hasError ? tokens.colors.status.critical : tokens.colors.text.tertiary,\n display: 'flex',\n alignItems: 'center',\n gap: tokens.spacing.xs,\n }}\n >\n {hasError && (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill={tokens.colors.status.critical} aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n )}\n {error || helperText}\n </span>\n )}\n </div>\n );\n}));\n\nexport default Input;\n"],"names":["Input"],"mappings":";;;;;AAmEO,MAAM,QAAQ,KAAK,WAAyC,SAASA,OAC1E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,IAAI;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,GAAG;AACL,GACA,KACoB;AAEpB,QAAM,oBAAoB,cAAc,SAAS,UAAU,UAAU;AACrE,QAAM,EAAE,QAAQ,MAAA,IAAU,SAAA;AAC1B,QAAM,EAAE,SAAA,IAAa,cAAA;AACrB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,cAAc,MAAA;AACpB,QAAM,UAAU,UAAU;AAG1B,QAAM,oBAAoB,SAAS,cAAc,SAAS,WAAW,iBAAiB,WAAW,iBAAiB;AAClH,QAAM,cAAc,CAAC,MAA8C;;AACjE,QAAI,mBAAmB;AACrB,YAAM,SAAS,EAAE,cAAc,QAAQ,MAAM;AAC7C,YAAM,UAAU,OAAO,KAAA;AACvB,UAAI,YAAY,QAAQ;AACtB,UAAE,eAAA;AACF,cAAM,QAAQ,EAAE;AAChB,cAAM,QAAQ,MAAM,kBAAkB;AACtC,cAAM,MAAM,MAAM,gBAAgB;AAClC,cAAM,MAAQ,KAA4B,SAAS,MAAM,SAAU;AACnE,cAAM,WAAW,IAAI,MAAM,GAAG,KAAK,IAAI,UAAU,IAAI,MAAM,GAAG;AAC9D,mBAAK,aAAL,8BAAgB,EAAE,QAAQ,EAAE,GAAG,OAAO,OAAO,SAAA;AAC7C,8BAAsB,MAAM;AAC1B,gBAAM,kBAAkB,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,QACxE,CAAC;AAAA,MACH;AAAA,IACF;AACA,+CAAc;AAAA,EAChB;AAGA,QAAM,mBAAmB,SAAS,WAAW,iBAAiB,WAAW,iBAAiB;AAC1F,QAAM,aAAa,CAAC,MAA0C;AAC5D,QAAI,kBAAkB;AACpB,YAAM,QAAQ,EAAE;AAChB,YAAM,MAAM,MAAM;AAClB,YAAM,UAAU,IAAI,KAAA;AACpB,UAAI,YAAY,OAAO,KAAK,UAAU;AACpC,aAAK,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,OAAO,QAAA,GAAkD;AAAA,MAC/F;AAAA,IACF;AACA,eAAW,KAAK;AAChB,qCAAS;AAAA,EACX;AAGA,QAAM,qBAAqB,UAAU,iBAAiB,UAAU,sBAAsB,UAAU;AACpE,SAAO,OAAO,YAAY;AAEtD,QAAM,WAAW,CAAC,CAAC;AACnB,QAAM,aAAa,mBAAmB;AAGtC,QAAM,YAAY,MAAM;AACtB,QAAI,SAAU,QAAO,OAAO,QAAQ,MAAM;AAC1C,QAAI,OAAQ,QAAO,GAAG,OAAO,QAAQ,MAAM,IAAI,UAAU,OAAO,OAAO,OAAO,MAAM,CAAC;AACrF,QAAI,QAAS,QAAO,OAAO,QAAQ,MAAM;AACzC,QAAI,WAAW,CAAC,SAAU,QAAO,OAAO,QAAQ,MAAM;AACtD,WAAO,OAAO,QAAQ,MAAM;AAAA,EAC9B;AAEA,QAAM,aAAa;AAAA,IACjB,OAAO;AAAA,MACL,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,MAClD,UAAU,OAAO,WAAW,SAAS;AAAA,MACrC,QAAQ,OAAO,YAAY;AAAA,MAC3B,UAAU;AAAA,MACV,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,IAAA;AAAA,IAEpB,QAAQ;AAAA,MACN,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,GAAG;AAAA,MACnD,UAAU,OAAO,WAAW,SAAS;AAAA,MACrC,QAAQ,OAAO,YAAY;AAAA,MAC3B,UAAU;AAAA,MACV,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,IAAA;AAAA,IAEpB,OAAO;AAAA,MACL,SAAS,GAAG,OAAO,QAAQ,GAAG,IAAI,OAAO,QAAQ,EAAE;AAAA,MACnD,UAAU,OAAO,WAAW,SAAS;AAAA,MACrC,QAAQ,OAAO,YAAY;AAAA,MAC3B,UAAU;AAAA,MACV,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,IAAA;AAAA,EACpB;AAGF,QAAM,SAAS,WAAW,IAAI;AAC9B,QAAM,gBAAgB,WAAW,SAAS,OAAO;AAGjD,QAAM,YAAY,WAAW,CAAC,WAC1B,OAAO,QAAQ,UAAU,UACzB,YAAY,UACZ,aAAa,OAAO,OAAO,OAAO,QAAQ,OAC1C;AAGJ,QAAM,UAAU,qBACZ,OAAO,OAAO,WAAW,OACzB,OAAO,OAAO,WAAW;AAG7B,QAAM,eACJ,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACA,YACC,oBAAC,QAAA,EAAK,OAAO,EAAE,OAAO,OAAO,OAAO,OAAO,UAAU,YAAY,MAAA,GAAS,UAAA,KAAC;AAAA,IAE5E,YACC,qBAAC,QAAA,EAAK,OAAO;AAAA,MACX,OAAO,OAAO,OAAO,KAAK;AAAA,MAC1B,YAAY;AAAA,MACZ,WAAW;AAAA,IAAA,GAEV,UAAA;AAAA,MAAA;AAAA,MAAI;AAAA,IAAA,EAAA,CACP;AAAA,EAAA,GAEJ;AAGF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,WAAW,wBAAwB,SAAS;AAAA,MACvD,OAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,KAAK,OAAO,QAAQ;AAAA,QACpB,OAAO,YAAY,SAAS;AAAA,QAC5B,UAAU,YAAY,SAAa,WAAW,SAAS;AAAA,QACvD,GAAG;AAAA,MAAA;AAAA,MAIJ,UAAA;AAAA,QAAA,SAAS,CAAC,cACT;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS;AAAA,YACT,OAAO;AAAA,cACL,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,KAAK,OAAO,QAAQ;AAAA,cACpB,UAAU,OAAO;AAAA,cACjB,YAAY;AAAA,cACZ,OAAO,OAAO,OAAO,KAAK;AAAA,cAC1B,eAAe;AAAA,YAAA;AAAA,YAGhB,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAIL;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,SAAS;AAAA,cACT,YAAY;AAAA,YAAA;AAAA,YAEd,cAAc,MAAM,WAAW,IAAI;AAAA,YACnC,cAAc,MAAM,WAAW,KAAK;AAAA,YAGnC,UAAA;AAAA,cAAA,SAAS,cACR;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,SAAS;AAAA,kBACT,OAAO;AAAA,oBACL,UAAU;AAAA,oBACV,KAAK;AAAA,oBACL,MAAM,OAAO,SAAS,GAAG,OAAO,mBAAmB,CAAC;AAAA,oBACpD,WAAW;AAAA,oBACX,iBAAiB;AAAA,oBACjB,SAAS,KAAK,OAAO,QAAQ,EAAE;AAAA,oBAC/B,UAAU,OAAO;AAAA,oBACjB,YAAY;AAAA,oBACZ,OAAO,UACF,WAAW,OAAO,OAAO,OAAO,WAAW,OAAO,OAAO,OAAO,UACjE,WACE,OAAO,OAAO,OAAO,WACrB,OAAO,OAAO,KAAK;AAAA,oBACzB,eAAe;AAAA,oBACf,QAAQ;AAAA,oBACR,eAAe;AAAA,oBACf,YAAY;AAAA,oBACZ,YAAY;AAAA,oBACZ,YAAY;AAAA,kBAAA;AAAA,kBAGb,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIJ,QACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAO;AAAA,oBACL,UAAU;AAAA,oBACV,MAAM,OAAO,QAAQ;AAAA,oBACrB,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,OAAO,UAAU,eAAe,OAAO,OAAO,OAAO,OAAO,IAAI,OAAO,OAAO,KAAK;AAAA,oBACnF,eAAe;AAAA,oBACf,YAAY,OAAO,UAAU;AAAA,kBAAA;AAAA,kBAG9B,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIL;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC;AAAA,kBACA,IAAI;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,gBAAc;AAAA,kBACd,oBAAkB,cAAc,QAAQ,GAAG,OAAO,YAAY;AAAA,kBAC9D,SAAS,CAAC,MAAM;AACd,+BAAW,IAAI;AACf,uDAAU;AAAA,kBACZ;AAAA,kBACA,QAAQ;AAAA,kBACR,SAAS;AAAA,kBACT;AAAA,kBACA;AAAA,kBACA,WAAW;AAAA,kBACX,OAAO;AAAA,oBACL,OAAO;AAAA,oBACP,QAAQ;AAAA,oBACR,SAAS,OAAO;AAAA,oBAChB,aAAa,OAAO,SAAS,OAAO;AAAA,oBACpC,cAAc,UAAU,SAAS,OAAO;AAAA,oBACxC,UAAU,OAAO;AAAA,oBACjB,YAAY,OAAO,WAAW,WAAW;AAAA,oBACzC,OAAO,OAAO,OAAO,KAAK;AAAA,oBAC1B,iBAAiB,qBAAqB,0BAA0B,OAAO,OAAO,WAAW;AAAA,oBACzF,QAAQ,UAAA;AAAA,oBACR,cAAc,OAAO,aAAa;AAAA,oBAClC,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,QAAQ,WAAW,gBAAgB;AAAA,oBACnC,SAAS,WAAW,MAAM;AAAA,oBAC1B,WAAW;AAAA,kBAAA;AAAA,kBAEZ,GAAG;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGL,WACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAO;AAAA,oBACL,UAAU;AAAA,oBACV,OAAO,OAAO,QAAQ;AAAA,oBACtB,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,OAAO,OAAO,OAAO,KAAK;AAAA,oBAC1B,QAAQ;AAAA,kBAAA;AAAA,kBAGT,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YACH;AAAA,UAAA;AAAA,QAAA;AAAA,SAIF,cAAc,UACd;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAI,GAAG,OAAO;AAAA,YACd,MAAM,WAAW,UAAU;AAAA,YAC3B,OAAO;AAAA,cACL,UAAU;AAAA,cACV,YAAY,WAAW,MAAM;AAAA,cAC7B,OAAO,WAAW,OAAO,OAAO,OAAO,WAAW,OAAO,OAAO,KAAK;AAAA,cACrE,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,KAAK,OAAO,QAAQ;AAAA,YAAA;AAAA,YAGrB,UAAA;AAAA,cAAA,YACC,oBAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAM,OAAO,OAAO,OAAO,UAAU,eAAY,QAAO,WAAU,SAChH,UAAA,oBAAC,QAAA,EAAK,GAAE,mGAAA,CAAkG,EAAA,CAC5G;AAAA,cAED,SAAS;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC,CAAC;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
|
|
3
|
+
export type LimitsState = 'red_low' | 'yellow_low' | 'green' | 'yellow_high' | 'red_high' | 'blue' | 'stale';
|
|
4
|
+
export interface LimitsBarProps {
|
|
5
|
+
/** Current value */
|
|
6
|
+
value: number;
|
|
7
|
+
/** Red low threshold (minimum critical) */
|
|
8
|
+
redLow?: number;
|
|
9
|
+
/** Yellow low threshold (minimum warning) */
|
|
10
|
+
yellowLow?: number;
|
|
11
|
+
/** Green low threshold (start of nominal) */
|
|
12
|
+
greenLow?: number;
|
|
13
|
+
/** Green high threshold (end of nominal) */
|
|
14
|
+
greenHigh?: number;
|
|
15
|
+
/** Yellow high threshold (maximum warning) */
|
|
16
|
+
yellowHigh?: number;
|
|
17
|
+
/** Red high threshold (maximum critical) */
|
|
18
|
+
redHigh?: number;
|
|
19
|
+
/** Overall min for the bar (defaults to redLow - 10%) */
|
|
20
|
+
min?: number;
|
|
21
|
+
/** Overall max for the bar (defaults to redHigh + 10%) */
|
|
22
|
+
max?: number;
|
|
23
|
+
/** Label text */
|
|
24
|
+
label?: string;
|
|
25
|
+
/** Unit string */
|
|
26
|
+
unit?: string;
|
|
27
|
+
/** Whether the value is stale / not updating */
|
|
28
|
+
stale?: boolean;
|
|
29
|
+
/** Compact mode (thinner bar, less text) */
|
|
30
|
+
compact?: boolean;
|
|
31
|
+
/** Show the numeric value on the bar */
|
|
32
|
+
showValue?: boolean;
|
|
33
|
+
/** Show limit threshold labels */
|
|
34
|
+
showThresholds?: boolean;
|
|
35
|
+
/** Width (default: '100%') */
|
|
36
|
+
width?: number | string;
|
|
37
|
+
/** Height of the bar (default: 20 for normal, 12 for compact) */
|
|
38
|
+
barHeight?: number;
|
|
39
|
+
/** Custom status override (forces a specific status regardless of value) */
|
|
40
|
+
statusOverride?: LimitsState;
|
|
41
|
+
/** Called when status changes */
|
|
42
|
+
onStatusChange?: (status: LimitsState, value: number) => void;
|
|
43
|
+
/** When false, lower-limit zones (red-low, yellow-low, green-low) are hidden even if threshold values are provided */
|
|
44
|
+
showLower?: boolean;
|
|
45
|
+
/** When false, upper-limit zones (green-high, yellow-high, red-high) are hidden even if threshold values are provided */
|
|
46
|
+
showUpper?: boolean;
|
|
47
|
+
/** CSS class */
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare const LimitsBar: React.NamedExoticComponent<LimitsBarProps>;
|
|
51
|
+
export default LimitsBar;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { useTheme } from "../theme/ThemeProvider.js";
|
|
4
|
+
function getLimitsState(value, redLow, yellowLow, greenLow, greenHigh, yellowHigh, redHigh) {
|
|
5
|
+
if (redLow !== void 0 && value < redLow) return "red_low";
|
|
6
|
+
if (yellowLow !== void 0 && value < yellowLow) return "yellow_low";
|
|
7
|
+
if (greenLow !== void 0 && value < greenLow) return "yellow_low";
|
|
8
|
+
if (redHigh !== void 0 && value > redHigh) return "red_high";
|
|
9
|
+
if (yellowHigh !== void 0 && value > yellowHigh) return "yellow_high";
|
|
10
|
+
if (greenHigh !== void 0 && value > greenHigh) return "yellow_high";
|
|
11
|
+
return "green";
|
|
12
|
+
}
|
|
13
|
+
const LimitsBar = memo(function LimitsBar2({
|
|
14
|
+
value,
|
|
15
|
+
redLow: redLowProp,
|
|
16
|
+
yellowLow: yellowLowProp,
|
|
17
|
+
greenLow: greenLowProp,
|
|
18
|
+
greenHigh: greenHighProp,
|
|
19
|
+
yellowHigh: yellowHighProp,
|
|
20
|
+
redHigh: redHighProp,
|
|
21
|
+
min: minProp,
|
|
22
|
+
max: maxProp,
|
|
23
|
+
label,
|
|
24
|
+
unit,
|
|
25
|
+
stale = false,
|
|
26
|
+
compact = false,
|
|
27
|
+
showValue = true,
|
|
28
|
+
showThresholds = false,
|
|
29
|
+
showLower = true,
|
|
30
|
+
showUpper = true,
|
|
31
|
+
width = "100%",
|
|
32
|
+
barHeight: barHeightProp,
|
|
33
|
+
statusOverride,
|
|
34
|
+
className = ""
|
|
35
|
+
}) {
|
|
36
|
+
const redLow = showLower ? redLowProp : void 0;
|
|
37
|
+
const yellowLow = showLower ? yellowLowProp : void 0;
|
|
38
|
+
const greenLow = showLower ? greenLowProp : void 0;
|
|
39
|
+
const greenHigh = showUpper ? greenHighProp : void 0;
|
|
40
|
+
const yellowHigh = showUpper ? yellowHighProp : void 0;
|
|
41
|
+
const redHigh = showUpper ? redHighProp : void 0;
|
|
42
|
+
const { tokens } = useTheme();
|
|
43
|
+
const softStatusColors = useMemo(() => ({
|
|
44
|
+
normal: tokens.colors.status.normal,
|
|
45
|
+
caution: tokens.colors.status.caution,
|
|
46
|
+
serious: tokens.colors.status.serious,
|
|
47
|
+
critical: tokens.colors.status.critical,
|
|
48
|
+
off: tokens.colors.status.off,
|
|
49
|
+
standby: tokens.colors.status.standby
|
|
50
|
+
}), [tokens]);
|
|
51
|
+
const barHeight = barHeightProp ?? (compact ? 12 : 20);
|
|
52
|
+
useMemo(() => {
|
|
53
|
+
const rl = redLow ?? -Infinity;
|
|
54
|
+
const yl = yellowLow ?? redLow ?? -Infinity;
|
|
55
|
+
const gl = greenLow ?? yellowLow ?? redLow ?? -Infinity;
|
|
56
|
+
const gh = greenHigh ?? yellowHigh ?? redHigh ?? Infinity;
|
|
57
|
+
const yh = yellowHigh ?? redHigh ?? Infinity;
|
|
58
|
+
const rh = redHigh ?? Infinity;
|
|
59
|
+
return { rl, yl, gl, gh, yh, rh };
|
|
60
|
+
}, [redLow, yellowLow, greenLow, greenHigh, yellowHigh, redHigh]);
|
|
61
|
+
const rangeMin = minProp ?? (redLow !== void 0 ? redLow - (redHigh !== void 0 ? (redHigh - redLow) * 0.1 : 10) : 0);
|
|
62
|
+
const rangeMax = maxProp ?? (redHigh !== void 0 ? redHigh + (redLow !== void 0 ? (redHigh - redLow) * 0.1 : 10) : 100);
|
|
63
|
+
const range = rangeMax - rangeMin;
|
|
64
|
+
const status = stale ? "stale" : statusOverride ?? getLimitsState(value, redLow, yellowLow, greenLow, greenHigh, yellowHigh, redHigh);
|
|
65
|
+
const statusColors = {
|
|
66
|
+
red_low: softStatusColors.critical,
|
|
67
|
+
red_high: softStatusColors.critical,
|
|
68
|
+
yellow_low: softStatusColors.caution,
|
|
69
|
+
yellow_high: softStatusColors.caution,
|
|
70
|
+
green: softStatusColors.normal,
|
|
71
|
+
blue: softStatusColors.standby,
|
|
72
|
+
stale: softStatusColors.off
|
|
73
|
+
};
|
|
74
|
+
const valuePercent = range > 0 ? Math.max(0, Math.min(100, (value - rangeMin) / range * 100)) : 50;
|
|
75
|
+
const zones = useMemo(() => {
|
|
76
|
+
const segs = [];
|
|
77
|
+
const toPercent = (v) => Math.max(0, Math.min(100, (v - rangeMin) / range * 100));
|
|
78
|
+
const critical = softStatusColors.critical;
|
|
79
|
+
const caution = softStatusColors.caution;
|
|
80
|
+
const normal = softStatusColors.normal;
|
|
81
|
+
if (redLow !== void 0) {
|
|
82
|
+
segs.push({ start: 0, end: toPercent(redLow), color: `${critical}66` });
|
|
83
|
+
}
|
|
84
|
+
if (yellowLow !== void 0) {
|
|
85
|
+
const s = redLow !== void 0 ? toPercent(redLow) : 0;
|
|
86
|
+
segs.push({ start: s, end: toPercent(yellowLow), color: `${caution}66` });
|
|
87
|
+
}
|
|
88
|
+
{
|
|
89
|
+
const s = yellowLow !== void 0 ? toPercent(yellowLow) : redLow !== void 0 ? toPercent(redLow) : 0;
|
|
90
|
+
const e = yellowHigh !== void 0 ? toPercent(yellowHigh) : redHigh !== void 0 ? toPercent(redHigh) : 100;
|
|
91
|
+
segs.push({ start: s, end: e, color: `${normal}44` });
|
|
92
|
+
}
|
|
93
|
+
if (yellowHigh !== void 0) {
|
|
94
|
+
const e = redHigh !== void 0 ? toPercent(redHigh) : 100;
|
|
95
|
+
segs.push({ start: toPercent(yellowHigh), end: e, color: `${caution}66` });
|
|
96
|
+
}
|
|
97
|
+
if (redHigh !== void 0) {
|
|
98
|
+
segs.push({ start: toPercent(redHigh), end: 100, color: `${critical}66` });
|
|
99
|
+
}
|
|
100
|
+
return segs;
|
|
101
|
+
}, [redLow, yellowLow, yellowHigh, redHigh, rangeMin, range, softStatusColors]);
|
|
102
|
+
const markerColor = statusColors[status];
|
|
103
|
+
return /* @__PURE__ */ jsxs(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: `limits-bar ${className}`,
|
|
107
|
+
role: "meter",
|
|
108
|
+
"aria-valuenow": value,
|
|
109
|
+
"aria-valuemin": rangeMin,
|
|
110
|
+
"aria-valuemax": rangeMax,
|
|
111
|
+
"aria-label": label ? `${label}: ${value}${unit ? " " + unit : ""}` : `${value}${unit ? " " + unit : ""}`,
|
|
112
|
+
style: { width, fontFamily: tokens.typography.fontFamily.primary },
|
|
113
|
+
children: [
|
|
114
|
+
(label || showValue) && !compact && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: tokens.spacing.xs, fontSize: tokens.typography.fontSize.sm }, children: [
|
|
115
|
+
label && /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary, fontWeight: tokens.typography.fontWeight.medium }, children: label }),
|
|
116
|
+
showValue && /* @__PURE__ */ jsxs("span", { style: { color: markerColor, fontWeight: tokens.typography.fontWeight.medium, fontFamily: tokens.typography.fontFamily.mono }, children: [
|
|
117
|
+
typeof value === "number" ? value.toFixed(2) : value,
|
|
118
|
+
unit && /* @__PURE__ */ jsx("span", { style: { fontSize: tokens.typography.fontSize.xxs, marginLeft: tokens.spacing.xxs, color: tokens.colors.text.muted }, children: unit })
|
|
119
|
+
] })
|
|
120
|
+
] }),
|
|
121
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
122
|
+
position: "relative",
|
|
123
|
+
height: barHeight,
|
|
124
|
+
borderRadius: tokens.borderRadius.full,
|
|
125
|
+
background: tokens.colors.background.base,
|
|
126
|
+
border: `1px solid ${tokens.colors.border.muted}`,
|
|
127
|
+
overflow: "hidden"
|
|
128
|
+
}, children: [
|
|
129
|
+
zones.map((z, i) => /* @__PURE__ */ jsx(
|
|
130
|
+
"div",
|
|
131
|
+
{
|
|
132
|
+
style: {
|
|
133
|
+
position: "absolute",
|
|
134
|
+
left: `${z.start}%`,
|
|
135
|
+
width: `${z.end - z.start}%`,
|
|
136
|
+
height: "100%",
|
|
137
|
+
background: z.color
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
i
|
|
141
|
+
)),
|
|
142
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
143
|
+
position: "absolute",
|
|
144
|
+
left: `${valuePercent}%`,
|
|
145
|
+
top: 0,
|
|
146
|
+
bottom: 0,
|
|
147
|
+
width: compact ? 3 : 4,
|
|
148
|
+
marginLeft: compact ? -1.5 : -2,
|
|
149
|
+
background: markerColor,
|
|
150
|
+
borderRadius: tokens.borderRadius.sm,
|
|
151
|
+
boxShadow: `0 0 8px ${markerColor}66, 0 0 3px ${markerColor}44`,
|
|
152
|
+
transition: "left 300ms cubic-bezier(0.4, 0, 0.2, 1), background 300ms ease"
|
|
153
|
+
} }),
|
|
154
|
+
compact && showValue && /* @__PURE__ */ jsxs("div", { style: {
|
|
155
|
+
position: "absolute",
|
|
156
|
+
right: tokens.spacing.xs,
|
|
157
|
+
top: "50%",
|
|
158
|
+
transform: "translateY(-50%)",
|
|
159
|
+
fontSize: tokens.typography.fontSize.micro,
|
|
160
|
+
fontWeight: tokens.typography.fontWeight.medium,
|
|
161
|
+
color: markerColor,
|
|
162
|
+
fontFamily: tokens.typography.fontFamily.mono,
|
|
163
|
+
textShadow: `0 0 4px ${tokens.colors.background.base}`
|
|
164
|
+
}, children: [
|
|
165
|
+
typeof value === "number" ? value.toFixed(1) : value,
|
|
166
|
+
unit || ""
|
|
167
|
+
] })
|
|
168
|
+
] }),
|
|
169
|
+
showThresholds && !compact && /* @__PURE__ */ jsx("div", { style: { position: "relative", height: 14, marginTop: tokens.spacing.xxs }, children: [
|
|
170
|
+
{ val: redLow, color: softStatusColors.critical },
|
|
171
|
+
{ val: yellowLow, color: softStatusColors.caution },
|
|
172
|
+
{ val: greenHigh ?? yellowHigh, color: softStatusColors.caution },
|
|
173
|
+
{ val: redHigh, color: softStatusColors.critical }
|
|
174
|
+
].filter((t) => t.val !== void 0).map((t, i) => {
|
|
175
|
+
const pct = range > 0 ? (t.val - rangeMin) / range * 100 : 0;
|
|
176
|
+
return /* @__PURE__ */ jsx(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
"aria-label": `Threshold: ${t.val}`,
|
|
180
|
+
style: {
|
|
181
|
+
position: "absolute",
|
|
182
|
+
left: `${pct}%`,
|
|
183
|
+
transform: "translateX(-50%)",
|
|
184
|
+
fontSize: tokens.typography.fontSize.micro,
|
|
185
|
+
color: t.color,
|
|
186
|
+
fontFamily: tokens.typography.fontFamily.mono
|
|
187
|
+
},
|
|
188
|
+
children: t.val
|
|
189
|
+
},
|
|
190
|
+
i
|
|
191
|
+
);
|
|
192
|
+
}) })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
export {
|
|
198
|
+
LimitsBar
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=LimitsBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LimitsBar.js","sources":["../../../src/react/core/LimitsBar.tsx"],"sourcesContent":["/**\n * @zendir/ui - LimitsBar Component\n * \n * Visual limits indicator for telemetry monitoring and spacecraft health assessment.\n * Displays a horizontal bar with colored zones (red-low, yellow-low, green, yellow-high, red-high)\n * and a marker showing the current value position within the range.\n * \n * Supports:\n * - 5-zone limits (red-low, yellow-low, green/normal, yellow-high, red-high)\n * - 3-zone limits (low, nominal, high) \n * - Blue zone for \"out of range\" / stale\n * - Animated value transitions\n * - Compact and full display modes\n * - Value label with units\n * - Configurable thresholds\n * \n * Astro UX Compliance:\n * - Uses official Astro status colors\n * - Consistent with Astro monitoring patterns\n * \n * @example\n * ```tsx\n * <LimitsBar\n * value={72.5}\n * redLow={10} yellowLow={25} greenLow={40}\n * greenHigh={80} yellowHigh={90} redHigh={100}\n * label=\"Temperature\" unit=\"°C\"\n * />\n * ```\n */\n\nimport React, { useMemo, memo } from 'react';\nimport { useTheme } from '../theme';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type LimitsState = 'red_low' | 'yellow_low' | 'green' | 'yellow_high' | 'red_high' | 'blue' | 'stale';\n\nexport interface LimitsBarProps {\n /** Current value */\n value: number;\n /** Red low threshold (minimum critical) */\n redLow?: number;\n /** Yellow low threshold (minimum warning) */\n yellowLow?: number;\n /** Green low threshold (start of nominal) */\n greenLow?: number;\n /** Green high threshold (end of nominal) */\n greenHigh?: number;\n /** Yellow high threshold (maximum warning) */\n yellowHigh?: number;\n /** Red high threshold (maximum critical) */\n redHigh?: number;\n /** Overall min for the bar (defaults to redLow - 10%) */\n min?: number;\n /** Overall max for the bar (defaults to redHigh + 10%) */\n max?: number;\n /** Label text */\n label?: string;\n /** Unit string */\n unit?: string;\n /** Whether the value is stale / not updating */\n stale?: boolean;\n /** Compact mode (thinner bar, less text) */\n compact?: boolean;\n /** Show the numeric value on the bar */\n showValue?: boolean;\n /** Show limit threshold labels */\n showThresholds?: boolean;\n /** Width (default: '100%') */\n width?: number | string;\n /** Height of the bar (default: 20 for normal, 12 for compact) */\n barHeight?: number;\n /** Custom status override (forces a specific status regardless of value) */\n statusOverride?: LimitsState;\n /** Called when status changes */\n onStatusChange?: (status: LimitsState, value: number) => void;\n /** When false, lower-limit zones (red-low, yellow-low, green-low) are hidden even if threshold values are provided */\n showLower?: boolean;\n /** When false, upper-limit zones (green-high, yellow-high, red-high) are hidden even if threshold values are provided */\n showUpper?: boolean;\n /** CSS class */\n className?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction getLimitsState(\n value: number,\n redLow?: number,\n yellowLow?: number,\n greenLow?: number,\n greenHigh?: number,\n yellowHigh?: number,\n redHigh?: number,\n): LimitsState {\n if (redLow !== undefined && value < redLow) return 'red_low';\n if (yellowLow !== undefined && value < yellowLow) return 'yellow_low';\n if (greenLow !== undefined && value < greenLow) return 'yellow_low';\n if (redHigh !== undefined && value > redHigh) return 'red_high';\n if (yellowHigh !== undefined && value > yellowHigh) return 'yellow_high';\n if (greenHigh !== undefined && value > greenHigh) return 'yellow_high';\n return 'green';\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport const LimitsBar = memo(function LimitsBar({\n value,\n redLow: redLowProp,\n yellowLow: yellowLowProp,\n greenLow: greenLowProp,\n greenHigh: greenHighProp,\n yellowHigh: yellowHighProp,\n redHigh: redHighProp,\n min: minProp,\n max: maxProp,\n label,\n unit,\n stale = false,\n compact = false,\n showValue = true,\n showThresholds = false,\n showLower = true,\n showUpper = true,\n width = '100%',\n barHeight: barHeightProp,\n statusOverride,\n className = '',\n}: LimitsBarProps): React.ReactElement {\n // Mask thresholds based on showLower / showUpper flags\n const redLow = showLower ? redLowProp : undefined;\n const yellowLow = showLower ? yellowLowProp : undefined;\n const greenLow = showLower ? greenLowProp : undefined;\n const greenHigh = showUpper ? greenHighProp : undefined;\n const yellowHigh = showUpper ? yellowHighProp : undefined;\n const redHigh = showUpper ? redHighProp : undefined;\n const { tokens } = useTheme();\n const softStatusColors = useMemo(() => ({\n normal: tokens.colors.status.normal,\n caution: tokens.colors.status.caution,\n serious: tokens.colors.status.serious,\n critical: tokens.colors.status.critical,\n off: tokens.colors.status.off,\n standby: tokens.colors.status.standby,\n }), [tokens]);\n\n const barHeight = barHeightProp ?? (compact ? 12 : 20);\n \n const _thresholds = useMemo(() => {\n const rl = redLow ?? -Infinity;\n const yl = yellowLow ?? redLow ?? -Infinity;\n const gl = greenLow ?? yellowLow ?? redLow ?? -Infinity;\n const gh = greenHigh ?? yellowHigh ?? redHigh ?? Infinity;\n const yh = yellowHigh ?? redHigh ?? Infinity;\n const rh = redHigh ?? Infinity;\n return { rl, yl, gl, gh, yh, rh };\n }, [redLow, yellowLow, greenLow, greenHigh, yellowHigh, redHigh]);\n\n const rangeMin = minProp ?? (redLow !== undefined ? redLow - (redHigh !== undefined ? (redHigh - redLow) * 0.1 : 10) : 0);\n const rangeMax = maxProp ?? (redHigh !== undefined ? redHigh + (redLow !== undefined ? (redHigh - redLow) * 0.1 : 10) : 100);\n const range = rangeMax - rangeMin;\n\n const status = stale ? 'stale' : (statusOverride ?? getLimitsState(value, redLow, yellowLow, greenLow, greenHigh, yellowHigh, redHigh));\n\n const statusColors: Record<LimitsState, string> = {\n red_low: softStatusColors.critical,\n red_high: softStatusColors.critical,\n yellow_low: softStatusColors.caution,\n yellow_high: softStatusColors.caution,\n green: softStatusColors.normal,\n blue: softStatusColors.standby,\n stale: softStatusColors.off,\n };\n\n const valuePercent = range > 0 ? Math.max(0, Math.min(100, ((value - rangeMin) / range) * 100)) : 50;\n\n // Build zone segments\n const zones = useMemo(() => {\n const segs: { start: number; end: number; color: string }[] = [];\n const toPercent = (v: number) => Math.max(0, Math.min(100, ((v - rangeMin) / range) * 100));\n\n const critical = softStatusColors.critical;\n const caution = softStatusColors.caution;\n const normal = softStatusColors.normal;\n\n if (redLow !== undefined) {\n segs.push({ start: 0, end: toPercent(redLow), color: `${critical}66` });\n }\n if (yellowLow !== undefined) {\n const s = redLow !== undefined ? toPercent(redLow) : 0;\n segs.push({ start: s, end: toPercent(yellowLow), color: `${caution}66` });\n }\n {\n const s = yellowLow !== undefined ? toPercent(yellowLow) : (redLow !== undefined ? toPercent(redLow) : 0);\n const e = yellowHigh !== undefined ? toPercent(yellowHigh) : (redHigh !== undefined ? toPercent(redHigh) : 100);\n segs.push({ start: s, end: e, color: `${normal}44` });\n }\n if (yellowHigh !== undefined) {\n const e = redHigh !== undefined ? toPercent(redHigh) : 100;\n segs.push({ start: toPercent(yellowHigh), end: e, color: `${caution}66` });\n }\n if (redHigh !== undefined) {\n segs.push({ start: toPercent(redHigh), end: 100, color: `${critical}66` });\n }\n\n return segs;\n }, [redLow, yellowLow, yellowHigh, redHigh, rangeMin, range, softStatusColors]);\n\n const markerColor = statusColors[status];\n\n return (\n <div\n className={`limits-bar ${className}`}\n role=\"meter\"\n aria-valuenow={value}\n aria-valuemin={rangeMin}\n aria-valuemax={rangeMax}\n aria-label={label ? `${label}: ${value}${unit ? ' ' + unit : ''}` : `${value}${unit ? ' ' + unit : ''}`}\n style={{ width, fontFamily: tokens.typography.fontFamily.primary }}\n >\n {/* Label row */}\n {(label || showValue) && !compact && (\n <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: tokens.spacing.xs, fontSize: tokens.typography.fontSize.sm }}>\n {label && <span style={{ color: tokens.colors.text.secondary, fontWeight: tokens.typography.fontWeight.medium }}>{label}</span>}\n {showValue && (\n <span style={{ color: markerColor, fontWeight: tokens.typography.fontWeight.medium, fontFamily: tokens.typography.fontFamily.mono }}>\n {typeof value === 'number' ? value.toFixed(2) : value}\n {unit && <span style={{ fontSize: tokens.typography.fontSize.xxs, marginLeft: tokens.spacing.xxs, color: tokens.colors.text.muted }}>{unit}</span>}\n </span>\n )}\n </div>\n )}\n\n {/* Bar */}\n <div style={{\n position: 'relative',\n height: barHeight,\n borderRadius: tokens.borderRadius.full,\n background: tokens.colors.background.base,\n border: `1px solid ${tokens.colors.border.muted}`,\n overflow: 'hidden',\n }}>\n {/* Zone segments */}\n {zones.map((z, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: `${z.start}%`,\n width: `${z.end - z.start}%`,\n height: '100%',\n background: z.color,\n }}\n />\n ))}\n\n {/* Value marker */}\n <div style={{\n position: 'absolute',\n left: `${valuePercent}%`,\n top: 0,\n bottom: 0,\n width: compact ? 3 : 4,\n marginLeft: compact ? -1.5 : -2,\n background: markerColor,\n borderRadius: tokens.borderRadius.sm,\n boxShadow: `0 0 8px ${markerColor}66, 0 0 3px ${markerColor}44`,\n transition: 'left 300ms cubic-bezier(0.4, 0, 0.2, 1), background 300ms ease',\n }} />\n\n {/* Compact label */}\n {compact && showValue && (\n <div style={{\n position: 'absolute',\n right: tokens.spacing.xs,\n top: '50%',\n transform: 'translateY(-50%)',\n fontSize: tokens.typography.fontSize.micro,\n fontWeight: tokens.typography.fontWeight.medium,\n color: markerColor,\n fontFamily: tokens.typography.fontFamily.mono,\n textShadow: `0 0 4px ${tokens.colors.background.base}`,\n }}>\n {typeof value === 'number' ? value.toFixed(1) : value}{unit || ''}\n </div>\n )}\n </div>\n\n {/* Threshold labels */}\n {showThresholds && !compact && (\n <div style={{ position: 'relative', height: 14, marginTop: tokens.spacing.xxs }}>\n {[\n { val: redLow, color: softStatusColors.critical },\n { val: yellowLow, color: softStatusColors.caution },\n { val: greenHigh ?? yellowHigh, color: softStatusColors.caution },\n { val: redHigh, color: softStatusColors.critical },\n ].filter(t => t.val !== undefined).map((t, i) => {\n const pct = range > 0 ? ((t.val! - rangeMin) / range) * 100 : 0;\n return (\n <span\n key={i}\n aria-label={`Threshold: ${t.val}`}\n style={{\n position: 'absolute',\n left: `${pct}%`,\n transform: 'translateX(-50%)',\n fontSize: tokens.typography.fontSize.micro,\n color: t.color,\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {t.val}\n </span>\n );\n })}\n </div>\n )}\n </div>\n );\n});\n\nexport default LimitsBar;\n"],"names":["LimitsBar"],"mappings":"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"}
|