@zendir/ui 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +640 -631
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/index.js +17 -221
  5. package/dist/react/3d/CesiumCaptureSource.d.ts +0 -1
  6. package/dist/react/3d/CesiumCaptureSource.js +364 -283
  7. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  8. package/dist/react/3d/ZenSpace3D.d.ts +2 -3
  9. package/dist/react/3d/ZenSpace3D.js +1681 -1237
  10. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  11. package/dist/react/3d/ZenSpace3DCesium.d.ts +0 -1
  12. package/dist/react/3d/ZenSpace3DCesium.js +513 -560
  13. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  14. package/dist/react/3d/ZenSpace3DShaders.js +61 -66
  15. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  16. package/dist/react/3d/ZenSpace3DTypes.d.ts +19 -20
  17. package/dist/react/3d/ZenSpace3DUtils.d.ts +0 -1
  18. package/dist/react/3d/ZenSpace3DUtils.js +37 -24
  19. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  20. package/dist/react/3d/capturePngAnalysis.js +42 -36
  21. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  22. package/dist/react/3d/index.d.ts +3 -3
  23. package/dist/react/3d/index.js +5 -53
  24. package/dist/react/3d/threeLoader.d.ts +1 -1
  25. package/dist/react/3d/threeLoader.js +23 -18
  26. package/dist/react/3d/threeLoader.js.map +1 -1
  27. package/dist/react/astro/ClassificationBanner.d.ts +2 -3
  28. package/dist/react/astro/ClassificationBanner.js +95 -79
  29. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  30. package/dist/react/astro/GlobalStatusBar.d.ts +0 -1
  31. package/dist/react/astro/GlobalStatusBar.js +157 -163
  32. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  33. package/dist/react/astro/MissionClock.d.ts +7 -8
  34. package/dist/react/astro/MissionClock.js +377 -400
  35. package/dist/react/astro/MissionClock.js.map +1 -1
  36. package/dist/react/astro/MonitoringIcon.d.ts +1 -2
  37. package/dist/react/astro/MonitoringIcon.js +422 -358
  38. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  39. package/dist/react/astro/Notification.d.ts +1 -2
  40. package/dist/react/astro/Notification.js +229 -126
  41. package/dist/react/astro/Notification.js.map +1 -1
  42. package/dist/react/astro/Progress.d.ts +0 -1
  43. package/dist/react/astro/Progress.js +199 -141
  44. package/dist/react/astro/Progress.js.map +1 -1
  45. package/dist/react/astro/SimulationControls.d.ts +3 -4
  46. package/dist/react/astro/SimulationControls.js +596 -650
  47. package/dist/react/astro/SimulationControls.js.map +1 -1
  48. package/dist/react/astro/StatusIndicator.d.ts +0 -1
  49. package/dist/react/astro/StatusIndicator.js +236 -170
  50. package/dist/react/astro/StatusIndicator.js.map +1 -1
  51. package/dist/react/astro/UnifiedTimeline.d.ts +9 -10
  52. package/dist/react/astro/UnifiedTimeline.js +2345 -2392
  53. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  54. package/dist/react/astro/index.d.ts +5 -5
  55. package/dist/react/astro/index.js +1 -25
  56. package/dist/react/cards/AccessCard.d.ts +0 -1
  57. package/dist/react/cards/AccessCard.js +471 -405
  58. package/dist/react/cards/AccessCard.js.map +1 -1
  59. package/dist/react/cards/OrbitCard.d.ts +0 -1
  60. package/dist/react/cards/OrbitCard.js +487 -364
  61. package/dist/react/cards/OrbitCard.js.map +1 -1
  62. package/dist/react/cards/SpacecraftCard.d.ts +0 -1
  63. package/dist/react/cards/SpacecraftCard.js +813 -925
  64. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  65. package/dist/react/cards/TelemetryCard.d.ts +0 -1
  66. package/dist/react/cards/TelemetryCard.js +1055 -732
  67. package/dist/react/cards/TelemetryCard.js.map +1 -1
  68. package/dist/react/cards/TelemetryStreamCard.d.ts +0 -1
  69. package/dist/react/cards/TelemetryStreamCard.js +323 -297
  70. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  71. package/dist/react/cards/index.d.ts +1 -1
  72. package/dist/react/cards/index.js +1 -8
  73. package/dist/react/charts/GroundTrackMap.d.ts +6 -7
  74. package/dist/react/charts/GroundTrackMap.js +1377 -1256
  75. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  76. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +1 -2
  77. package/dist/react/charts/GroundTrackMapLeaflet.js +1065 -987
  78. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  79. package/dist/react/charts/groundTrackMapLeafletTiles.js +34 -25
  80. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  81. package/dist/react/charts/groundTrackMapLeafletUtils.js +70 -61
  82. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  83. package/dist/react/charts/index.d.ts +1 -1
  84. package/dist/react/charts/index.js +7 -100
  85. package/dist/react/charts/unified/AstroChart.d.ts +1 -2
  86. package/dist/react/charts/unified/AstroChart.js +1331 -1411
  87. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  88. package/dist/react/charts/unified/PowerOverviewChart.d.ts +3 -3
  89. package/dist/react/charts/unified/PowerOverviewChart.js +495 -478
  90. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  91. package/dist/react/charts/unified/domain.d.ts +12 -13
  92. package/dist/react/charts/unified/domain.js +3999 -3145
  93. package/dist/react/charts/unified/domain.js.map +1 -1
  94. package/dist/react/charts/unified/generators.d.ts +3 -4
  95. package/dist/react/charts/unified/generators.js +561 -498
  96. package/dist/react/charts/unified/generators.js.map +1 -1
  97. package/dist/react/charts/unified/index.d.ts +1 -1
  98. package/dist/react/charts/unified/presets.d.ts +14 -15
  99. package/dist/react/charts/unified/presets.js +857 -994
  100. package/dist/react/charts/unified/presets.js.map +1 -1
  101. package/dist/react/charts/unified/sync.d.ts +2 -3
  102. package/dist/react/charts/unified/sync.js +229 -195
  103. package/dist/react/charts/unified/sync.js.map +1 -1
  104. package/dist/react/charts/unified/theme.d.ts +11 -12
  105. package/dist/react/charts/unified/theme.js +606 -642
  106. package/dist/react/charts/unified/theme.js.map +1 -1
  107. package/dist/react/charts/unified/types.d.ts +32 -33
  108. package/dist/react/charts/unified/useChartStream.d.ts +1 -2
  109. package/dist/react/charts/unified/useChartStream.js +203 -216
  110. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  111. package/dist/react/chatgpt/AppCard.d.ts +1 -2
  112. package/dist/react/chatgpt/index.d.ts +7 -7
  113. package/dist/react/chatgpt/index.js +160 -139
  114. package/dist/react/chatgpt/index.js.map +1 -1
  115. package/dist/react/context/CategoryContext.d.ts +0 -1
  116. package/dist/react/context/CategoryContext.js +78 -29
  117. package/dist/react/context/CategoryContext.js.map +1 -1
  118. package/dist/react/context/DisplaySettingsContext.d.ts +1 -2
  119. package/dist/react/context/DisplaySettingsContext.js +205 -156
  120. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  121. package/dist/react/context/SpatialSelectionContext.d.ts +0 -1
  122. package/dist/react/context/SpatialSelectionContext.js +36 -7
  123. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  124. package/dist/react/core/data/DataTable.d.ts +3 -4
  125. package/dist/react/core/data/DataTable.js +473 -440
  126. package/dist/react/core/data/DataTable.js.map +1 -1
  127. package/dist/react/core/data/DataValue.d.ts +4 -5
  128. package/dist/react/core/data/DataValue.js +605 -538
  129. package/dist/react/core/data/DataValue.js.map +1 -1
  130. package/dist/react/core/data/propertyConfig.d.ts +1 -2
  131. package/dist/react/core/data/propertyConfig.js +446 -382
  132. package/dist/react/core/data/propertyConfig.js.map +1 -1
  133. package/dist/react/core/display/AstroIcon.d.ts +4 -5
  134. package/dist/react/core/display/AstroIcon.js +339 -429
  135. package/dist/react/core/display/AstroIcon.js.map +1 -1
  136. package/dist/react/core/display/Badge.d.ts +2 -3
  137. package/dist/react/core/display/Badge.js +131 -131
  138. package/dist/react/core/display/Badge.js.map +1 -1
  139. package/dist/react/core/display/CardHeader.d.ts +0 -1
  140. package/dist/react/core/display/CardHeader.js +398 -311
  141. package/dist/react/core/display/CardHeader.js.map +1 -1
  142. package/dist/react/core/display/Container.d.ts +2 -3
  143. package/dist/react/core/display/Container.js +640 -668
  144. package/dist/react/core/display/Container.js.map +1 -1
  145. package/dist/react/core/display/CopyButton.d.ts +1 -2
  146. package/dist/react/core/display/CopyButton.js +158 -101
  147. package/dist/react/core/display/CopyButton.js.map +1 -1
  148. package/dist/react/core/display/GlassCard.d.ts +3 -4
  149. package/dist/react/core/display/GlassCard.js +416 -369
  150. package/dist/react/core/display/GlassCard.js.map +1 -1
  151. package/dist/react/core/display/HeaderIconWithStatus.d.ts +0 -1
  152. package/dist/react/core/display/HeaderIconWithStatus.js +152 -152
  153. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  154. package/dist/react/core/display/Icon.d.ts +2 -3
  155. package/dist/react/core/display/Icon.js +172 -143
  156. package/dist/react/core/display/Icon.js.map +1 -1
  157. package/dist/react/core/display/Typography.d.ts +24 -25
  158. package/dist/react/core/display/Typography.js +360 -178
  159. package/dist/react/core/display/Typography.js.map +1 -1
  160. package/dist/react/core/feedback/ConfirmDialog.d.ts +1 -2
  161. package/dist/react/core/feedback/ConfirmDialog.js +343 -304
  162. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  163. package/dist/react/core/feedback/Dialog.d.ts +2 -3
  164. package/dist/react/core/feedback/Dialog.js +189 -197
  165. package/dist/react/core/feedback/Dialog.js.map +1 -1
  166. package/dist/react/core/feedback/Toast.d.ts +2 -3
  167. package/dist/react/core/feedback/Toast.js +346 -207
  168. package/dist/react/core/feedback/Toast.js.map +1 -1
  169. package/dist/react/core/index.d.ts +26 -26
  170. package/dist/react/core/index.js +7 -119
  171. package/dist/react/core/inputs/Button.d.ts +2 -3
  172. package/dist/react/core/inputs/Button.js +281 -304
  173. package/dist/react/core/inputs/Button.js.map +1 -1
  174. package/dist/react/core/inputs/Checkbox.d.ts +2 -3
  175. package/dist/react/core/inputs/Checkbox.js +139 -127
  176. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  177. package/dist/react/core/inputs/Input.d.ts +3 -4
  178. package/dist/react/core/inputs/Input.js +277 -285
  179. package/dist/react/core/inputs/Input.js.map +1 -1
  180. package/dist/react/core/inputs/LimitsBar.d.ts +1 -2
  181. package/dist/react/core/inputs/LimitsBar.js +271 -196
  182. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  183. package/dist/react/core/inputs/NumberInput.d.ts +2 -3
  184. package/dist/react/core/inputs/NumberInput.js +531 -503
  185. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  186. package/dist/react/core/inputs/PinInput.d.ts +2 -3
  187. package/dist/react/core/inputs/PinInput.js +224 -207
  188. package/dist/react/core/inputs/PinInput.js.map +1 -1
  189. package/dist/react/core/inputs/Select.d.ts +1 -2
  190. package/dist/react/core/inputs/Select.js +298 -299
  191. package/dist/react/core/inputs/Select.js.map +1 -1
  192. package/dist/react/core/inputs/Toggle.d.ts +2 -3
  193. package/dist/react/core/inputs/Toggle.js +142 -148
  194. package/dist/react/core/inputs/Toggle.js.map +1 -1
  195. package/dist/react/core/layout/Box.d.ts +3 -4
  196. package/dist/react/core/layout/Box.js +118 -122
  197. package/dist/react/core/layout/Box.js.map +1 -1
  198. package/dist/react/core/layout/Center.d.ts +0 -1
  199. package/dist/react/core/layout/Center.js +45 -32
  200. package/dist/react/core/layout/Center.js.map +1 -1
  201. package/dist/react/core/layout/Divider.d.ts +1 -2
  202. package/dist/react/core/layout/Divider.js +112 -106
  203. package/dist/react/core/layout/Divider.js.map +1 -1
  204. package/dist/react/core/layout/Flex.d.ts +4 -5
  205. package/dist/react/core/layout/Flex.js +120 -124
  206. package/dist/react/core/layout/Flex.js.map +1 -1
  207. package/dist/react/core/layout/Grid.d.ts +5 -6
  208. package/dist/react/core/layout/Grid.js +131 -138
  209. package/dist/react/core/layout/Grid.js.map +1 -1
  210. package/dist/react/core/layout/Spacer.d.ts +0 -1
  211. package/dist/react/core/layout/Spacer.js +36 -29
  212. package/dist/react/core/layout/Spacer.js.map +1 -1
  213. package/dist/react/core/layout/Stack.d.ts +4 -5
  214. package/dist/react/core/layout/Stack.js +127 -70
  215. package/dist/react/core/layout/Stack.js.map +1 -1
  216. package/dist/react/core/layout/responsive.d.ts +1 -2
  217. package/dist/react/core/layout/responsive.js +25 -19
  218. package/dist/react/core/layout/responsive.js.map +1 -1
  219. package/dist/react/core/layout/useBreakpoint.d.ts +1 -1
  220. package/dist/react/core/layout/useBreakpoint.js +119 -66
  221. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  222. package/dist/react/core/navigation/AppBar.d.ts +1 -2
  223. package/dist/react/core/navigation/AppBar.js +827 -805
  224. package/dist/react/core/navigation/AppBar.js.map +1 -1
  225. package/dist/react/core/navigation/Pagination.d.ts +2 -3
  226. package/dist/react/core/navigation/Pagination.js +207 -187
  227. package/dist/react/core/navigation/Pagination.js.map +1 -1
  228. package/dist/react/core/navigation/SideNav.d.ts +11 -5
  229. package/dist/react/core/navigation/SideNav.js +857 -602
  230. package/dist/react/core/navigation/SideNav.js.map +1 -1
  231. package/dist/react/core/navigation/Tabs.d.ts +0 -1
  232. package/dist/react/core/navigation/Tabs.js +113 -119
  233. package/dist/react/core/navigation/Tabs.js.map +1 -1
  234. package/dist/react/core/overlays/Popover.d.ts +2 -3
  235. package/dist/react/core/overlays/Popover.js +303 -282
  236. package/dist/react/core/overlays/Popover.js.map +1 -1
  237. package/dist/react/core/overlays/SidePanel.d.ts +1 -2
  238. package/dist/react/core/overlays/SidePanel.js +217 -212
  239. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  240. package/dist/react/core/overlays/Tooltip.d.ts +1 -2
  241. package/dist/react/core/overlays/Tooltip.js +170 -176
  242. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  243. package/dist/react/core/widgets/ActivityPlanner.d.ts +0 -1
  244. package/dist/react/core/widgets/ActivityPlanner.js +855 -517
  245. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  246. package/dist/react/core/widgets/Capture.d.ts +2 -3
  247. package/dist/react/core/widgets/Capture.js +965 -779
  248. package/dist/react/core/widgets/Capture.js.map +1 -1
  249. package/dist/react/core/widgets/ChatPanel.d.ts +16 -17
  250. package/dist/react/core/widgets/ChatPanel.js +1734 -1034
  251. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  252. package/dist/react/core/widgets/ColorPickerPanel.d.ts +0 -1
  253. package/dist/react/core/widgets/ColorPickerPanel.js +298 -287
  254. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  255. package/dist/react/core/widgets/CommandBuilder.d.ts +2 -3
  256. package/dist/react/core/widgets/CommandBuilder.js +624 -516
  257. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  258. package/dist/react/core/widgets/ConnectionForm.d.ts +2 -3
  259. package/dist/react/core/widgets/ConnectionForm.js +528 -492
  260. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  261. package/dist/react/core/widgets/FileExplorer.d.ts +3 -4
  262. package/dist/react/core/widgets/FileExplorer.js +617 -505
  263. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  264. package/dist/react/core/widgets/HexViewer.d.ts +2 -3
  265. package/dist/react/core/widgets/HexViewer.js +1353 -1091
  266. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  267. package/dist/react/core/widgets/ImageFrame.d.ts +1 -2
  268. package/dist/react/core/widgets/ImageFrame.js +230 -193
  269. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  270. package/dist/react/core/widgets/ImageGallery.d.ts +2 -1
  271. package/dist/react/core/widgets/ImageGallery.js +380 -314
  272. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  273. package/dist/react/core/widgets/ImagePanel.d.ts +0 -1
  274. package/dist/react/core/widgets/ImagePanel.js +110 -101
  275. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  276. package/dist/react/core/widgets/LogViewer.d.ts +2 -3
  277. package/dist/react/core/widgets/LogViewer.js +711 -607
  278. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  279. package/dist/react/core/widgets/MessageStream.d.ts +3 -4
  280. package/dist/react/core/widgets/MessageStream.js +514 -444
  281. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  282. package/dist/react/core/widgets/MissionCalendar.d.ts +3 -4
  283. package/dist/react/core/widgets/MissionCalendar.js +1488 -1020
  284. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  285. package/dist/react/core/widgets/PacketViewer.d.ts +2 -3
  286. package/dist/react/core/widgets/PacketViewer.js +550 -421
  287. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  288. package/dist/react/core/widgets/capture-placeholder.png.js +6 -5
  289. package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -1
  290. package/dist/react/hooks/index.d.ts +5 -5
  291. package/dist/react/hooks/useAccessWindows.d.ts +0 -1
  292. package/dist/react/hooks/useCompactMode.d.ts +1 -1
  293. package/dist/react/hooks/useCompactMode.js +104 -58
  294. package/dist/react/hooks/useCompactMode.js.map +1 -1
  295. package/dist/react/hooks/useGroundTrackHistory.d.ts +0 -1
  296. package/dist/react/hooks/useSimulationScene.d.ts +1 -2
  297. package/dist/react/hooks/useSimulationScene.js +481 -374
  298. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  299. package/dist/react/index.d.ts +3 -3
  300. package/dist/react/panels/LayerControlPanel.d.ts +1 -2
  301. package/dist/react/panels/LayerControlPanel.js +223 -180
  302. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  303. package/dist/react/panels/ObjectInventoryPanel.d.ts +2 -3
  304. package/dist/react/panels/ObjectInventoryPanel.js +315 -250
  305. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  306. package/dist/react/panels/index.d.ts +1 -1
  307. package/dist/react/panels/index.js +1 -6
  308. package/dist/react/shared/ErrorBoundary.d.ts +1 -2
  309. package/dist/react/shared/ErrorBoundary.js +170 -139
  310. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  311. package/dist/react/shared/Skeleton.d.ts +1 -2
  312. package/dist/react/shared/Skeleton.js +300 -301
  313. package/dist/react/shared/Skeleton.js.map +1 -1
  314. package/dist/react/theme/ThemeProvider.d.ts +2 -321
  315. package/dist/react/theme/ThemeProvider.js +312 -939
  316. package/dist/react/theme/ThemeProvider.js.map +1 -1
  317. package/dist/react/theme/cardAccent.d.ts +1 -2
  318. package/dist/react/theme/cardAccent.js +196 -126
  319. package/dist/react/theme/cardAccent.js.map +1 -1
  320. package/dist/react/theme/config.d.ts +0 -1
  321. package/dist/react/theme/config.js +47 -25
  322. package/dist/react/theme/config.js.map +1 -1
  323. package/dist/react/theme/index.d.ts +2 -2
  324. package/dist/react/theme/index.js +1 -16
  325. package/dist/react/theme/types.d.ts +332 -0
  326. package/dist/react/theme/types.js +39 -0
  327. package/dist/react/theme/types.js.map +1 -0
  328. package/dist/react/types.d.ts +8 -8
  329. package/dist/react/types.js +147 -47
  330. package/dist/react/types.js.map +1 -1
  331. package/dist/react/utils/categoryPalette.d.ts +0 -1
  332. package/dist/react/utils/categoryPalette.js +91 -102
  333. package/dist/react/utils/categoryPalette.js.map +1 -1
  334. package/dist/react/utils/index.d.ts +5 -5
  335. package/dist/react/utils/index.js +457 -371
  336. package/dist/react/utils/index.js.map +1 -1
  337. package/dist/react/visualizations/EclipseTimerCard.d.ts +0 -1
  338. package/dist/react/visualizations/LinkBudgetCard.d.ts +0 -1
  339. package/dist/react/visualizations/NavBallCard.d.ts +0 -1
  340. package/dist/react/visualizations/PropulsionCard.d.ts +1 -2
  341. package/dist/react/visualizations/SensorFootprintCard.d.ts +1 -2
  342. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +0 -1
  343. package/dist/react/visualizations/index.d.ts +3 -3
  344. package/dist/react.d.ts +2 -1
  345. package/dist/react.js +17 -221
  346. package/dist/shaders/atmosphere.frag.js +6 -5
  347. package/dist/shaders/atmosphere.frag.js.map +1 -1
  348. package/dist/shaders/atmosphere.vert.js +6 -5
  349. package/dist/shaders/atmosphere.vert.js.map +1 -1
  350. package/dist/shaders/stars.frag.js +6 -5
  351. package/dist/shaders/stars.frag.js.map +1 -1
  352. package/dist/shaders/stars.vert.js +6 -5
  353. package/dist/shaders/stars.vert.js.map +1 -1
  354. package/dist/style.css +217 -194
  355. package/dist/tokens/core.d.ts +159 -0
  356. package/dist/tokens/core.js +144 -0
  357. package/dist/tokens/core.js.map +1 -0
  358. package/dist/tokens/css-vars.d.ts +213 -2
  359. package/dist/tokens/css-vars.js +590 -227
  360. package/dist/tokens/css-vars.js.map +1 -1
  361. package/dist/tokens/index.d.ts +31 -228
  362. package/dist/tokens/index.js +281 -366
  363. package/dist/tokens/index.js.map +1 -1
  364. package/dist/tokens/palettes/astro.d.ts +129 -0
  365. package/dist/tokens/palettes/astro.js +112 -0
  366. package/dist/tokens/palettes/astro.js.map +1 -0
  367. package/dist/tokens/palettes/index.d.ts +288 -0
  368. package/dist/tokens/palettes/index.js +35 -0
  369. package/dist/tokens/palettes/index.js.map +1 -0
  370. package/dist/tokens/palettes/tailwind.d.ts +324 -0
  371. package/dist/tokens/palettes/tailwind.js +201 -0
  372. package/dist/tokens/palettes/tailwind.js.map +1 -0
  373. package/dist/tokens/palettes/zendir.d.ts +126 -0
  374. package/dist/tokens/palettes/zendir.js +92 -0
  375. package/dist/tokens/palettes/zendir.js.map +1 -0
  376. package/dist/tokens/themes.d.ts +30 -0
  377. package/dist/tokens/themes.js +704 -0
  378. package/dist/tokens/themes.js.map +1 -0
  379. package/dist/tokens/tokens.css +419 -41
  380. package/dist/types/index.d.ts +2 -2
  381. package/package.json +310 -313
  382. package/dist/index.js.map +0 -1
  383. package/dist/react/3d/index.js.map +0 -1
  384. package/dist/react/astro/index.js.map +0 -1
  385. package/dist/react/cards/index.js.map +0 -1
  386. package/dist/react/charts/index.js.map +0 -1
  387. package/dist/react/core/index.js.map +0 -1
  388. package/dist/react/panels/index.js.map +0 -1
  389. package/dist/react/theme/astro-tokens.d.ts +0 -153
  390. package/dist/react/theme/index.js.map +0 -1
  391. package/dist/react.js.map +0 -1
@@ -1,226 +1,213 @@
1
- import { useRef, useState, useCallback, useEffect } from "react";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ //#region src/react/charts/unified/useChartStream.ts
3
+ /**
4
+ * @zendir/ui - Real-time Chart Streaming Hook
5
+ *
6
+ * Provides efficient real-time data streaming for charts.
7
+ * Handles buffering, throttling, and memory management.
8
+ */
2
9
  function useChartStream(chartRef, options = {}) {
3
- const {
4
- maxPoints: _maxPoints = 1e3,
5
- timeWindow: _timeWindow,
6
- throttleMs = 16,
7
- // ~60fps
8
- bufferSize = 10,
9
- decimate = true,
10
- decimateThreshold = 5e3
11
- } = options;
12
- const bufferRef = useRef(/* @__PURE__ */ new Map());
13
- const lastFlushRef = useRef(0);
14
- const pointCountRef = useRef(0);
15
- const [isPaused, setIsPaused] = useState(false);
16
- const animationFrameRef = useRef();
17
- const flush = useCallback(() => {
18
- const chart = chartRef.current;
19
- if (!chart || isPaused) return;
20
- const now = Date.now();
21
- if (now - lastFlushRef.current < throttleMs) {
22
- animationFrameRef.current = requestAnimationFrame(flush);
23
- return;
24
- }
25
- bufferRef.current.forEach((points, seriesIndex) => {
26
- if (points.length === 0) return;
27
- let processedPoints = points;
28
- if (decimate && pointCountRef.current > decimateThreshold) {
29
- processedPoints = decimateData(points, Math.ceil(points.length / 2));
30
- }
31
- processedPoints.forEach((point) => {
32
- chart.appendData(seriesIndex, point);
33
- });
34
- pointCountRef.current += processedPoints.length;
35
- });
36
- bufferRef.current.clear();
37
- lastFlushRef.current = now;
38
- }, [chartRef, isPaused, throttleMs, decimate, decimateThreshold]);
39
- const push = useCallback((seriesIndex, point) => {
40
- if (isPaused) return;
41
- let buffer = bufferRef.current.get(seriesIndex);
42
- if (!buffer) {
43
- buffer = [];
44
- bufferRef.current.set(seriesIndex, buffer);
45
- }
46
- buffer.push(point);
47
- if (buffer.length >= bufferSize) {
48
- flush();
49
- } else if (!animationFrameRef.current) {
50
- animationFrameRef.current = requestAnimationFrame(() => {
51
- animationFrameRef.current = void 0;
52
- flush();
53
- });
54
- }
55
- }, [isPaused, bufferSize, flush]);
56
- const pushBatch = useCallback((seriesIndex, points) => {
57
- if (isPaused || points.length === 0) return;
58
- let buffer = bufferRef.current.get(seriesIndex);
59
- if (!buffer) {
60
- buffer = [];
61
- bufferRef.current.set(seriesIndex, buffer);
62
- }
63
- buffer.push(...points);
64
- flush();
65
- }, [isPaused, flush]);
66
- const clear = useCallback(() => {
67
- var _a;
68
- bufferRef.current.clear();
69
- pointCountRef.current = 0;
70
- (_a = chartRef.current) == null ? void 0 : _a.clearData();
71
- }, [chartRef]);
72
- const pause = useCallback(() => setIsPaused(true), []);
73
- const resume = useCallback(() => setIsPaused(false), []);
74
- useEffect(() => {
75
- return () => {
76
- if (animationFrameRef.current) {
77
- cancelAnimationFrame(animationFrameRef.current);
78
- }
79
- };
80
- }, []);
81
- return {
82
- push,
83
- pushBatch,
84
- clear,
85
- pause,
86
- resume,
87
- isPaused,
88
- pointCount: pointCountRef.current
89
- };
10
+ const { maxPoints: _maxPoints = 1e3, timeWindow: _timeWindow, throttleMs = 16, bufferSize = 10, decimate = true, decimateThreshold = 5e3 } = options;
11
+ const bufferRef = useRef(/* @__PURE__ */ new Map());
12
+ const lastFlushRef = useRef(0);
13
+ const pointCountRef = useRef(0);
14
+ const [isPaused, setIsPaused] = useState(false);
15
+ const animationFrameRef = useRef();
16
+ const flush = useCallback(() => {
17
+ const chart = chartRef.current;
18
+ if (!chart || isPaused) return;
19
+ const now = Date.now();
20
+ if (now - lastFlushRef.current < throttleMs) {
21
+ animationFrameRef.current = requestAnimationFrame(flush);
22
+ return;
23
+ }
24
+ bufferRef.current.forEach((points, seriesIndex) => {
25
+ if (points.length === 0) return;
26
+ let processedPoints = points;
27
+ if (decimate && pointCountRef.current > decimateThreshold) processedPoints = decimateData(points, Math.ceil(points.length / 2));
28
+ processedPoints.forEach((point) => {
29
+ chart.appendData(seriesIndex, point);
30
+ });
31
+ pointCountRef.current += processedPoints.length;
32
+ });
33
+ bufferRef.current.clear();
34
+ lastFlushRef.current = now;
35
+ }, [
36
+ chartRef,
37
+ isPaused,
38
+ throttleMs,
39
+ decimate,
40
+ decimateThreshold
41
+ ]);
42
+ const push = useCallback((seriesIndex, point) => {
43
+ if (isPaused) return;
44
+ let buffer = bufferRef.current.get(seriesIndex);
45
+ if (!buffer) {
46
+ buffer = [];
47
+ bufferRef.current.set(seriesIndex, buffer);
48
+ }
49
+ buffer.push(point);
50
+ if (buffer.length >= bufferSize) flush();
51
+ else if (!animationFrameRef.current) animationFrameRef.current = requestAnimationFrame(() => {
52
+ animationFrameRef.current = void 0;
53
+ flush();
54
+ });
55
+ }, [
56
+ isPaused,
57
+ bufferSize,
58
+ flush
59
+ ]);
60
+ const pushBatch = useCallback((seriesIndex, points) => {
61
+ if (isPaused || points.length === 0) return;
62
+ let buffer = bufferRef.current.get(seriesIndex);
63
+ if (!buffer) {
64
+ buffer = [];
65
+ bufferRef.current.set(seriesIndex, buffer);
66
+ }
67
+ buffer.push(...points);
68
+ flush();
69
+ }, [isPaused, flush]);
70
+ const clear = useCallback(() => {
71
+ bufferRef.current.clear();
72
+ pointCountRef.current = 0;
73
+ chartRef.current?.clearData();
74
+ }, [chartRef]);
75
+ const pause = useCallback(() => setIsPaused(true), []);
76
+ const resume = useCallback(() => setIsPaused(false), []);
77
+ useEffect(() => {
78
+ return () => {
79
+ if (animationFrameRef.current) cancelAnimationFrame(animationFrameRef.current);
80
+ };
81
+ }, []);
82
+ return {
83
+ push,
84
+ pushBatch,
85
+ clear,
86
+ pause,
87
+ resume,
88
+ isPaused,
89
+ pointCount: pointCountRef.current
90
+ };
90
91
  }
92
+ /**
93
+ * Largest Triangle Three Buckets (LTTB) algorithm for data decimation
94
+ * Preserves visual shape while reducing point count
95
+ */
91
96
  function decimateData(data, threshold) {
92
- if (data.length <= threshold) return data;
93
- const result = [];
94
- const bucketSize = (data.length - 2) / (threshold - 2);
95
- result.push(data[0]);
96
- let a = 0;
97
- for (let i = 0; i < threshold - 2; i++) {
98
- const bucketStart = Math.floor((i + 1) * bucketSize) + 1;
99
- const bucketEnd = Math.floor((i + 2) * bucketSize) + 1;
100
- const bucketLength = Math.min(bucketEnd, data.length) - bucketStart;
101
- let avgX = 0;
102
- let avgY = 0;
103
- const nextBucketStart = Math.floor((i + 2) * bucketSize) + 1;
104
- const nextBucketEnd = Math.min(Math.floor((i + 3) * bucketSize) + 1, data.length);
105
- const nextBucketLength = nextBucketEnd - nextBucketStart;
106
- for (let j = nextBucketStart; j < nextBucketEnd; j++) {
107
- const point = data[j];
108
- const [x, y] = getPointXY(point);
109
- avgX += x;
110
- avgY += y;
111
- }
112
- avgX /= nextBucketLength || 1;
113
- avgY /= nextBucketLength || 1;
114
- const [aX, aY] = getPointXY(data[a]);
115
- let maxArea = -1;
116
- let maxIdx = bucketStart;
117
- for (let j = bucketStart; j < bucketStart + bucketLength; j++) {
118
- const point = data[j];
119
- const [x, y] = getPointXY(point);
120
- const area = Math.abs(
121
- (aX - avgX) * (y - aY) - (aX - x) * (avgY - aY)
122
- );
123
- if (area > maxArea) {
124
- maxArea = area;
125
- maxIdx = j;
126
- }
127
- }
128
- result.push(data[maxIdx]);
129
- a = maxIdx;
130
- }
131
- result.push(data[data.length - 1]);
132
- return result;
97
+ if (data.length <= threshold) return data;
98
+ const result = [];
99
+ const bucketSize = (data.length - 2) / (threshold - 2);
100
+ result.push(data[0]);
101
+ let a = 0;
102
+ for (let i = 0; i < threshold - 2; i++) {
103
+ const bucketStart = Math.floor((i + 1) * bucketSize) + 1;
104
+ const bucketEnd = Math.floor((i + 2) * bucketSize) + 1;
105
+ const bucketLength = Math.min(bucketEnd, data.length) - bucketStart;
106
+ let avgX = 0;
107
+ let avgY = 0;
108
+ const nextBucketStart = Math.floor((i + 2) * bucketSize) + 1;
109
+ const nextBucketEnd = Math.min(Math.floor((i + 3) * bucketSize) + 1, data.length);
110
+ const nextBucketLength = nextBucketEnd - nextBucketStart;
111
+ for (let j = nextBucketStart; j < nextBucketEnd; j++) {
112
+ const point = data[j];
113
+ const [x, y] = getPointXY(point);
114
+ avgX += x;
115
+ avgY += y;
116
+ }
117
+ avgX /= nextBucketLength || 1;
118
+ avgY /= nextBucketLength || 1;
119
+ const [aX, aY] = getPointXY(data[a]);
120
+ let maxArea = -1;
121
+ let maxIdx = bucketStart;
122
+ for (let j = bucketStart; j < bucketStart + bucketLength; j++) {
123
+ const point = data[j];
124
+ const [x, y] = getPointXY(point);
125
+ const area = Math.abs((aX - avgX) * (y - aY) - (aX - x) * (avgY - aY));
126
+ if (area > maxArea) {
127
+ maxArea = area;
128
+ maxIdx = j;
129
+ }
130
+ }
131
+ result.push(data[maxIdx]);
132
+ a = maxIdx;
133
+ }
134
+ result.push(data[data.length - 1]);
135
+ return result;
133
136
  }
134
137
  function getPointXY(point) {
135
- if ("time" in point) {
136
- return [
137
- typeof point.time === "number" ? point.time : new Date(point.time).getTime(),
138
- point.value
139
- ];
140
- }
141
- return [
142
- typeof point.x === "number" ? point.x : 0,
143
- point.y
144
- ];
138
+ if ("time" in point) return [typeof point.time === "number" ? point.time : new Date(point.time).getTime(), point.value];
139
+ return [typeof point.x === "number" ? point.x : 0, point.y];
145
140
  }
146
141
  function useWebSocketStream(chartRef, options) {
147
- const {
148
- url,
149
- reconnect = true,
150
- reconnectDelay = 1e3,
151
- maxReconnects = 10,
152
- parseMessage,
153
- ...streamOptions
154
- } = options;
155
- const wsRef = useRef(null);
156
- const reconnectCountRef = useRef(0);
157
- const reconnectTimerRef = useRef();
158
- const [connectionState, setConnectionState] = useState("disconnected");
159
- const stream = useChartStream(chartRef, streamOptions);
160
- const connect = useCallback(() => {
161
- var _a;
162
- if (((_a = wsRef.current) == null ? void 0 : _a.readyState) === WebSocket.OPEN) return;
163
- setConnectionState("connecting");
164
- const ws = new WebSocket(url);
165
- ws.onopen = () => {
166
- setConnectionState("connected");
167
- reconnectCountRef.current = 0;
168
- };
169
- ws.onmessage = (event) => {
170
- try {
171
- const data = JSON.parse(event.data);
172
- const parsed = parseMessage ? parseMessage(data) : defaultParseMessage(data);
173
- if (parsed) {
174
- stream.push(parsed.seriesIndex, parsed.point);
175
- }
176
- } catch (e) {
177
- }
178
- };
179
- ws.onerror = () => {
180
- setConnectionState("error");
181
- };
182
- ws.onclose = () => {
183
- setConnectionState("disconnected");
184
- if (reconnect && reconnectCountRef.current < maxReconnects) {
185
- reconnectCountRef.current++;
186
- reconnectTimerRef.current = setTimeout(connect, reconnectDelay * reconnectCountRef.current);
187
- }
188
- };
189
- wsRef.current = ws;
190
- }, [url, reconnect, reconnectDelay, maxReconnects, parseMessage, stream]);
191
- const disconnect = useCallback(() => {
192
- var _a;
193
- clearTimeout(reconnectTimerRef.current);
194
- (_a = wsRef.current) == null ? void 0 : _a.close();
195
- wsRef.current = null;
196
- }, []);
197
- useEffect(() => {
198
- connect();
199
- return disconnect;
200
- }, [connect, disconnect]);
201
- return {
202
- ...stream,
203
- connectionState,
204
- connect,
205
- disconnect
206
- };
142
+ const { url, reconnect = true, reconnectDelay = 1e3, maxReconnects = 10, parseMessage, ...streamOptions } = options;
143
+ const wsRef = useRef(null);
144
+ const reconnectCountRef = useRef(0);
145
+ const reconnectTimerRef = useRef();
146
+ const [connectionState, setConnectionState] = useState("disconnected");
147
+ const stream = useChartStream(chartRef, streamOptions);
148
+ const connect = useCallback(() => {
149
+ if (wsRef.current?.readyState === WebSocket.OPEN) return;
150
+ setConnectionState("connecting");
151
+ const ws = new WebSocket(url);
152
+ ws.onopen = () => {
153
+ setConnectionState("connected");
154
+ reconnectCountRef.current = 0;
155
+ };
156
+ ws.onmessage = (event) => {
157
+ try {
158
+ const data = JSON.parse(event.data);
159
+ const parsed = parseMessage ? parseMessage(data) : defaultParseMessage(data);
160
+ if (parsed) stream.push(parsed.seriesIndex, parsed.point);
161
+ } catch (e) {}
162
+ };
163
+ ws.onerror = () => {
164
+ setConnectionState("error");
165
+ };
166
+ ws.onclose = () => {
167
+ setConnectionState("disconnected");
168
+ if (reconnect && reconnectCountRef.current < maxReconnects) {
169
+ reconnectCountRef.current++;
170
+ reconnectTimerRef.current = setTimeout(connect, reconnectDelay * reconnectCountRef.current);
171
+ }
172
+ };
173
+ wsRef.current = ws;
174
+ }, [
175
+ url,
176
+ reconnect,
177
+ reconnectDelay,
178
+ maxReconnects,
179
+ parseMessage,
180
+ stream
181
+ ]);
182
+ const disconnect = useCallback(() => {
183
+ clearTimeout(reconnectTimerRef.current);
184
+ wsRef.current?.close();
185
+ wsRef.current = null;
186
+ }, []);
187
+ useEffect(() => {
188
+ connect();
189
+ return disconnect;
190
+ }, [connect, disconnect]);
191
+ return {
192
+ ...stream,
193
+ connectionState,
194
+ connect,
195
+ disconnect
196
+ };
207
197
  }
208
198
  function defaultParseMessage(data) {
209
- if (typeof data !== "object" || data === null) return null;
210
- const obj = data;
211
- if ("time" in obj && "value" in obj) {
212
- return {
213
- seriesIndex: typeof obj.seriesIndex === "number" ? obj.seriesIndex : 0,
214
- point: {
215
- time: obj.time,
216
- value: obj.value
217
- }
218
- };
219
- }
220
- return null;
199
+ if (typeof data !== "object" || data === null) return null;
200
+ const obj = data;
201
+ if ("time" in obj && "value" in obj) return {
202
+ seriesIndex: typeof obj.seriesIndex === "number" ? obj.seriesIndex : 0,
203
+ point: {
204
+ time: obj.time,
205
+ value: obj.value
206
+ }
207
+ };
208
+ return null;
221
209
  }
222
- export {
223
- useChartStream,
224
- useWebSocketStream
225
- };
226
- //# sourceMappingURL=useChartStream.js.map
210
+ //#endregion
211
+ export { useChartStream, useWebSocketStream };
212
+
213
+ //# sourceMappingURL=useChartStream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useChartStream.js","sources":["../../../../src/react/charts/unified/useChartStream.ts"],"sourcesContent":["/**\n * @zendir/ui - Real-time Chart Streaming Hook\n * \n * Provides efficient real-time data streaming for charts.\n * Handles buffering, throttling, and memory management.\n */\n\nimport { useRef, useCallback, useEffect, useState } from 'react';\nimport type { AstroChartHandle } from './AstroChart';\nimport type { TimeSeriesPoint, DataPoint } from './types';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StreamOptions {\n /** Maximum data points to keep */\n maxPoints?: number;\n /** Time window in milliseconds (alternative to maxPoints) */\n timeWindow?: number;\n /** Throttle interval in milliseconds */\n throttleMs?: number;\n /** Buffer size before flushing */\n bufferSize?: number;\n /** Enable data decimation for large datasets */\n decimate?: boolean;\n /** Decimation threshold (start decimating above this count) */\n decimateThreshold?: number;\n}\n\nexport interface StreamController {\n /** Push a single data point */\n push: (seriesIndex: number, point: TimeSeriesPoint | DataPoint) => void;\n /** Push multiple data points */\n pushBatch: (seriesIndex: number, points: (TimeSeriesPoint | DataPoint)[]) => void;\n /** Clear all data */\n clear: () => void;\n /** Pause streaming */\n pause: () => void;\n /** Resume streaming */\n resume: () => void;\n /** Get current state */\n isPaused: boolean;\n /** Get current point count */\n pointCount: number;\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\nexport function useChartStream(\n chartRef: React.RefObject<AstroChartHandle>,\n options: StreamOptions = {}\n): StreamController {\n const {\n maxPoints: _maxPoints = 1000,\n timeWindow: _timeWindow,\n throttleMs = 16, // ~60fps\n bufferSize = 10,\n decimate = true,\n decimateThreshold = 5000,\n } = options;\n\n const bufferRef = useRef<Map<number, (TimeSeriesPoint | DataPoint)[]>>(new Map());\n const lastFlushRef = useRef<number>(0);\n const pointCountRef = useRef<number>(0);\n const [isPaused, setIsPaused] = useState(false);\n const animationFrameRef = useRef<number>();\n\n // Flush buffer to chart\n const flush = useCallback(() => {\n const chart = chartRef.current;\n if (!chart || isPaused) return;\n\n const now = Date.now();\n if (now - lastFlushRef.current < throttleMs) {\n // Schedule next flush\n animationFrameRef.current = requestAnimationFrame(flush);\n return;\n }\n\n bufferRef.current.forEach((points, seriesIndex) => {\n if (points.length === 0) return;\n\n // Apply decimation if needed\n let processedPoints = points;\n if (decimate && pointCountRef.current > decimateThreshold) {\n processedPoints = decimateData(points, Math.ceil(points.length / 2));\n }\n\n // Append each point\n processedPoints.forEach(point => {\n chart.appendData(seriesIndex, point);\n });\n\n pointCountRef.current += processedPoints.length;\n });\n\n // Clear buffer\n bufferRef.current.clear();\n lastFlushRef.current = now;\n }, [chartRef, isPaused, throttleMs, decimate, decimateThreshold]);\n\n // Push single point\n const push = useCallback((seriesIndex: number, point: TimeSeriesPoint | DataPoint) => {\n if (isPaused) return;\n\n let buffer = bufferRef.current.get(seriesIndex);\n if (!buffer) {\n buffer = [];\n bufferRef.current.set(seriesIndex, buffer);\n }\n\n buffer.push(point);\n\n // Flush if buffer is full\n if (buffer.length >= bufferSize) {\n flush();\n } else if (!animationFrameRef.current) {\n // Schedule flush\n animationFrameRef.current = requestAnimationFrame(() => {\n animationFrameRef.current = undefined;\n flush();\n });\n }\n }, [isPaused, bufferSize, flush]);\n\n // Push batch\n const pushBatch = useCallback((seriesIndex: number, points: (TimeSeriesPoint | DataPoint)[]) => {\n if (isPaused || points.length === 0) return;\n\n let buffer = bufferRef.current.get(seriesIndex);\n if (!buffer) {\n buffer = [];\n bufferRef.current.set(seriesIndex, buffer);\n }\n\n buffer.push(...points);\n flush();\n }, [isPaused, flush]);\n\n // Clear all data\n const clear = useCallback(() => {\n bufferRef.current.clear();\n pointCountRef.current = 0;\n chartRef.current?.clearData();\n }, [chartRef]);\n\n // Pause/resume\n const pause = useCallback(() => setIsPaused(true), []);\n const resume = useCallback(() => setIsPaused(false), []);\n\n // Cleanup\n useEffect(() => {\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, []);\n\n return {\n push,\n pushBatch,\n clear,\n pause,\n resume,\n isPaused,\n pointCount: pointCountRef.current,\n };\n}\n\n// =============================================================================\n// Data Decimation\n// =============================================================================\n\n/**\n * Largest Triangle Three Buckets (LTTB) algorithm for data decimation\n * Preserves visual shape while reducing point count\n */\nfunction decimateData<T extends TimeSeriesPoint | DataPoint>(\n data: T[],\n threshold: number\n): T[] {\n if (data.length <= threshold) return data;\n\n const result: T[] = [];\n const bucketSize = (data.length - 2) / (threshold - 2);\n\n // Always include first point\n result.push(data[0]);\n\n let a = 0; // Previous selected point\n\n for (let i = 0; i < threshold - 2; i++) {\n // Calculate bucket range\n const bucketStart = Math.floor((i + 1) * bucketSize) + 1;\n const bucketEnd = Math.floor((i + 2) * bucketSize) + 1;\n const bucketLength = Math.min(bucketEnd, data.length) - bucketStart;\n\n // Calculate average point in next bucket\n let avgX = 0;\n let avgY = 0;\n const nextBucketStart = Math.floor((i + 2) * bucketSize) + 1;\n const nextBucketEnd = Math.min(Math.floor((i + 3) * bucketSize) + 1, data.length);\n const nextBucketLength = nextBucketEnd - nextBucketStart;\n\n for (let j = nextBucketStart; j < nextBucketEnd; j++) {\n const point = data[j];\n const [x, y] = getPointXY(point);\n avgX += x;\n avgY += y;\n }\n avgX /= nextBucketLength || 1;\n avgY /= nextBucketLength || 1;\n\n // Find point with largest triangle area\n const [aX, aY] = getPointXY(data[a]);\n let maxArea = -1;\n let maxIdx = bucketStart;\n\n for (let j = bucketStart; j < bucketStart + bucketLength; j++) {\n const point = data[j];\n const [x, y] = getPointXY(point);\n \n // Triangle area\n const area = Math.abs(\n (aX - avgX) * (y - aY) - (aX - x) * (avgY - aY)\n );\n\n if (area > maxArea) {\n maxArea = area;\n maxIdx = j;\n }\n }\n\n result.push(data[maxIdx]);\n a = maxIdx;\n }\n\n // Always include last point\n result.push(data[data.length - 1]);\n\n return result;\n}\n\nfunction getPointXY(point: TimeSeriesPoint | DataPoint): [number, number] {\n if ('time' in point) {\n return [\n typeof point.time === 'number' ? point.time : new Date(point.time).getTime(),\n point.value,\n ];\n }\n return [\n typeof point.x === 'number' ? point.x : 0,\n point.y,\n ];\n}\n\n// =============================================================================\n// WebSocket Stream Hook\n// =============================================================================\n\nexport interface WebSocketStreamOptions extends StreamOptions {\n /** WebSocket URL */\n url: string;\n /** Reconnect on disconnect */\n reconnect?: boolean;\n /** Reconnect delay in milliseconds */\n reconnectDelay?: number;\n /** Maximum reconnect attempts */\n maxReconnects?: number;\n /** Message parser */\n parseMessage?: (data: unknown) => { seriesIndex: number; point: TimeSeriesPoint | DataPoint } | null;\n}\n\nexport interface WebSocketStreamController extends StreamController {\n /** WebSocket connection state */\n connectionState: 'connecting' | 'connected' | 'disconnected' | 'error';\n /** Manually connect */\n connect: () => void;\n /** Manually disconnect */\n disconnect: () => void;\n}\n\nexport function useWebSocketStream(\n chartRef: React.RefObject<AstroChartHandle>,\n options: WebSocketStreamOptions\n): WebSocketStreamController {\n const {\n url,\n reconnect = true,\n reconnectDelay = 1000,\n maxReconnects = 10,\n parseMessage,\n ...streamOptions\n } = options;\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectCountRef = useRef(0);\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout>>();\n const [connectionState, setConnectionState] = useState<WebSocketStreamController['connectionState']>('disconnected');\n \n const stream = useChartStream(chartRef, streamOptions);\n\n const connect = useCallback(() => {\n if (wsRef.current?.readyState === WebSocket.OPEN) return;\n\n setConnectionState('connecting');\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n setConnectionState('connected');\n reconnectCountRef.current = 0;\n };\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n const parsed = parseMessage \n ? parseMessage(data) \n : defaultParseMessage(data);\n \n if (parsed) {\n stream.push(parsed.seriesIndex, parsed.point);\n }\n } catch (e) {\n if (import.meta.env.DEV) {\n console.error('Failed to parse WebSocket message:', e);\n }\n }\n };\n\n ws.onerror = () => {\n setConnectionState('error');\n };\n\n ws.onclose = () => {\n setConnectionState('disconnected');\n \n if (reconnect && reconnectCountRef.current < maxReconnects) {\n reconnectCountRef.current++;\n reconnectTimerRef.current = setTimeout(connect, reconnectDelay * reconnectCountRef.current);\n }\n };\n\n wsRef.current = ws;\n }, [url, reconnect, reconnectDelay, maxReconnects, parseMessage, stream]);\n\n const disconnect = useCallback(() => {\n clearTimeout(reconnectTimerRef.current);\n wsRef.current?.close();\n wsRef.current = null;\n }, []);\n\n // Auto-connect on mount\n useEffect(() => {\n connect();\n return disconnect;\n }, [connect, disconnect]);\n\n return {\n ...stream,\n connectionState,\n connect,\n disconnect,\n };\n}\n\nfunction defaultParseMessage(data: unknown): { seriesIndex: number; point: TimeSeriesPoint } | null {\n if (typeof data !== 'object' || data === null) return null;\n \n const obj = data as Record<string, unknown>;\n \n if ('time' in obj && 'value' in obj) {\n return {\n seriesIndex: typeof obj.seriesIndex === 'number' ? obj.seriesIndex : 0,\n point: {\n time: obj.time as number,\n value: obj.value as number,\n },\n };\n }\n \n return null;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useChartStream.js","names":[],"sources":["../../../../src/react/charts/unified/useChartStream.ts"],"sourcesContent":["/**\n * @zendir/ui - Real-time Chart Streaming Hook\n *\n * Provides efficient real-time data streaming for charts.\n * Handles buffering, throttling, and memory management.\n */\n\nimport { useRef, useCallback, useEffect, useState } from \"react\";\nimport type { AstroChartHandle } from \"./AstroChart\";\nimport type { TimeSeriesPoint, DataPoint } from \"./types\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StreamOptions {\n /** Maximum data points to keep */\n maxPoints?: number;\n /** Time window in milliseconds (alternative to maxPoints) */\n timeWindow?: number;\n /** Throttle interval in milliseconds */\n throttleMs?: number;\n /** Buffer size before flushing */\n bufferSize?: number;\n /** Enable data decimation for large datasets */\n decimate?: boolean;\n /** Decimation threshold (start decimating above this count) */\n decimateThreshold?: number;\n}\n\nexport interface StreamController {\n /** Push a single data point */\n push: (seriesIndex: number, point: TimeSeriesPoint | DataPoint) => void;\n /** Push multiple data points */\n pushBatch: (\n seriesIndex: number,\n points: (TimeSeriesPoint | DataPoint)[],\n ) => void;\n /** Clear all data */\n clear: () => void;\n /** Pause streaming */\n pause: () => void;\n /** Resume streaming */\n resume: () => void;\n /** Get current state */\n isPaused: boolean;\n /** Get current point count */\n pointCount: number;\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\nexport function useChartStream(\n chartRef: React.RefObject<AstroChartHandle>,\n options: StreamOptions = {},\n): StreamController {\n const {\n maxPoints: _maxPoints = 1000,\n timeWindow: _timeWindow,\n throttleMs = 16, // ~60fps\n bufferSize = 10,\n decimate = true,\n decimateThreshold = 5000,\n } = options;\n\n const bufferRef = useRef<Map<number, (TimeSeriesPoint | DataPoint)[]>>(\n new Map(),\n );\n const lastFlushRef = useRef<number>(0);\n const pointCountRef = useRef<number>(0);\n const [isPaused, setIsPaused] = useState(false);\n const animationFrameRef = useRef<number>();\n\n // Flush buffer to chart\n const flush = useCallback(() => {\n const chart = chartRef.current;\n if (!chart || isPaused) return;\n\n const now = Date.now();\n if (now - lastFlushRef.current < throttleMs) {\n // Schedule next flush\n animationFrameRef.current = requestAnimationFrame(flush);\n return;\n }\n\n bufferRef.current.forEach((points, seriesIndex) => {\n if (points.length === 0) return;\n\n // Apply decimation if needed\n let processedPoints = points;\n if (decimate && pointCountRef.current > decimateThreshold) {\n processedPoints = decimateData(points, Math.ceil(points.length / 2));\n }\n\n // Append each point\n processedPoints.forEach((point) => {\n chart.appendData(seriesIndex, point);\n });\n\n pointCountRef.current += processedPoints.length;\n });\n\n // Clear buffer\n bufferRef.current.clear();\n lastFlushRef.current = now;\n }, [chartRef, isPaused, throttleMs, decimate, decimateThreshold]);\n\n // Push single point\n const push = useCallback(\n (seriesIndex: number, point: TimeSeriesPoint | DataPoint) => {\n if (isPaused) return;\n\n let buffer = bufferRef.current.get(seriesIndex);\n if (!buffer) {\n buffer = [];\n bufferRef.current.set(seriesIndex, buffer);\n }\n\n buffer.push(point);\n\n // Flush if buffer is full\n if (buffer.length >= bufferSize) {\n flush();\n } else if (!animationFrameRef.current) {\n // Schedule flush\n animationFrameRef.current = requestAnimationFrame(() => {\n animationFrameRef.current = undefined;\n flush();\n });\n }\n },\n [isPaused, bufferSize, flush],\n );\n\n // Push batch\n const pushBatch = useCallback(\n (seriesIndex: number, points: (TimeSeriesPoint | DataPoint)[]) => {\n if (isPaused || points.length === 0) return;\n\n let buffer = bufferRef.current.get(seriesIndex);\n if (!buffer) {\n buffer = [];\n bufferRef.current.set(seriesIndex, buffer);\n }\n\n buffer.push(...points);\n flush();\n },\n [isPaused, flush],\n );\n\n // Clear all data\n const clear = useCallback(() => {\n bufferRef.current.clear();\n pointCountRef.current = 0;\n chartRef.current?.clearData();\n }, [chartRef]);\n\n // Pause/resume\n const pause = useCallback(() => setIsPaused(true), []);\n const resume = useCallback(() => setIsPaused(false), []);\n\n // Cleanup\n useEffect(() => {\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, []);\n\n return {\n push,\n pushBatch,\n clear,\n pause,\n resume,\n isPaused,\n pointCount: pointCountRef.current,\n };\n}\n\n// =============================================================================\n// Data Decimation\n// =============================================================================\n\n/**\n * Largest Triangle Three Buckets (LTTB) algorithm for data decimation\n * Preserves visual shape while reducing point count\n */\nfunction decimateData<T extends TimeSeriesPoint | DataPoint>(\n data: T[],\n threshold: number,\n): T[] {\n if (data.length <= threshold) return data;\n\n const result: T[] = [];\n const bucketSize = (data.length - 2) / (threshold - 2);\n\n // Always include first point\n result.push(data[0]);\n\n let a = 0; // Previous selected point\n\n for (let i = 0; i < threshold - 2; i++) {\n // Calculate bucket range\n const bucketStart = Math.floor((i + 1) * bucketSize) + 1;\n const bucketEnd = Math.floor((i + 2) * bucketSize) + 1;\n const bucketLength = Math.min(bucketEnd, data.length) - bucketStart;\n\n // Calculate average point in next bucket\n let avgX = 0;\n let avgY = 0;\n const nextBucketStart = Math.floor((i + 2) * bucketSize) + 1;\n const nextBucketEnd = Math.min(\n Math.floor((i + 3) * bucketSize) + 1,\n data.length,\n );\n const nextBucketLength = nextBucketEnd - nextBucketStart;\n\n for (let j = nextBucketStart; j < nextBucketEnd; j++) {\n const point = data[j];\n const [x, y] = getPointXY(point);\n avgX += x;\n avgY += y;\n }\n avgX /= nextBucketLength || 1;\n avgY /= nextBucketLength || 1;\n\n // Find point with largest triangle area\n const [aX, aY] = getPointXY(data[a]);\n let maxArea = -1;\n let maxIdx = bucketStart;\n\n for (let j = bucketStart; j < bucketStart + bucketLength; j++) {\n const point = data[j];\n const [x, y] = getPointXY(point);\n\n // Triangle area\n const area = Math.abs((aX - avgX) * (y - aY) - (aX - x) * (avgY - aY));\n\n if (area > maxArea) {\n maxArea = area;\n maxIdx = j;\n }\n }\n\n result.push(data[maxIdx]);\n a = maxIdx;\n }\n\n // Always include last point\n result.push(data[data.length - 1]);\n\n return result;\n}\n\nfunction getPointXY(point: TimeSeriesPoint | DataPoint): [number, number] {\n if (\"time\" in point) {\n return [\n typeof point.time === \"number\"\n ? point.time\n : new Date(point.time).getTime(),\n point.value,\n ];\n }\n return [typeof point.x === \"number\" ? point.x : 0, point.y];\n}\n\n// =============================================================================\n// WebSocket Stream Hook\n// =============================================================================\n\nexport interface WebSocketStreamOptions extends StreamOptions {\n /** WebSocket URL */\n url: string;\n /** Reconnect on disconnect */\n reconnect?: boolean;\n /** Reconnect delay in milliseconds */\n reconnectDelay?: number;\n /** Maximum reconnect attempts */\n maxReconnects?: number;\n /** Message parser */\n parseMessage?: (\n data: unknown,\n ) => { seriesIndex: number; point: TimeSeriesPoint | DataPoint } | null;\n}\n\nexport interface WebSocketStreamController extends StreamController {\n /** WebSocket connection state */\n connectionState: \"connecting\" | \"connected\" | \"disconnected\" | \"error\";\n /** Manually connect */\n connect: () => void;\n /** Manually disconnect */\n disconnect: () => void;\n}\n\nexport function useWebSocketStream(\n chartRef: React.RefObject<AstroChartHandle>,\n options: WebSocketStreamOptions,\n): WebSocketStreamController {\n const {\n url,\n reconnect = true,\n reconnectDelay = 1000,\n maxReconnects = 10,\n parseMessage,\n ...streamOptions\n } = options;\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectCountRef = useRef(0);\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout>>();\n const [connectionState, setConnectionState] =\n useState<WebSocketStreamController[\"connectionState\"]>(\"disconnected\");\n\n const stream = useChartStream(chartRef, streamOptions);\n\n const connect = useCallback(() => {\n if (wsRef.current?.readyState === WebSocket.OPEN) return;\n\n setConnectionState(\"connecting\");\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n setConnectionState(\"connected\");\n reconnectCountRef.current = 0;\n };\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n const parsed = parseMessage\n ? parseMessage(data)\n : defaultParseMessage(data);\n\n if (parsed) {\n stream.push(parsed.seriesIndex, parsed.point);\n }\n } catch (e) {\n if (import.meta.env.DEV) {\n console.error(\"Failed to parse WebSocket message:\", e);\n }\n }\n };\n\n ws.onerror = () => {\n setConnectionState(\"error\");\n };\n\n ws.onclose = () => {\n setConnectionState(\"disconnected\");\n\n if (reconnect && reconnectCountRef.current < maxReconnects) {\n reconnectCountRef.current++;\n reconnectTimerRef.current = setTimeout(\n connect,\n reconnectDelay * reconnectCountRef.current,\n );\n }\n };\n\n wsRef.current = ws;\n }, [url, reconnect, reconnectDelay, maxReconnects, parseMessage, stream]);\n\n const disconnect = useCallback(() => {\n clearTimeout(reconnectTimerRef.current);\n wsRef.current?.close();\n wsRef.current = null;\n }, []);\n\n // Auto-connect on mount\n useEffect(() => {\n connect();\n return disconnect;\n }, [connect, disconnect]);\n\n return {\n ...stream,\n connectionState,\n connect,\n disconnect,\n };\n}\n\nfunction defaultParseMessage(\n data: unknown,\n): { seriesIndex: number; point: TimeSeriesPoint } | null {\n if (typeof data !== \"object\" || data === null) return null;\n\n const obj = data as Record<string, unknown>;\n\n if (\"time\" in obj && \"value\" in obj) {\n return {\n seriesIndex: typeof obj.seriesIndex === \"number\" ? obj.seriesIndex : 0,\n point: {\n time: obj.time as number,\n value: obj.value as number,\n },\n };\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { default as React, ReactNode } from 'react';
2
2
  import { StatusLevel } from '../utils';
3
-
4
3
  export interface AppCardProps {
5
4
  /** Card content */
6
5
  children: ReactNode;
@@ -19,7 +18,7 @@ export interface AppCardProps {
19
18
  label: string;
20
19
  level?: StatusLevel;
21
20
  /** @deprecated Use `level` (Astro UX StatusLevel) instead. Still supported for backward compatibility. */
22
- variant?: 'success' | 'warning' | 'error' | 'info' | 'neutral';
21
+ variant?: "success" | "warning" | "error" | "info" | "neutral";
23
22
  };
24
23
  /** Show fullscreen button (only rendered inside ChatGPT host) */
25
24
  allowFullscreen?: boolean;
@@ -24,15 +24,15 @@ export interface OpenAiGlobals {
24
24
  /** Snapshot of UI state persisted between renders */
25
25
  widgetState?: Record<string, unknown>;
26
26
  /** Current theme */
27
- theme?: 'light' | 'dark';
27
+ theme?: "light" | "dark";
28
28
  /** Current locale (e.g., 'en-US') */
29
29
  locale?: string;
30
30
  /** Display mode */
31
- displayMode?: 'inline' | 'pip' | 'fullscreen';
31
+ displayMode?: "inline" | "pip" | "fullscreen";
32
32
  /** Maximum allowed height */
33
33
  maxHeight?: number;
34
34
  /** View type */
35
- view?: 'conversation' | 'modal';
35
+ view?: "conversation" | "modal";
36
36
  /** User agent info */
37
37
  userAgent?: string;
38
38
  /** Safe area insets */
@@ -56,7 +56,7 @@ export interface OpenAiGlobals {
56
56
  downloadUrl: string;
57
57
  }>;
58
58
  requestDisplayMode?: (options: {
59
- mode: 'inline' | 'pip' | 'fullscreen';
59
+ mode: "inline" | "pip" | "fullscreen";
60
60
  }) => Promise<void>;
61
61
  requestModal?: (options: unknown) => Promise<void>;
62
62
  notifyIntrinsicHeight?: (height: number) => void;
@@ -87,7 +87,7 @@ export declare function useToolOutput<T = Record<string, unknown>>(): T | undefi
87
87
  * Read the tool input (arguments) from the tool invocation
88
88
  */
89
89
  export declare function useToolInput<T = Record<string, unknown>>(): T | undefined;
90
- export type ThemeMode = 'light' | 'dark';
90
+ export type ThemeMode = "light" | "dark";
91
91
  /**
92
92
  * Get current ChatGPT theme and provide CSS-friendly values
93
93
  * Named useChatGPTTheme to avoid conflict with the core useTheme from ThemeProvider
@@ -113,9 +113,9 @@ export declare function useLocale(): string;
113
113
  * Manage widget display mode (inline, PiP, fullscreen)
114
114
  */
115
115
  export declare function useDisplayMode(): {
116
- mode: 'inline' | 'pip' | 'fullscreen';
116
+ mode: "inline" | "pip" | "fullscreen";
117
117
  maxHeight?: number;
118
- requestMode: (mode: 'inline' | 'pip' | 'fullscreen') => Promise<void>;
118
+ requestMode: (mode: "inline" | "pip" | "fullscreen") => Promise<void>;
119
119
  close: () => void;
120
120
  };
121
121
  /**