@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.
Files changed (359) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +589 -0
  4. package/dist/index.d.ts +8 -0
  5. package/dist/index.js +421 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/react/3d/EarthViewer.d.ts +46 -0
  8. package/dist/react/3d/EarthViewer.js +836 -0
  9. package/dist/react/3d/EarthViewer.js.map +1 -0
  10. package/dist/react/3d/SolarSystemViewer.d.ts +43 -0
  11. package/dist/react/3d/SolarSystemViewer.js +372 -0
  12. package/dist/react/3d/SolarSystemViewer.js.map +1 -0
  13. package/dist/react/3d/ZenSpace3D.d.ts +16 -0
  14. package/dist/react/3d/ZenSpace3D.js +1253 -0
  15. package/dist/react/3d/ZenSpace3D.js.map +1 -0
  16. package/dist/react/3d/ZenSpace3DCesium.d.ts +9 -0
  17. package/dist/react/3d/ZenSpace3DCesium.js +186 -0
  18. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -0
  19. package/dist/react/3d/ZenSpace3DShaders.d.ts +78 -0
  20. package/dist/react/3d/ZenSpace3DShaders.js +94 -0
  21. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -0
  22. package/dist/react/3d/ZenSpace3DTypes.d.ts +614 -0
  23. package/dist/react/3d/ZenSpace3DUtils.d.ts +183 -0
  24. package/dist/react/3d/ZenSpace3DUtils.js +213 -0
  25. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -0
  26. package/dist/react/3d/index.d.ts +23 -0
  27. package/dist/react/3d/threeLoader.d.ts +22 -0
  28. package/dist/react/3d/threeLoader.js +18 -0
  29. package/dist/react/3d/threeLoader.js.map +1 -0
  30. package/dist/react/astro/ClassificationBanner.d.ts +25 -0
  31. package/dist/react/astro/ClassificationBanner.js +83 -0
  32. package/dist/react/astro/ClassificationBanner.js.map +1 -0
  33. package/dist/react/astro/GlobalStatusBar.d.ts +42 -0
  34. package/dist/react/astro/GlobalStatusBar.js +165 -0
  35. package/dist/react/astro/GlobalStatusBar.js.map +1 -0
  36. package/dist/react/astro/MissionClock.d.ts +169 -0
  37. package/dist/react/astro/MissionClock.js +411 -0
  38. package/dist/react/astro/MissionClock.js.map +1 -0
  39. package/dist/react/astro/MonitoringIcon.d.ts +60 -0
  40. package/dist/react/astro/MonitoringIcon.js +369 -0
  41. package/dist/react/astro/MonitoringIcon.js.map +1 -0
  42. package/dist/react/astro/Notification.d.ts +42 -0
  43. package/dist/react/astro/Notification.js +156 -0
  44. package/dist/react/astro/Notification.js.map +1 -0
  45. package/dist/react/astro/Progress.d.ts +39 -0
  46. package/dist/react/astro/Progress.js +149 -0
  47. package/dist/react/astro/Progress.js.map +1 -0
  48. package/dist/react/astro/SimulationControls.d.ts +136 -0
  49. package/dist/react/astro/SimulationControls.js +668 -0
  50. package/dist/react/astro/SimulationControls.js.map +1 -0
  51. package/dist/react/astro/StatusIndicator.d.ts +34 -0
  52. package/dist/react/astro/StatusIndicator.js +189 -0
  53. package/dist/react/astro/StatusIndicator.js.map +1 -0
  54. package/dist/react/astro/UnifiedTimeline.d.ts +106 -0
  55. package/dist/react/astro/UnifiedTimeline.js +1768 -0
  56. package/dist/react/astro/UnifiedTimeline.js.map +1 -0
  57. package/dist/react/astro/index.d.ts +63 -0
  58. package/dist/react/cards/AccessCard.d.ts +37 -0
  59. package/dist/react/cards/AccessCard.js +410 -0
  60. package/dist/react/cards/AccessCard.js.map +1 -0
  61. package/dist/react/cards/OrbitCard.d.ts +31 -0
  62. package/dist/react/cards/OrbitCard.js +372 -0
  63. package/dist/react/cards/OrbitCard.js.map +1 -0
  64. package/dist/react/cards/SpacecraftCard.d.ts +54 -0
  65. package/dist/react/cards/SpacecraftCard.js +941 -0
  66. package/dist/react/cards/SpacecraftCard.js.map +1 -0
  67. package/dist/react/cards/TelemetryCard.d.ts +40 -0
  68. package/dist/react/cards/TelemetryCard.js +742 -0
  69. package/dist/react/cards/TelemetryCard.js.map +1 -0
  70. package/dist/react/cards/TelemetryStreamCard.d.ts +59 -0
  71. package/dist/react/cards/TelemetryStreamCard.js +309 -0
  72. package/dist/react/cards/TelemetryStreamCard.js.map +1 -0
  73. package/dist/react/cards/index.d.ts +13 -0
  74. package/dist/react/charts/GroundTrackMap.d.ts +112 -0
  75. package/dist/react/charts/GroundTrackMap.js +1123 -0
  76. package/dist/react/charts/GroundTrackMap.js.map +1 -0
  77. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +26 -0
  78. package/dist/react/charts/GroundTrackMapLeaflet.js +571 -0
  79. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -0
  80. package/dist/react/charts/groundTrackMapLeafletTiles.d.ts +22 -0
  81. package/dist/react/charts/groundTrackMapLeafletTiles.js +11 -0
  82. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -0
  83. package/dist/react/charts/groundTrackMapLeafletUtils.d.ts +24 -0
  84. package/dist/react/charts/groundTrackMapLeafletUtils.js +109 -0
  85. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -0
  86. package/dist/react/charts/index.d.ts +10 -0
  87. package/dist/react/charts/unified/AstroChart.d.ts +24 -0
  88. package/dist/react/charts/unified/AstroChart.js +1405 -0
  89. package/dist/react/charts/unified/AstroChart.js.map +1 -0
  90. package/dist/react/charts/unified/PowerOverviewChart.d.ts +73 -0
  91. package/dist/react/charts/unified/PowerOverviewChart.js +488 -0
  92. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -0
  93. package/dist/react/charts/unified/domain.d.ts +845 -0
  94. package/dist/react/charts/unified/domain.js +3168 -0
  95. package/dist/react/charts/unified/domain.js.map +1 -0
  96. package/dist/react/charts/unified/generators.d.ts +276 -0
  97. package/dist/react/charts/unified/generators.js +518 -0
  98. package/dist/react/charts/unified/generators.js.map +1 -0
  99. package/dist/react/charts/unified/index.d.ts +55 -0
  100. package/dist/react/charts/unified/presets.d.ts +290 -0
  101. package/dist/react/charts/unified/presets.js +999 -0
  102. package/dist/react/charts/unified/presets.js.map +1 -0
  103. package/dist/react/charts/unified/sync.d.ts +69 -0
  104. package/dist/react/charts/unified/sync.js +219 -0
  105. package/dist/react/charts/unified/sync.js.map +1 -0
  106. package/dist/react/charts/unified/theme.d.ts +447 -0
  107. package/dist/react/charts/unified/theme.js +562 -0
  108. package/dist/react/charts/unified/theme.js.map +1 -0
  109. package/dist/react/charts/unified/types.d.ts +826 -0
  110. package/dist/react/charts/unified/useChartStream.d.ts +58 -0
  111. package/dist/react/charts/unified/useChartStream.js +226 -0
  112. package/dist/react/charts/unified/useChartStream.js.map +1 -0
  113. package/dist/react/chatgpt/AppCard.d.ts +59 -0
  114. package/dist/react/chatgpt/AppCard.js +306 -0
  115. package/dist/react/chatgpt/AppCard.js.map +1 -0
  116. package/dist/react/chatgpt/ChatGPTCard.d.ts +6 -0
  117. package/dist/react/chatgpt/index.d.ts +167 -0
  118. package/dist/react/chatgpt/index.js +166 -0
  119. package/dist/react/chatgpt/index.js.map +1 -0
  120. package/dist/react/context/DisplaySettingsContext.d.ts +107 -0
  121. package/dist/react/context/DisplaySettingsContext.js +169 -0
  122. package/dist/react/context/DisplaySettingsContext.js.map +1 -0
  123. package/dist/react/context/index.d.ts +5 -0
  124. package/dist/react/core/ActivityPlanner.d.ts +45 -0
  125. package/dist/react/core/ActivityPlanner.js +532 -0
  126. package/dist/react/core/ActivityPlanner.js.map +1 -0
  127. package/dist/react/core/AppBar.d.ts +71 -0
  128. package/dist/react/core/AppBar.js +817 -0
  129. package/dist/react/core/AppBar.js.map +1 -0
  130. package/dist/react/core/AstroIcon.d.ts +84 -0
  131. package/dist/react/core/AstroIcon.js +1243 -0
  132. package/dist/react/core/AstroIcon.js.map +1 -0
  133. package/dist/react/core/Badge.d.ts +27 -0
  134. package/dist/react/core/Badge.js +134 -0
  135. package/dist/react/core/Badge.js.map +1 -0
  136. package/dist/react/core/Button.d.ts +26 -0
  137. package/dist/react/core/Button.js +306 -0
  138. package/dist/react/core/Button.js.map +1 -0
  139. package/dist/react/core/CardHeader.d.ts +34 -0
  140. package/dist/react/core/CardHeader.js +316 -0
  141. package/dist/react/core/CardHeader.js.map +1 -0
  142. package/dist/react/core/ChatPanel.d.ts +627 -0
  143. package/dist/react/core/ChatPanel.js +1144 -0
  144. package/dist/react/core/ChatPanel.js.map +1 -0
  145. package/dist/react/core/Checkbox.d.ts +26 -0
  146. package/dist/react/core/Checkbox.js +130 -0
  147. package/dist/react/core/Checkbox.js.map +1 -0
  148. package/dist/react/core/ColorPickerPanel.d.ts +25 -0
  149. package/dist/react/core/ColorPickerPanel.js +293 -0
  150. package/dist/react/core/ColorPickerPanel.js.map +1 -0
  151. package/dist/react/core/CommandBuilder.d.ts +74 -0
  152. package/dist/react/core/CommandBuilder.js +518 -0
  153. package/dist/react/core/CommandBuilder.js.map +1 -0
  154. package/dist/react/core/ConfirmDialog.d.ts +45 -0
  155. package/dist/react/core/ConfirmDialog.js +315 -0
  156. package/dist/react/core/ConfirmDialog.js.map +1 -0
  157. package/dist/react/core/ConnectionForm.d.ts +57 -0
  158. package/dist/react/core/ConnectionForm.js +496 -0
  159. package/dist/react/core/ConnectionForm.js.map +1 -0
  160. package/dist/react/core/Container.d.ts +51 -0
  161. package/dist/react/core/Container.js +670 -0
  162. package/dist/react/core/Container.js.map +1 -0
  163. package/dist/react/core/CopyButton.d.ts +39 -0
  164. package/dist/react/core/CopyButton.js +105 -0
  165. package/dist/react/core/CopyButton.js.map +1 -0
  166. package/dist/react/core/DataTable.d.ts +113 -0
  167. package/dist/react/core/DataTable.js +446 -0
  168. package/dist/react/core/DataTable.js.map +1 -0
  169. package/dist/react/core/DataValue.d.ts +64 -0
  170. package/dist/react/core/DataValue.js +545 -0
  171. package/dist/react/core/DataValue.js.map +1 -0
  172. package/dist/react/core/Dialog.d.ts +32 -0
  173. package/dist/react/core/Dialog.js +201 -0
  174. package/dist/react/core/Dialog.js.map +1 -0
  175. package/dist/react/core/FileExplorer.d.ts +65 -0
  176. package/dist/react/core/FileExplorer.js +520 -0
  177. package/dist/react/core/FileExplorer.js.map +1 -0
  178. package/dist/react/core/GlassCard.d.ts +129 -0
  179. package/dist/react/core/GlassCard.js +375 -0
  180. package/dist/react/core/GlassCard.js.map +1 -0
  181. package/dist/react/core/HeaderIconWithStatus.d.ts +39 -0
  182. package/dist/react/core/HeaderIconWithStatus.js +157 -0
  183. package/dist/react/core/HeaderIconWithStatus.js.map +1 -0
  184. package/dist/react/core/HexViewer.d.ts +143 -0
  185. package/dist/react/core/HexViewer.js +1106 -0
  186. package/dist/react/core/HexViewer.js.map +1 -0
  187. package/dist/react/core/Icon.d.ts +32 -0
  188. package/dist/react/core/Icon.js +142 -0
  189. package/dist/react/core/Icon.js.map +1 -0
  190. package/dist/react/core/ImageGallery.d.ts +41 -0
  191. package/dist/react/core/ImageGallery.js +320 -0
  192. package/dist/react/core/ImageGallery.js.map +1 -0
  193. package/dist/react/core/Input.d.ts +38 -0
  194. package/dist/react/core/Input.js +288 -0
  195. package/dist/react/core/Input.js.map +1 -0
  196. package/dist/react/core/LimitsBar.d.ts +51 -0
  197. package/dist/react/core/LimitsBar.js +200 -0
  198. package/dist/react/core/LimitsBar.js.map +1 -0
  199. package/dist/react/core/LogViewer.d.ts +61 -0
  200. package/dist/react/core/LogViewer.js +599 -0
  201. package/dist/react/core/LogViewer.js.map +1 -0
  202. package/dist/react/core/MessageStream.d.ts +58 -0
  203. package/dist/react/core/MessageStream.js +455 -0
  204. package/dist/react/core/MessageStream.js.map +1 -0
  205. package/dist/react/core/MissionCalendar.d.ts +81 -0
  206. package/dist/react/core/MissionCalendar.js +1049 -0
  207. package/dist/react/core/MissionCalendar.js.map +1 -0
  208. package/dist/react/core/NumberInput.d.ts +85 -0
  209. package/dist/react/core/NumberInput.js +507 -0
  210. package/dist/react/core/NumberInput.js.map +1 -0
  211. package/dist/react/core/PacketViewer.d.ts +73 -0
  212. package/dist/react/core/PacketViewer.js +431 -0
  213. package/dist/react/core/PacketViewer.js.map +1 -0
  214. package/dist/react/core/Pagination.d.ts +30 -0
  215. package/dist/react/core/Pagination.js +190 -0
  216. package/dist/react/core/Pagination.js.map +1 -0
  217. package/dist/react/core/PinInput.d.ts +41 -0
  218. package/dist/react/core/PinInput.js +210 -0
  219. package/dist/react/core/PinInput.js.map +1 -0
  220. package/dist/react/core/Popover.d.ts +55 -0
  221. package/dist/react/core/Popover.js +288 -0
  222. package/dist/react/core/Popover.js.map +1 -0
  223. package/dist/react/core/Select.d.ts +42 -0
  224. package/dist/react/core/Select.js +303 -0
  225. package/dist/react/core/Select.js.map +1 -0
  226. package/dist/react/core/SideNav.d.ts +103 -0
  227. package/dist/react/core/SideNav.js +551 -0
  228. package/dist/react/core/SideNav.js.map +1 -0
  229. package/dist/react/core/SidePanel.d.ts +33 -0
  230. package/dist/react/core/SidePanel.js +199 -0
  231. package/dist/react/core/SidePanel.js.map +1 -0
  232. package/dist/react/core/Tabs.d.ts +47 -0
  233. package/dist/react/core/Tabs.js +129 -0
  234. package/dist/react/core/Tabs.js.map +1 -0
  235. package/dist/react/core/Toast.d.ts +56 -0
  236. package/dist/react/core/Toast.js +229 -0
  237. package/dist/react/core/Toast.js.map +1 -0
  238. package/dist/react/core/Toggle.d.ts +22 -0
  239. package/dist/react/core/Toggle.js +151 -0
  240. package/dist/react/core/Toggle.js.map +1 -0
  241. package/dist/react/core/Tooltip.d.ts +19 -0
  242. package/dist/react/core/Tooltip.js +179 -0
  243. package/dist/react/core/Tooltip.js.map +1 -0
  244. package/dist/react/core/Typography.d.ts +127 -0
  245. package/dist/react/core/Typography.js +187 -0
  246. package/dist/react/core/Typography.js.map +1 -0
  247. package/dist/react/core/index.d.ts +108 -0
  248. package/dist/react/core/layout/Box.d.ts +77 -0
  249. package/dist/react/core/layout/Box.js +126 -0
  250. package/dist/react/core/layout/Box.js.map +1 -0
  251. package/dist/react/core/layout/Center.d.ts +20 -0
  252. package/dist/react/core/layout/Center.js +34 -0
  253. package/dist/react/core/layout/Center.js.map +1 -0
  254. package/dist/react/core/layout/Divider.d.ts +16 -0
  255. package/dist/react/core/layout/Divider.js +108 -0
  256. package/dist/react/core/layout/Divider.js.map +1 -0
  257. package/dist/react/core/layout/Flex.d.ts +30 -0
  258. package/dist/react/core/layout/Flex.js +128 -0
  259. package/dist/react/core/layout/Flex.js.map +1 -0
  260. package/dist/react/core/layout/Grid.d.ts +36 -0
  261. package/dist/react/core/layout/Grid.js +142 -0
  262. package/dist/react/core/layout/Grid.js.map +1 -0
  263. package/dist/react/core/layout/Spacer.d.ts +8 -0
  264. package/dist/react/core/layout/Spacer.js +31 -0
  265. package/dist/react/core/layout/Spacer.js.map +1 -0
  266. package/dist/react/core/layout/Stack.d.ts +54 -0
  267. package/dist/react/core/layout/Stack.js +74 -0
  268. package/dist/react/core/layout/Stack.js.map +1 -0
  269. package/dist/react/core/layout/index.d.ts +38 -0
  270. package/dist/react/core/layout/responsive.d.ts +23 -0
  271. package/dist/react/core/layout/responsive.js +26 -0
  272. package/dist/react/core/layout/responsive.js.map +1 -0
  273. package/dist/react/core/layout/useBreakpoint.d.ts +77 -0
  274. package/dist/react/core/layout/useBreakpoint.js +73 -0
  275. package/dist/react/core/layout/useBreakpoint.js.map +1 -0
  276. package/dist/react/core/propertyConfig.d.ts +443 -0
  277. package/dist/react/core/propertyConfig.js +399 -0
  278. package/dist/react/core/propertyConfig.js.map +1 -0
  279. package/dist/react/hooks/index.d.ts +21 -0
  280. package/dist/react/hooks/useAccessWindows.d.ts +66 -0
  281. package/dist/react/hooks/useCompactMode.d.ts +82 -0
  282. package/dist/react/hooks/useCompactMode.js +62 -0
  283. package/dist/react/hooks/useCompactMode.js.map +1 -0
  284. package/dist/react/hooks/useLiveSelection.d.ts +57 -0
  285. package/dist/react/hooks/useSimulationPlayback.d.ts +97 -0
  286. package/dist/react/hooks/useSimulationTime.d.ts +61 -0
  287. package/dist/react/hooks/useSpacecraftPosition.d.ts +50 -0
  288. package/dist/react/hooks/useSpacecraftPosition.js +89 -0
  289. package/dist/react/hooks/useSpacecraftPosition.js.map +1 -0
  290. package/dist/react/hooks/useTelemetry.d.ts +55 -0
  291. package/dist/react/hooks/useTelemetry.js +73 -0
  292. package/dist/react/hooks/useTelemetry.js.map +1 -0
  293. package/dist/react/hooks/useZendirSession.d.ts +109 -0
  294. package/dist/react/hooks/useZendirSession.js +148 -0
  295. package/dist/react/hooks/useZendirSession.js.map +1 -0
  296. package/dist/react/index.d.ts +74 -0
  297. package/dist/react/shared/ErrorBoundary.d.ts +63 -0
  298. package/dist/react/shared/ErrorBoundary.js +142 -0
  299. package/dist/react/shared/ErrorBoundary.js.map +1 -0
  300. package/dist/react/shared/Skeleton.d.ts +110 -0
  301. package/dist/react/shared/Skeleton.js +324 -0
  302. package/dist/react/shared/Skeleton.js.map +1 -0
  303. package/dist/react/shared/index.d.ts +12 -0
  304. package/dist/react/theme/ThemeProvider.d.ts +385 -0
  305. package/dist/react/theme/ThemeProvider.js +1096 -0
  306. package/dist/react/theme/ThemeProvider.js.map +1 -0
  307. package/dist/react/theme/astro-tokens.d.ts +153 -0
  308. package/dist/react/theme/cardAccent.d.ts +75 -0
  309. package/dist/react/theme/cardAccent.js +137 -0
  310. package/dist/react/theme/cardAccent.js.map +1 -0
  311. package/dist/react/theme/config.d.ts +39 -0
  312. package/dist/react/theme/index.d.ts +9 -0
  313. package/dist/react/types.d.ts +360 -0
  314. package/dist/react/types.js +58 -0
  315. package/dist/react/types.js.map +1 -0
  316. package/dist/react/utils/index.d.ts +247 -0
  317. package/dist/react/utils/index.js +423 -0
  318. package/dist/react/utils/index.js.map +1 -0
  319. package/dist/react/visualizations/EclipseTimerCard.d.ts +17 -0
  320. package/dist/react/visualizations/EclipseTimerCard.js +250 -0
  321. package/dist/react/visualizations/EclipseTimerCard.js.map +1 -0
  322. package/dist/react/visualizations/LinkBudgetCard.d.ts +50 -0
  323. package/dist/react/visualizations/LinkBudgetCard.js +444 -0
  324. package/dist/react/visualizations/LinkBudgetCard.js.map +1 -0
  325. package/dist/react/visualizations/NavBallCard.d.ts +17 -0
  326. package/dist/react/visualizations/NavBallCard.js +243 -0
  327. package/dist/react/visualizations/NavBallCard.js.map +1 -0
  328. package/dist/react/visualizations/PropulsionCard.d.ts +37 -0
  329. package/dist/react/visualizations/PropulsionCard.js +298 -0
  330. package/dist/react/visualizations/PropulsionCard.js.map +1 -0
  331. package/dist/react/visualizations/SensorFootprintCard.d.ts +33 -0
  332. package/dist/react/visualizations/SensorFootprintCard.js +326 -0
  333. package/dist/react/visualizations/SensorFootprintCard.js.map +1 -0
  334. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +38 -0
  335. package/dist/react/visualizations/ThermalHeatmapCard.js +372 -0
  336. package/dist/react/visualizations/ThermalHeatmapCard.js.map +1 -0
  337. package/dist/react/visualizations/index.d.ts +17 -0
  338. package/dist/react.d.ts +1 -0
  339. package/dist/react.js +421 -0
  340. package/dist/react.js.map +1 -0
  341. package/dist/shaders/atmosphere.frag.js +5 -0
  342. package/dist/shaders/atmosphere.frag.js.map +1 -0
  343. package/dist/shaders/atmosphere.vert.js +5 -0
  344. package/dist/shaders/atmosphere.vert.js.map +1 -0
  345. package/dist/shaders/stars.frag.js +5 -0
  346. package/dist/shaders/stars.frag.js.map +1 -0
  347. package/dist/shaders/stars.vert.js +5 -0
  348. package/dist/shaders/stars.vert.js.map +1 -0
  349. package/dist/style.css +143 -0
  350. package/dist/tokens/index.d.ts +296 -0
  351. package/dist/tokens/index.js +263 -0
  352. package/dist/tokens/index.js.map +1 -0
  353. package/dist/tokens/tokens.css +155 -0
  354. package/dist/types/index.d.ts +23 -0
  355. package/dist/types.d.ts +1 -0
  356. package/dist/types.js +2 -0
  357. package/dist/types.js.map +1 -0
  358. package/package.json +220 -0
  359. 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":"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"}
@@ -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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"}