@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 +1 @@
1
- {"version":3,"file":"SideNav.js","sources":["../../../../src/react/core/navigation/SideNav.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - SideNav Component\r\n * \r\n * Persistent sidebar navigation for operator dashboards. Compound component\r\n * pattern with Header, Item, Section, Divider, and Footer subcomponents.\r\n * \r\n * Responsive: Full sidebar on desktop, hamburger overlay on mobile.\r\n * \r\n * Astro UX Compliance:\r\n * - Persistent side navigation pattern (AstroUXDS Navigation)\r\n * - Status indicator integration\r\n * - Active state highlighting with accent color\r\n * - Keyboard navigation support\r\n * - Reduced motion support\r\n * \r\n * @example\r\n * ```tsx\r\n * <SideNav>\r\n * <SideNav.Header logo={<Icon name=\"satellite\" size={24} />} title=\"Space Range\" badge=\"Operator\" />\r\n * <SideNav.Section title=\"Operations\">\r\n * <SideNav.Item icon=\"controls\" label=\"Controls\" description=\"System command interface\" href=\"/controls\" active />\r\n * <SideNav.Item icon=\"telemetry\" label=\"Telemetry\" href=\"/telemetry\" badge={3} tag=\"LIVE\" tagVariant=\"success\" />\r\n * <SideNav.Item icon=\"images\" label=\"Images\" href=\"/images\" />\r\n * </SideNav.Section>\r\n * <SideNav.Divider />\r\n * <SideNav.Section title=\"Analysis\">\r\n * <SideNav.Item icon=\"chart\" label=\"Plots\" href=\"/plots\" />\r\n * <SideNav.Item icon=\"map\" label=\"Map\" href=\"/map\" />\r\n * </SideNav.Section>\r\n * <SideNav.Footer>\r\n * <SideNav.Item icon=\"settings\" label=\"Settings\" href=\"/settings\" />\r\n * </SideNav.Footer>\r\n * </SideNav>\r\n * ```\r\n */\r\n\r\nimport React, { memo, useState, createContext, useContext, useCallback, useEffect, useLayoutEffect } from 'react';\r\n\r\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\r\nimport { useTheme } from '../../theme';\r\nimport { safeAccentText } from '../../utils';\r\nimport { Icon } from '../display/Icon';\r\nimport type { IconName } from '../display/Icon';\r\n\r\n// ─── Astro UX Status Shape ───────────────────────────────────────────────────\r\n\r\nconst SIDENAV_STATUS_COLORS: Record<string, string> = {\r\n off: '#a4abb6',\r\n standby: '#2dccff',\r\n normal: '#56f000',\r\n caution: '#fce83a',\r\n serious: '#ffb302',\r\n critical: '#ff3838',\r\n};\r\n\r\n/** Astro UX dual-coded status shape (color + geometry). */\r\nfunction NavStatusShape({ status, size = 8 }: { status: string; size?: number }) {\r\n const color = SIDENAV_STATUS_COLORS[status] ?? SIDENAV_STATUS_COLORS.off;\r\n const glow = `${color}50`;\r\n const style = { flexShrink: 0 as const, filter: `drop-shadow(0 0 3px ${glow})` };\r\n\r\n switch (status) {\r\n case 'caution':\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" fill={color} /></svg>;\r\n case 'serious':\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><polygon points=\"6,1 11,6 6,11 1,6\" fill={color} /></svg>;\r\n case 'critical':\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><polygon points=\"6,11 1,2 11,2\" fill={color} /></svg>;\r\n case 'standby':\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><circle cx=\"6\" cy=\"6\" r=\"3.5\" fill=\"none\" stroke={color} strokeWidth=\"2\" /></svg>;\r\n case 'off':\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><circle cx=\"6\" cy=\"6\" r=\"3\" fill={color} /></svg>;\r\n default: // normal\r\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={style} aria-hidden=\"true\"><circle cx=\"6\" cy=\"6\" r=\"5\" fill={color} /></svg>;\r\n }\r\n}\r\n\r\n// ─── Responsive Breakpoints ──────────────────────────────────────────────────\r\n\r\nconst SIDENAV_BREAKPOINTS = {\r\n mobile: 768,\r\n tablet: 1024,\r\n} as const;\r\n\r\ntype SideNavMode = 'desktop' | 'tablet' | 'mobile';\r\n\r\nfunction getSideNavMode(width: number): SideNavMode {\r\n if (width < SIDENAV_BREAKPOINTS.mobile) return 'mobile';\r\n if (width < SIDENAV_BREAKPOINTS.tablet) return 'tablet';\r\n return 'desktop';\r\n}\r\n\r\n// ─── Context ─────────────────────────────────────────────────────────────────\r\n\r\ninterface SideNavContextValue {\r\n collapsed: boolean;\r\n mobileOpen: boolean;\r\n mode: SideNavMode;\r\n showCollapseToggle: boolean;\r\n setMobileOpen: (open: boolean) => void;\r\n toggleCollapse: () => void;\r\n}\r\n\r\nconst SideNavContext = createContext<SideNavContextValue>({\r\n collapsed: false,\r\n mobileOpen: false,\r\n mode: 'desktop',\r\n showCollapseToggle: true,\r\n setMobileOpen: () => {},\r\n toggleCollapse: () => {},\r\n});\r\n\r\n// ─── SideNav ─────────────────────────────────────────────────────────────────\r\n\r\nexport interface SideNavProps {\r\n /** Collapsed mode (icon-only). When omitted, auto-collapses on tablet viewports. */\r\n collapsed?: boolean;\r\n /** Callback when collapsed state changes (via toggle button or responsive breakpoint). */\r\n onCollapsedChange?: (collapsed: boolean) => void;\r\n /** Show a collapse/expand toggle button in the sidebar (default true). */\r\n showCollapseToggle?: boolean;\r\n /** Width in pixels (default 260) */\r\n width?: number;\r\n /** Collapsed width in pixels (default 64) */\r\n collapsedWidth?: number;\r\n /**\r\n * Mobile viewport behavior.\r\n * - `'drawer'` (default): hamburger button with slide-out overlay drawer.\r\n * - `'collapsed'`: persistent collapsed icon-only strip (same as tablet).\r\n */\r\n mobileVariant?: 'drawer' | 'collapsed';\r\n /** Children (SideNav.Header, SideNav.Item, SideNav.Section, SideNav.Footer) */\r\n children?: React.ReactNode;\r\n /** Custom style */\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst SideNavRoot = memo(function SideNav({\r\n collapsed,\r\n onCollapsedChange,\r\n showCollapseToggle = true,\r\n width = 260,\r\n collapsedWidth = 64,\r\n mobileVariant = 'drawer',\r\n children,\r\n style,\r\n}: SideNavProps): React.ReactElement {\r\n const { tokens, theme } = useTheme();\r\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\r\n const [mobileOpen, setMobileOpen] = useState(false);\r\n const [userCollapsed, setUserCollapsed] = useState<boolean | null>(null);\r\n \r\n // Initialize to 'desktop' to guarantee the first client render matches SSR\r\n // (where window is undefined), preventing a React hydration mismatch if the\r\n // client happens to be on a mobile/tablet width at initial load.\r\n const [viewMode, setViewMode] = useState<SideNavMode>('desktop');\r\n \r\n useIsomorphicLayoutEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n\r\n // Synchronously correct the viewMode right after hydration but before paint\r\n setViewMode(getSideNavMode(window.innerWidth));\r\n\r\n let rafId: number;\r\n const handleResize = () => {\r\n cancelAnimationFrame(rafId);\r\n rafId = requestAnimationFrame(() => setViewMode(getSideNavMode(window.innerWidth)));\r\n };\r\n window.addEventListener('resize', handleResize, { passive: true });\r\n return () => {\r\n window.removeEventListener('resize', handleResize);\r\n cancelAnimationFrame(rafId);\r\n };\r\n }, []);\r\n\r\n // When mobileVariant='collapsed', promote mobile to tablet (collapsed inline strip)\r\n const effectiveMode = mobileVariant === 'collapsed' && viewMode === 'mobile' ? 'tablet' : viewMode;\r\n\r\n // Reset user toggle when crossing breakpoints\r\n useEffect(() => {\r\n setUserCollapsed(null);\r\n }, [effectiveMode]);\r\n\r\n // Close mobile drawer when switching away from mobile\r\n useEffect(() => {\r\n if (effectiveMode !== 'mobile' && mobileOpen) setMobileOpen(false);\r\n }, [effectiveMode, mobileOpen]);\r\n \r\n // Close mobile nav on escape\r\n useEffect(() => {\r\n if (!mobileOpen) return;\r\n const handleEsc = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setMobileOpen(false);\r\n };\r\n document.addEventListener('keydown', handleEsc);\r\n return () => document.removeEventListener('keydown', handleEsc);\r\n }, [mobileOpen]);\r\n\r\n // Resolve collapsed: explicit prop > user toggle > auto (tablet = collapsed)\r\n const autoCollapsed = effectiveMode === 'tablet';\r\n const isCollapsed = collapsed !== undefined\r\n ? collapsed\r\n : userCollapsed !== null\r\n ? userCollapsed\r\n : autoCollapsed;\r\n const isMobile = effectiveMode === 'mobile';\r\n const navWidth = isCollapsed ? collapsedWidth : width;\r\n\r\n const handleToggleCollapse = useCallback(() => {\r\n const next = !isCollapsed;\r\n setUserCollapsed(next);\r\n onCollapsedChange?.(next);\r\n }, [isCollapsed, onCollapsedChange]);\r\n \r\n const navStyle: React.CSSProperties = {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n width: isMobile ? 280 : navWidth,\r\n height: '100%',\r\n backgroundColor: isTransparentTheme\r\n ? 'rgba(15, 12, 30, 0.7)'\r\n : tokens.colors.background.surface,\r\n borderRight: `1px solid ${tokens.colors.border.muted}`,\r\n transition: 'width 0.25s ease, transform 0.25s ease',\r\n overflowX: 'hidden',\r\n overflowY: 'auto',\r\n flexShrink: 0,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n ...(isTransparentTheme ? {\r\n backdropFilter: 'blur(16px)',\r\n WebkitBackdropFilter: 'blur(16px)',\r\n } : {}),\r\n ...style,\r\n };\r\n \r\n const contextValue: SideNavContextValue = { collapsed: isCollapsed, mobileOpen, mode: effectiveMode, showCollapseToggle, setMobileOpen, toggleCollapse: handleToggleCollapse };\r\n \r\n // Mobile: hamburger button + overlay drawer\r\n if (isMobile) {\r\n return (\r\n <SideNavContext.Provider value={contextValue}>\r\n {/* Hamburger button */}\r\n <button\r\n aria-label=\"Open navigation\"\r\n onClick={() => setMobileOpen(true)}\r\n style={{\r\n position: 'fixed',\r\n top: 6,\r\n left: 6,\r\n zIndex: 1001,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: 32,\r\n height: 32,\r\n border: 'none',\r\n borderRadius: tokens.borderRadius.sm,\r\n backgroundColor: 'transparent',\r\n color: tokens.colors.text.primary,\r\n cursor: 'pointer',\r\n padding: 0,\r\n transition: tokens.animation.fast,\r\n }}\r\n >\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\r\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\r\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\r\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\r\n </svg>\r\n </button>\r\n \r\n {/* Overlay */}\r\n <div\r\n aria-hidden=\"true\"\r\n style={{\r\n position: 'fixed',\r\n inset: 0,\r\n zIndex: 1002,\r\n backgroundColor: `${tokens.colors.background.base}99`,\r\n backdropFilter: 'blur(4px)',\r\n opacity: mobileOpen ? 1 : 0,\r\n pointerEvents: mobileOpen ? 'auto' : 'none',\r\n transition: 'opacity 0.25s ease',\r\n }}\r\n onClick={() => setMobileOpen(false)}\r\n />\r\n \r\n {/* Slide-out nav */}\r\n <nav\r\n role=\"navigation\"\r\n aria-label=\"Main navigation\"\r\n style={{\r\n ...navStyle,\r\n position: 'fixed',\r\n top: 0,\r\n left: 0,\r\n zIndex: 1003,\r\n transform: mobileOpen ? 'translateX(0)' : 'translateX(-100%)',\r\n boxShadow: mobileOpen ? tokens.shadows.xl : 'none',\r\n }}\r\n >\r\n {children}\r\n </nav>\r\n </SideNavContext.Provider>\r\n );\r\n }\r\n \r\n return (\r\n <SideNavContext.Provider value={contextValue}>\r\n <nav role=\"navigation\" aria-label=\"Main navigation\" style={navStyle}>\r\n {children}\r\n </nav>\r\n </SideNavContext.Provider>\r\n );\r\n});\r\n\r\n// ─── Header ──────────────────────────────────────────────────────────────────\r\n\r\n/** Default height for the logo row so dashboard / operator / other apps align the same mark. */\r\nexport const SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX = 44;\r\n\r\nexport interface SideNavHeaderProps {\r\n /** Logo element (Icon, image, or ReactNode) */\r\n logo?: React.ReactNode;\r\n /** Compact logo shown when sidebar is collapsed or on tablet (e.g., just the icon mark) */\r\n collapsedLogo?: React.ReactNode;\r\n /** App title */\r\n title?: string;\r\n /** Subtitle or version */\r\n subtitle?: string;\r\n /** Role badge (e.g., \"Operator\", \"Admin\") */\r\n badge?: string;\r\n /** Badge variant for color */\r\n badgeVariant?: 'info' | 'success' | 'warning' | 'caution';\r\n /**\r\n * Fixed height (px) for the top logo band. Title, subtitle, and badge render below this band\r\n * so different logo assets still line up across apps (dashboard vs operator).\r\n */\r\n logoSlotHeight?: number;\r\n /** Children override (advanced: replaces default header content entirely) */\r\n children?: React.ReactNode;\r\n}\r\n\r\n/** Chevron toggle button for collapsing/expanding the sidebar. */\r\nfunction CollapseToggleButton() {\r\n const { tokens } = useTheme();\r\n const { collapsed, toggleCollapse } = useContext(SideNavContext);\r\n const [hovered, setHovered] = useState(false);\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\r\n onClick={toggleCollapse}\r\n onMouseEnter={() => setHovered(true)}\r\n onMouseLeave={() => setHovered(false)}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: 28,\r\n height: 28,\r\n border: `1px solid ${hovered ? tokens.colors.border.focus : tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n backgroundColor: hovered ? `${tokens.colors.accent.primary}15` : 'transparent',\r\n color: hovered ? tokens.colors.accent.primary : tokens.colors.text.tertiary,\r\n cursor: 'pointer',\r\n flexShrink: 0,\r\n padding: 0,\r\n transition: tokens.animation.fast,\r\n outline: 'none',\r\n }}\r\n >\r\n <svg\r\n width=\"14\"\r\n height=\"14\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n style={{\r\n transition: 'transform 0.25s ease',\r\n transform: collapsed ? 'rotate(180deg)' : 'rotate(0deg)',\r\n }}\r\n >\r\n <polyline points=\"15 18 9 12 15 6\" />\r\n </svg>\r\n </button>\r\n );\r\n}\r\n\r\nconst SideNavHeader = memo(function SideNavHeader({\r\n logo,\r\n collapsedLogo,\r\n title,\r\n subtitle,\r\n badge,\r\n badgeVariant = 'info',\r\n logoSlotHeight = SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX,\r\n children,\r\n}: SideNavHeaderProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { collapsed, mode, showCollapseToggle, toggleCollapse } = useContext(SideNavContext);\r\n const displayLogo = collapsed && collapsedLogo ? collapsedLogo : logo;\r\n const showToggle = showCollapseToggle && mode !== 'mobile';\r\n const hasMeta = Boolean(title || subtitle || badge);\r\n const slotH = logoSlotHeight;\r\n\r\n const badgeColors: Record<string, string> = {\r\n info: tokens.colors.accent.primary,\r\n success: tokens.colors.status.normal,\r\n warning: tokens.colors.status.caution,\r\n caution: tokens.colors.status.serious,\r\n };\r\n\r\n const metaBlock = !collapsed && hasMeta ? (\r\n <div style={{ flex: 1, minWidth: 0, width: '100%' }}>\r\n {title ? (\r\n <div style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: tokens.colors.text.primary,\r\n lineHeight: tokens.typography.lineHeight.tight,\r\n whiteSpace: 'nowrap',\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n }}>\r\n {title}\r\n </div>\r\n ) : null}\r\n {(subtitle || badge) ? (\r\n <div style={{ display: 'flex', alignItems: 'center', gap: tokens.spacing.xs, marginTop: title ? '2px' : 0, flexWrap: 'wrap' }}>\r\n {subtitle ? (\r\n <span style={{\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n }}>\r\n {subtitle}\r\n </span>\r\n ) : null}\r\n {badge ? (\r\n <span style={{\r\n fontSize: '0.6rem',\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: badgeColors[badgeVariant] || safeAccentText(tokens.colors.accent.primary),\r\n backgroundColor: `${badgeColors[badgeVariant] || tokens.colors.accent.primary}18`,\r\n border: `1px solid ${badgeColors[badgeVariant] || tokens.colors.accent.primary}30`,\r\n padding: '1px 6px',\r\n borderRadius: tokens.borderRadius.sm,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.05em',\r\n }}>\r\n {badge}\r\n </span>\r\n ) : null}\r\n </div>\r\n ) : null}\r\n </div>\r\n ) : null;\r\n\r\n const logoSlot = displayLogo ? (\r\n <div\r\n style={{\r\n height: slotH,\r\n minHeight: slotH,\r\n maxHeight: slotH,\r\n width: '100%',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: collapsed ? 'center' : 'flex-start',\r\n overflow: 'hidden',\r\n boxSizing: 'border-box',\r\n marginBottom: !collapsed && hasMeta && displayLogo ? tokens.spacing.sm : 0,\r\n }}\r\n >\r\n <div\r\n style={{\r\n maxHeight: '100%',\r\n maxWidth: '100%',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: collapsed ? 'center' : 'flex-start',\r\n minWidth: 0,\r\n cursor: collapsed && showToggle ? 'pointer' : undefined,\r\n }}\r\n onClick={collapsed && showToggle ? toggleCollapse : undefined}\r\n >\r\n {displayLogo}\r\n </div>\r\n </div>\r\n ) : null;\r\n\r\n if (children) {\r\n return (\r\n <div style={{\r\n padding: `${tokens.spacing.md} 16px ${tokens.spacing.md} 15px`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n flexShrink: 0,\r\n boxSizing: 'border-box',\r\n position: 'relative',\r\n }}>\r\n {children}\r\n </div>\r\n );\r\n }\r\n\r\n // Collapsed: centered logo in the same fixed slot height as expanded (visual parity with operator).\r\n if (collapsed) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n padding: `${tokens.spacing.md} ${tokens.spacing.sm}`,\r\n minHeight: slotH + 24,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n flexShrink: 0,\r\n boxSizing: 'border-box',\r\n position: 'relative',\r\n justifyContent: 'center',\r\n }}>\r\n {logoSlot}\r\n {showToggle ? (\r\n <div style={{ position: 'absolute', right: 4, top: '50%', transform: 'translateY(-50%)' }}>\r\n <CollapseToggleButton />\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'stretch',\r\n padding: `${tokens.spacing.md} 16px ${tokens.spacing.md} 15px`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n flexShrink: 0,\r\n boxSizing: 'border-box',\r\n position: 'relative',\r\n }}>\r\n {showToggle ? (\r\n <div style={{ position: 'absolute', top: tokens.spacing.sm, right: tokens.spacing.sm, zIndex: 1 }}>\r\n <CollapseToggleButton />\r\n </div>\r\n ) : null}\r\n <div style={{ paddingRight: showToggle ? 36 : 0, width: '100%', minWidth: 0 }}>\r\n {logoSlot}\r\n {metaBlock}\r\n </div>\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Item ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface SideNavItemProps {\r\n /** Icon name from zendir-ui icon library */\r\n icon?: IconName | React.ReactNode;\r\n /** Label text */\r\n label: string;\r\n /** Description text displayed beneath the label (hidden in collapsed mode) */\r\n description?: string;\r\n /** Small tag/chip displayed after the label (e.g. \"v2\", \"NEW\", \"BETA\") */\r\n tag?: string;\r\n /** Tag color variant */\r\n tagVariant?: 'default' | 'info' | 'success' | 'warning' | 'danger';\r\n /** Link href (renders <a>) */\r\n href?: string;\r\n /** Click handler (renders <button>) */\r\n onClick?: () => void;\r\n /** Active state */\r\n active?: boolean;\r\n /** Disabled state */\r\n disabled?: boolean;\r\n /** Notification badge count */\r\n badge?: number;\r\n /** External link indicator */\r\n external?: boolean;\r\n /**\r\n * Astro UX status level — renders a dual-coded indicator (color + shape).\r\n * Shapes per official Astro UXDS: normal = ● filled circle, standby = ◎ ring,\r\n * caution = ■ square, serious = ◆ diamond, critical = ▼ triangle, off = · small circle.\r\n */\r\n status?: 'off' | 'standby' | 'normal' | 'caution' | 'serious' | 'critical';\r\n /** Optional status label shown as tooltip or text next to status shape */\r\n statusLabel?: string;\r\n /** Right-side slot — arbitrary ReactNode rendered at the end of the item row */\r\n suffix?: React.ReactNode;\r\n}\r\n\r\nconst TAG_COLORS: Record<string, { bg: string; fg: string; border: string }> = {\r\n default: { bg: '#ffffff10', fg: '#9590a8', border: '#ffffff15' },\r\n info: { bg: '#8a2be218', fg: '#c4a0ff', border: '#8a2be230' },\r\n success: { bg: '#56f00018', fg: '#56f000', border: '#56f00030' },\r\n warning: { bg: '#fce83a18', fg: '#fce83a', border: '#fce83a30' },\r\n danger: { bg: '#ff383818', fg: '#ff3838', border: '#ff383830' },\r\n};\r\n\r\nconst SideNavItem = memo(function SideNavItem({\r\n icon,\r\n label,\r\n description,\r\n tag,\r\n tagVariant = 'default',\r\n href,\r\n onClick,\r\n active = false,\r\n disabled = false,\r\n badge,\r\n external = false,\r\n status,\r\n statusLabel,\r\n suffix,\r\n}: SideNavItemProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { collapsed, setMobileOpen } = useContext(SideNavContext);\r\n const [isHovered, setIsHovered] = useState(false);\r\n \r\n const handleClick = useCallback((e: React.MouseEvent) => {\r\n if (disabled) return;\r\n if (onClick && href && !e.metaKey && !e.ctrlKey && !e.shiftKey) {\r\n e.preventDefault();\r\n }\r\n setMobileOpen(false);\r\n onClick?.();\r\n }, [disabled, onClick, href, setMobileOpen]);\r\n \r\n // Status-aware accent: when an item has a status, tint active/hover with its color\r\n const statusColor = status ? (SIDENAV_STATUS_COLORS[status] ?? undefined) : undefined;\r\n const accentColor = statusColor && active ? statusColor : safeAccentText(tokens.colors.accent.primary);\r\n \r\n const hasDescription = !!description && !collapsed;\r\n \r\n const iconElement = typeof icon === 'string'\r\n ? <Icon name={icon as IconName} size={hasDescription ? 22 : 20} color={active ? accentColor : tokens.colors.text.secondary} />\r\n : icon;\r\n \r\n const itemStyle: React.CSSProperties = {\r\n display: 'flex',\r\n alignItems: hasDescription ? 'flex-start' : 'center',\r\n gap: tokens.spacing.sm,\r\n padding: collapsed\r\n ? `${tokens.spacing.sm} 0`\r\n : hasDescription\r\n ? `10px 16px 10px 12px`\r\n : `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 12px`,\r\n justifyContent: collapsed ? 'center' : 'flex-start',\r\n color: active\r\n ? accentColor\r\n : disabled\r\n ? tokens.colors.text.tertiary\r\n : tokens.colors.text.secondary,\r\n backgroundColor: active\r\n ? `${accentColor}12`\r\n : isHovered && !disabled\r\n ? `${accentColor}08`\r\n : 'transparent',\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontWeight: active ? tokens.typography.fontWeight.semibold : tokens.typography.fontWeight.normal,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n textDecoration: 'none',\r\n borderTop: 'none',\r\n borderRight: 'none',\r\n borderBottom: 'none',\r\n borderLeft: active\r\n ? `3px solid ${accentColor}`\r\n : '3px solid transparent',\r\n outline: 'none',\r\n width: '100%',\r\n boxSizing: 'border-box',\r\n transition: tokens.animation.fast,\r\n position: 'relative',\r\n opacity: disabled ? 0.5 : 1,\r\n };\r\n \r\n const tagColors = TAG_COLORS[tagVariant] ?? TAG_COLORS.default;\r\n \r\n const content = (\r\n <>\r\n {/* Icon + collapsed status overlay */}\r\n {iconElement && (\r\n <span style={{ flexShrink: 0, display: 'flex', position: 'relative', marginTop: hasDescription ? '2px' : 0 }}>\r\n {iconElement}\r\n {/* In collapsed mode, show a small status shape overlaid on the icon (top-left) */}\r\n {collapsed && status && (\r\n <span\r\n style={{\r\n position: 'absolute',\r\n top: -3,\r\n left: -4,\r\n lineHeight: 0,\r\n }}\r\n title={statusLabel ?? status}\r\n >\r\n <NavStatusShape status={status} size={7} />\r\n </span>\r\n )}\r\n </span>\r\n )}\r\n {!collapsed && (\r\n <>\r\n {/* Label + description block */}\r\n <span style={{ flex: 1, minWidth: 0, overflow: 'hidden' }}>\r\n <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\r\n <span style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\r\n {label}\r\n </span>\r\n {tag && (\r\n <span style={{\r\n fontSize: '0.6rem',\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: tagColors.fg,\r\n backgroundColor: tagColors.bg,\r\n border: `1px solid ${tagColors.border}`,\r\n padding: '1px 5px',\r\n borderRadius: tokens.borderRadius.sm,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.04em',\r\n flexShrink: 0,\r\n lineHeight: '1.3',\r\n whiteSpace: 'nowrap',\r\n }}>\r\n {tag}\r\n </span>\r\n )}\r\n </span>\r\n {description && (\r\n <span style={{\r\n display: 'block',\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n lineHeight: tokens.typography.lineHeight.normal,\r\n marginTop: '2px',\r\n whiteSpace: 'nowrap',\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n fontWeight: tokens.typography.fontWeight.normal,\r\n }}>\r\n {description}\r\n </span>\r\n )}\r\n </span>\r\n {/* Right-side trailing elements — badge, status, suffix, external icon */}\r\n {(badge !== undefined && badge > 0 || status || suffix || external) && (\r\n <span style={{\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n gap: 8,\r\n flexShrink: 0,\r\n marginTop: hasDescription ? '2px' : 0,\r\n }}>\r\n {/* Badge */}\r\n {badge !== undefined && badge > 0 && (\r\n <span style={{\r\n fontSize: '0.65rem',\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: '#fff',\r\n backgroundColor: tokens.colors.status.critical,\r\n borderRadius: tokens.borderRadius.full,\r\n minWidth: '18px',\r\n height: '18px',\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: '0 5px',\r\n flexShrink: 0,\r\n lineHeight: 1,\r\n boxSizing: 'border-box',\r\n }}>\r\n {badge > 99 ? '99+' : badge}\r\n </span>\r\n )}\r\n {/* Status */}\r\n {status && (\r\n <span\r\n style={{ display: 'inline-flex', alignItems: 'center', flexShrink: 0 }}\r\n role=\"status\"\r\n aria-label={`Status: ${statusLabel ?? status}`}\r\n title={statusLabel ?? status}\r\n >\r\n <NavStatusShape status={status} size={8} />\r\n </span>\r\n )}\r\n {/* Suffix */}\r\n {suffix && (\r\n <span style={{ flexShrink: 0, display: 'inline-flex', alignItems: 'center' }}>\r\n {suffix}\r\n </span>\r\n )}\r\n {/* External */}\r\n {external && (\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" style={{ flexShrink: 0, opacity: 0.5 }}>\r\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\r\n <polyline points=\"15 3 21 3 21 9\" />\r\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\r\n </svg>\r\n )}\r\n </span>\r\n )}\r\n </>\r\n )}\r\n </>\r\n );\r\n \r\n const props = {\r\n style: itemStyle,\r\n onMouseEnter: () => setIsHovered(true),\r\n onMouseLeave: () => setIsHovered(false),\r\n title: collapsed ? label : undefined,\r\n 'aria-current': active ? ('page' as const) : undefined,\r\n 'aria-disabled': disabled,\r\n };\r\n \r\n if (href && !disabled) {\r\n return (\r\n <a href={href} onClick={handleClick} target={external ? '_blank' : undefined} rel={external ? 'noopener noreferrer' : undefined} {...props}>\r\n {content}\r\n </a>\r\n );\r\n }\r\n \r\n return (\r\n <button type=\"button\" onClick={handleClick} disabled={disabled} {...props}>\r\n {content}\r\n </button>\r\n );\r\n});\r\n\r\n// ─── Section ─────────────────────────────────────────────────────────────────\r\n\r\nexport interface SideNavSectionProps {\r\n /** Section title */\r\n title?: string;\r\n /** Children (SideNav.Item elements) */\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst SideNavSection = memo(function SideNavSection({\r\n title,\r\n children,\r\n}: SideNavSectionProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { collapsed } = useContext(SideNavContext);\r\n \r\n return (\r\n <div style={{ marginTop: tokens.spacing.sm }}>\r\n {title && !collapsed && (\r\n <div style={{\r\n padding: `${tokens.spacing.xs} 16px ${tokens.spacing.xs} 15px`,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n fontWeight: tokens.typography.fontWeight.bold,\r\n color: tokens.colors.text.tertiary,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.08em',\r\n }}>\r\n {title}\r\n </div>\r\n )}\r\n {collapsed && title && (\r\n <div style={{\r\n width: '60%',\r\n height: '1px',\r\n backgroundColor: tokens.colors.border.muted,\r\n margin: `${tokens.spacing.xs} auto`,\r\n }} />\r\n )}\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Divider ─────────────────────────────────────────────────────────────────\r\n\r\nexport interface SideNavDividerProps {\r\n /** Optional label shown in the center of the divider line */\r\n label?: string;\r\n}\r\n\r\nconst SideNavDivider = memo(function SideNavDivider({\r\n label,\r\n}: SideNavDividerProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const { collapsed } = useContext(SideNavContext);\r\n\r\n if (collapsed) {\r\n return (\r\n <div style={{\r\n width: '60%',\r\n height: '1px',\r\n backgroundColor: tokens.colors.border.muted,\r\n margin: `${tokens.spacing.sm} auto`,\r\n }} />\r\n );\r\n }\r\n\r\n if (label) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: tokens.spacing.sm,\r\n padding: `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 15px`,\r\n }}>\r\n <div style={{ flex: 1, height: '1px', backgroundColor: tokens.colors.border.muted }} />\r\n <span style={{\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.06em',\r\n whiteSpace: 'nowrap',\r\n }}>\r\n {label}\r\n </span>\r\n <div style={{ flex: 1, height: '1px', backgroundColor: tokens.colors.border.muted }} />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{\r\n height: '1px',\r\n backgroundColor: tokens.colors.border.muted,\r\n margin: `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 15px`,\r\n }} />\r\n );\r\n});\r\n\r\n// ─── Footer ──────────────────────────────────────────────────────────────────\r\n\r\nexport interface SideNavFooterProps {\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst SideNavFooter = memo(function SideNavFooter({\r\n children,\r\n}: SideNavFooterProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n \r\n return (\r\n <div style={{\r\n marginTop: 'auto',\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n paddingTop: tokens.spacing.xs,\r\n paddingBottom: tokens.spacing.xs,\r\n }}>\r\n {children}\r\n </div>\r\n );\r\n});\r\n\r\n// ─── Compound Export ─────────────────────────────────────────────────────────\r\n\r\ntype SideNavComponent = typeof SideNavRoot & {\r\n Header: typeof SideNavHeader;\r\n Item: typeof SideNavItem;\r\n Section: typeof SideNavSection;\r\n Divider: typeof SideNavDivider;\r\n Footer: typeof SideNavFooter;\r\n};\r\n\r\nexport const SideNav: SideNavComponent = Object.assign(SideNavRoot, {\r\n Header: SideNavHeader,\r\n Item: SideNavItem,\r\n Section: SideNavSection,\r\n Divider: SideNavDivider,\r\n Footer: SideNavFooter,\r\n});\r\n\r\nexport default SideNav;\r\n"],"names":["SideNav","SideNavHeader","SideNavItem","SideNavSection","SideNavDivider","SideNavFooter"],"mappings":"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"}
1
+ {"version":3,"file":"SideNav.js","names":[],"sources":["../../../../src/react/core/navigation/SideNav.tsx"],"sourcesContent":["/**\n * @zendir/ui - SideNav Component\n *\n * Persistent sidebar navigation for operator dashboards. Compound component\n * pattern with Header, Item, Section, Divider, and Footer subcomponents.\n *\n * Responsive: Full sidebar on desktop, hamburger overlay on mobile.\n *\n * Astro UX Compliance:\n * - Persistent side navigation pattern (AstroUXDS Navigation)\n * - Status indicator integration\n * - Active state highlighting with accent color\n * - Keyboard navigation support\n * - Reduced motion support\n *\n * @example\n * ```tsx\n * <SideNav>\n * <SideNav.Header logo={<Icon name=\"satellite\" size={24} />} title=\"Space Range\" badge=\"Operator\" />\n * <SideNav.Section title=\"Operations\">\n * <SideNav.Item icon=\"controls\" label=\"Controls\" description=\"System command interface\" href=\"/controls\" active />\n * <SideNav.Item icon=\"telemetry\" label=\"Telemetry\" href=\"/telemetry\" badge={3} tag=\"LIVE\" tagVariant=\"success\" />\n * <SideNav.Item icon=\"images\" label=\"Images\" href=\"/images\" />\n * </SideNav.Section>\n * <SideNav.Divider />\n * <SideNav.Section title=\"Analysis\">\n * <SideNav.Item icon=\"chart\" label=\"Plots\" href=\"/plots\" />\n * <SideNav.Item icon=\"map\" label=\"Map\" href=\"/map\" />\n * </SideNav.Section>\n * <SideNav.Footer>\n * <SideNav.Item icon=\"settings\" label=\"Settings\" href=\"/settings\" />\n * </SideNav.Footer>\n * </SideNav>\n * ```\n */\n\nimport React, {\n memo,\n useState,\n createContext,\n useContext,\n useCallback,\n useEffect,\n useLayoutEffect,\n} from \"react\";\n\nconst useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\nimport { useTheme } from \"../../theme\";\nimport { safeAccentText } from \"../../utils\";\nimport { Icon } from \"../display/Icon\";\nimport type { IconName } from \"../display/Icon\";\n\n// ─── Reveal animation ────────────────────────────────────────────────────────\n\n/**\n * Content that only renders when expanded (item labels, section titles, the\n * header meta block) fades and slides in rather than popping, so widening the\n * rail reads as material flowing in. Injected once as a stylesheet because\n * keyframes can't be expressed inline; honours `prefers-reduced-motion`.\n */\nconst SIDENAV_REVEAL_STYLE_ID = \"zendir-sidenav-reveal\";\nfunction ensureSideNavReveal(): void {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(SIDENAV_REVEAL_STYLE_ID)) return;\n const el = document.createElement(\"style\");\n el.id = SIDENAV_REVEAL_STYLE_ID;\n el.textContent =\n \"@keyframes zsn-reveal{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:translateX(0)}}\" +\n \".zsn-reveal{animation:zsn-reveal 220ms cubic-bezier(0.22,1,0.36,1)}\" +\n // Item label is always mounted and toggled via data-collapsed, so it fades\n // and slides BOTH on expand and collapse (the icon stays put as the anchor).\n \".zsn-label{transition:opacity 220ms cubic-bezier(0.22,1,0.36,1),transform 220ms cubic-bezier(0.22,1,0.36,1)}\" +\n '.zsn-label[data-collapsed=\"true\"]{opacity:0;transform:translateX(-6px);pointer-events:none}' +\n \"@media (prefers-reduced-motion: reduce){.zsn-reveal,.zsn-label{animation:none;transition:none}}\";\n document.head.appendChild(el);\n}\n\n// ─── Astro UX Status Shape ───────────────────────────────────────────────────\n\n/** Astro UX dual-coded status shape (color + geometry). */\nfunction NavStatusShape({\n status,\n size = 8,\n}: {\n status: string;\n size?: number;\n}) {\n const { tokens } = useTheme();\n const color =\n tokens.colors.status[status as keyof typeof tokens.colors.status] ??\n tokens.colors.status.off;\n const glow = `${color}50`;\n const style = {\n flexShrink: 0 as const,\n filter: `drop-shadow(0 0 3px ${glow})`,\n };\n\n switch (status) {\n case \"caution\":\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" fill={color} />\n </svg>\n );\n case \"serious\":\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <polygon points=\"6,1 11,6 6,11 1,6\" fill={color} />\n </svg>\n );\n case \"critical\":\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <polygon points=\"6,11 1,2 11,2\" fill={color} />\n </svg>\n );\n case \"standby\":\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"6\"\n cy=\"6\"\n r=\"3.5\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n />\n </svg>\n );\n case \"off\":\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <circle cx=\"6\" cy=\"6\" r=\"3\" fill={color} />\n </svg>\n );\n default: // normal\n return (\n <svg\n viewBox=\"0 0 12 12\"\n width={size}\n height={size}\n style={style}\n aria-hidden=\"true\"\n >\n <circle cx=\"6\" cy=\"6\" r=\"5\" fill={color} />\n </svg>\n );\n }\n}\n\n// ─── Responsive Breakpoints ──────────────────────────────────────────────────\n\nconst SIDENAV_BREAKPOINTS = {\n mobile: 768,\n tablet: 1024,\n} as const;\n\ntype SideNavMode = \"desktop\" | \"tablet\" | \"mobile\";\n\nfunction getSideNavMode(width: number): SideNavMode {\n if (width < SIDENAV_BREAKPOINTS.mobile) return \"mobile\";\n if (width < SIDENAV_BREAKPOINTS.tablet) return \"tablet\";\n return \"desktop\";\n}\n\n// ─── Context ─────────────────────────────────────────────────────────────────\n\ninterface SideNavContextValue {\n collapsed: boolean;\n mobileOpen: boolean;\n mode: SideNavMode;\n density: \"default\" | \"compact\";\n showCollapseToggle: boolean;\n setMobileOpen: (open: boolean) => void;\n toggleCollapse: () => void;\n}\n\nconst SideNavContext = createContext<SideNavContextValue>({\n collapsed: false,\n mobileOpen: false,\n mode: \"desktop\",\n density: \"default\",\n showCollapseToggle: true,\n setMobileOpen: () => {},\n toggleCollapse: () => {},\n});\n\n// ─── SideNav ─────────────────────────────────────────────────────────────────\n\nexport interface SideNavProps {\n /** Collapsed mode (icon-only). When omitted, auto-collapses on tablet viewports. */\n collapsed?: boolean;\n /** Callback when collapsed state changes (via toggle button or responsive breakpoint). */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** Show a collapse/expand toggle button in the sidebar (default true). */\n showCollapseToggle?: boolean;\n /** Width in pixels (default 260) */\n width?: number;\n /** Collapsed width in pixels (default 64) */\n collapsedWidth?: number;\n /**\n * Row density. `'compact'` tightens row padding, drops the left accent bar\n * in favour of a pill-style (rounded, bg-tinted) active row, and shrinks the\n * label — matching the v2.3 operator/admin secondary-nav mock. Default\n * `'default'`. (TODO: row inset + mono section headings for full mock parity.)\n */\n density?: \"default\" | \"compact\";\n /**\n * Mobile viewport behavior.\n * - `'drawer'` (default): hamburger button with slide-out overlay drawer.\n * - `'collapsed'`: persistent collapsed icon-only strip (same as tablet).\n */\n mobileVariant?: \"drawer\" | \"collapsed\";\n /** Children (SideNav.Header, SideNav.Item, SideNav.Section, SideNav.Footer) */\n children?: React.ReactNode;\n /** Custom style */\n style?: React.CSSProperties;\n}\n\nconst SideNavRoot = memo(function SideNav({\n collapsed,\n onCollapsedChange,\n showCollapseToggle = true,\n width = 260,\n collapsedWidth = 64,\n density = \"default\",\n mobileVariant = \"drawer\",\n children,\n style,\n}: SideNavProps): React.ReactElement {\n const { tokens, theme } = useTheme();\n const isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const [mobileOpen, setMobileOpen] = useState(false);\n const [userCollapsed, setUserCollapsed] = useState<boolean | null>(null);\n\n // Initialize to 'desktop' to guarantee the first client render matches SSR\n // (where window is undefined), preventing a React hydration mismatch if the\n // client happens to be on a mobile/tablet width at initial load.\n const [viewMode, setViewMode] = useState<SideNavMode>(\"desktop\");\n\n useIsomorphicLayoutEffect(() => {\n if (typeof window === \"undefined\") return;\n\n // Synchronously correct the viewMode right after hydration but before paint\n setViewMode(getSideNavMode(window.innerWidth));\n\n let rafId: number;\n const handleResize = () => {\n cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() =>\n setViewMode(getSideNavMode(window.innerWidth)),\n );\n };\n window.addEventListener(\"resize\", handleResize, { passive: true });\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n cancelAnimationFrame(rafId);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n ensureSideNavReveal();\n }, []);\n\n // When mobileVariant='collapsed', promote mobile to tablet (collapsed inline strip)\n const effectiveMode =\n mobileVariant === \"collapsed\" && viewMode === \"mobile\"\n ? \"tablet\"\n : viewMode;\n\n // Reset user toggle when crossing breakpoints\n useEffect(() => {\n setUserCollapsed(null);\n }, [effectiveMode]);\n\n // Close mobile drawer when switching away from mobile\n useEffect(() => {\n if (effectiveMode !== \"mobile\" && mobileOpen) setMobileOpen(false);\n }, [effectiveMode, mobileOpen]);\n\n // Close mobile nav on escape\n useEffect(() => {\n if (!mobileOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setMobileOpen(false);\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [mobileOpen]);\n\n // Resolve collapsed: explicit prop > user toggle > auto (tablet = collapsed)\n const autoCollapsed = effectiveMode === \"tablet\";\n const isCollapsed =\n collapsed !== undefined\n ? collapsed\n : userCollapsed !== null\n ? userCollapsed\n : autoCollapsed;\n const isMobile = effectiveMode === \"mobile\";\n const navWidth = isCollapsed ? collapsedWidth : width;\n\n const handleToggleCollapse = useCallback(() => {\n const next = !isCollapsed;\n setUserCollapsed(next);\n onCollapsedChange?.(next);\n }, [isCollapsed, onCollapsedChange]);\n\n const navStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n width: isMobile ? 280 : navWidth,\n height: \"100%\",\n backgroundColor: isTransparentTheme\n ? \"rgba(15, 12, 30, 0.7)\"\n : tokens.colors.background.surface,\n borderRight: `1px solid ${tokens.colors.border.muted}`,\n transition:\n \"width 0.3s cubic-bezier(0.22, 1, 0.36, 1), transform 0.25s ease\",\n overflowX: \"hidden\",\n overflowY: \"auto\",\n flexShrink: 0,\n fontFamily: tokens.typography.fontFamily.primary,\n ...(isTransparentTheme\n ? {\n backdropFilter: \"blur(16px)\",\n WebkitBackdropFilter: \"blur(16px)\",\n }\n : {}),\n ...style,\n };\n\n const contextValue: SideNavContextValue = {\n collapsed: isCollapsed,\n mobileOpen,\n mode: effectiveMode,\n density,\n showCollapseToggle,\n setMobileOpen,\n toggleCollapse: handleToggleCollapse,\n };\n\n // Mobile: hamburger button + overlay drawer\n if (isMobile) {\n return (\n <SideNavContext.Provider value={contextValue}>\n {/* Hamburger button */}\n <button\n aria-label=\"Open navigation\"\n onClick={() => setMobileOpen(true)}\n style={{\n position: \"fixed\",\n top: 6,\n left: 6,\n zIndex: 1001,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 32,\n height: 32,\n border: \"none\",\n borderRadius: tokens.borderRadius.sm,\n backgroundColor: \"transparent\",\n color: tokens.colors.text.primary,\n cursor: \"pointer\",\n padding: 0,\n transition: tokens.animation.fast,\n }}\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </button>\n\n {/* Overlay */}\n <div\n aria-hidden=\"true\"\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 1002,\n backgroundColor: `${tokens.colors.background.base}99`,\n backdropFilter: \"blur(4px)\",\n opacity: mobileOpen ? 1 : 0,\n pointerEvents: mobileOpen ? \"auto\" : \"none\",\n transition: \"opacity 0.25s ease\",\n }}\n onClick={() => setMobileOpen(false)}\n />\n\n {/* Slide-out nav */}\n <nav\n role=\"navigation\"\n aria-label=\"Main navigation\"\n style={{\n ...navStyle,\n position: \"fixed\",\n top: 0,\n left: 0,\n zIndex: 1003,\n transform: mobileOpen ? \"translateX(0)\" : \"translateX(-100%)\",\n boxShadow: mobileOpen ? tokens.shadows.xl : \"none\",\n }}\n >\n {children}\n </nav>\n </SideNavContext.Provider>\n );\n }\n\n return (\n <SideNavContext.Provider value={contextValue}>\n <nav role=\"navigation\" aria-label=\"Main navigation\" style={navStyle}>\n {children}\n </nav>\n </SideNavContext.Provider>\n );\n});\n\n// ─── Header ──────────────────────────────────────────────────────────────────\n\n/** Default height for the logo row so dashboard / operator / other apps align the same mark. */\nexport const SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX = 44;\n\nexport interface SideNavHeaderProps {\n /** Logo element (Icon, image, or ReactNode) */\n logo?: React.ReactNode;\n /** Compact logo shown when sidebar is collapsed or on tablet (e.g., just the icon mark) */\n collapsedLogo?: React.ReactNode;\n /** App title */\n title?: string;\n /** Subtitle or version */\n subtitle?: string;\n /** Role badge (e.g., \"Operator\", \"Admin\") */\n badge?: string;\n /** Badge variant for color */\n badgeVariant?: \"info\" | \"success\" | \"warning\" | \"caution\";\n /**\n * Fixed height (px) for the top logo band. Title, subtitle, and badge render below this band\n * so different logo assets still line up across apps (dashboard vs operator).\n */\n logoSlotHeight?: number;\n /** Children override (advanced: replaces default header content entirely) */\n children?: React.ReactNode;\n}\n\n/** Chevron toggle button for collapsing/expanding the sidebar. */\nfunction CollapseToggleButton() {\n const { tokens } = useTheme();\n const { collapsed, toggleCollapse } = useContext(SideNavContext);\n const [hovered, setHovered] = useState(false);\n\n return (\n <button\n type=\"button\"\n aria-label={collapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n onClick={toggleCollapse}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 28,\n height: 28,\n border: `1px solid ${hovered ? tokens.colors.border.focus : tokens.colors.border.muted}`,\n borderRadius: tokens.borderRadius.md,\n backgroundColor: hovered\n ? `${tokens.colors.accent.primary}15`\n : \"transparent\",\n color: hovered\n ? tokens.colors.accent.primary\n : tokens.colors.text.tertiary,\n cursor: \"pointer\",\n flexShrink: 0,\n padding: 0,\n transition: tokens.animation.fast,\n outline: \"none\",\n }}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n transition: \"transform 0.25s ease\",\n transform: collapsed ? \"rotate(180deg)\" : \"rotate(0deg)\",\n }}\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n );\n}\n\nconst SideNavHeader = memo(function SideNavHeader({\n logo,\n collapsedLogo,\n title,\n subtitle,\n badge,\n badgeVariant = \"info\",\n logoSlotHeight = SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX,\n children,\n}: SideNavHeaderProps): React.ReactElement {\n const { tokens } = useTheme();\n const { collapsed, mode, showCollapseToggle, toggleCollapse } =\n useContext(SideNavContext);\n const displayLogo = collapsed && collapsedLogo ? collapsedLogo : logo;\n const showToggle = showCollapseToggle && mode !== \"mobile\";\n const hasMeta = Boolean(title || subtitle || badge);\n const slotH = logoSlotHeight;\n\n const badgeColors: Record<string, string> = {\n info: tokens.colors.accent.primary,\n success: tokens.colors.status.normal,\n warning: tokens.colors.status.caution,\n caution: tokens.colors.status.serious,\n };\n\n const metaBlock =\n !collapsed && hasMeta ? (\n <div\n className=\"zsn-reveal\"\n style={{ flex: 1, minWidth: 0, width: \"100%\" }}\n >\n {title ? (\n <div\n style={{\n fontSize: tokens.typography.fontSize.sm,\n fontWeight: tokens.typography.fontWeight.bold,\n color: tokens.colors.text.primary,\n lineHeight: tokens.typography.lineHeight.tight,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {title}\n </div>\n ) : null}\n {subtitle || badge ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.xs,\n marginTop: title ? \"2px\" : 0,\n flexWrap: \"wrap\",\n }}\n >\n {subtitle ? (\n <span\n style={{\n fontSize: tokens.typography.fontSize.xxs,\n color: tokens.colors.text.tertiary,\n }}\n >\n {subtitle}\n </span>\n ) : null}\n {badge ? (\n <span\n style={{\n fontSize: \"0.6rem\",\n fontWeight: tokens.typography.fontWeight.bold,\n color:\n badgeColors[badgeVariant] ||\n safeAccentText(tokens.colors.accent.primary),\n backgroundColor: `${badgeColors[badgeVariant] || tokens.colors.accent.primary}18`,\n border: `1px solid ${badgeColors[badgeVariant] || tokens.colors.accent.primary}30`,\n padding: \"1px 6px\",\n borderRadius: tokens.borderRadius.sm,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n }}\n >\n {badge}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null;\n\n const logoSlot = displayLogo ? (\n <div\n style={{\n height: slotH,\n minHeight: slotH,\n maxHeight: slotH,\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: collapsed ? \"center\" : \"flex-start\",\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n marginBottom:\n !collapsed && hasMeta && displayLogo ? tokens.spacing.sm : 0,\n }}\n >\n <div\n style={{\n maxHeight: \"100%\",\n maxWidth: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: collapsed ? \"center\" : \"flex-start\",\n minWidth: 0,\n cursor: collapsed && showToggle ? \"pointer\" : undefined,\n }}\n onClick={collapsed && showToggle ? toggleCollapse : undefined}\n >\n {displayLogo}\n </div>\n </div>\n ) : null;\n\n if (children) {\n return (\n <div\n style={{\n padding: `${tokens.spacing.md} 16px ${tokens.spacing.md} 15px`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n flexShrink: 0,\n boxSizing: \"border-box\",\n position: \"relative\",\n }}\n >\n {children}\n </div>\n );\n }\n\n // Collapsed: centered logo in the same fixed slot height as expanded (visual parity with operator).\n if (collapsed) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n padding: `${tokens.spacing.md} ${tokens.spacing.sm}`,\n minHeight: slotH + 24,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n flexShrink: 0,\n boxSizing: \"border-box\",\n position: \"relative\",\n justifyContent: \"center\",\n }}\n >\n {logoSlot}\n {showToggle ? (\n <div\n style={{\n position: \"absolute\",\n right: 4,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n }}\n >\n <CollapseToggleButton />\n </div>\n ) : null}\n </div>\n );\n }\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"stretch\",\n padding: `${tokens.spacing.md} 16px ${tokens.spacing.md} 15px`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n flexShrink: 0,\n boxSizing: \"border-box\",\n position: \"relative\",\n }}\n >\n {showToggle ? (\n <div\n style={{\n position: \"absolute\",\n top: tokens.spacing.sm,\n right: tokens.spacing.sm,\n zIndex: 1,\n }}\n >\n <CollapseToggleButton />\n </div>\n ) : null}\n <div\n style={{\n paddingRight: showToggle ? 36 : 0,\n width: \"100%\",\n minWidth: 0,\n }}\n >\n {logoSlot}\n {metaBlock}\n </div>\n </div>\n );\n});\n\n// ─── Item ────────────────────────────────────────────────────────────────────\n\nexport interface SideNavItemProps {\n /** Icon name from zendir-ui icon library */\n icon?: IconName | React.ReactNode;\n /** Label text */\n label: string;\n /** Description text displayed beneath the label (hidden in collapsed mode) */\n description?: string;\n /** Small tag/chip displayed after the label (e.g. \"v2\", \"NEW\", \"BETA\") */\n tag?: string;\n /** Tag color variant */\n tagVariant?: \"default\" | \"info\" | \"success\" | \"warning\" | \"danger\";\n /** Link href (renders <a>) */\n href?: string;\n /** Click handler (renders <button>) */\n onClick?: () => void;\n /** Active state */\n active?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Notification badge count */\n badge?: number;\n /** External link indicator */\n external?: boolean;\n /**\n * Astro UX status level — renders a dual-coded indicator (color + shape).\n * Shapes per official Astro UXDS: normal = ● filled circle, standby = ◎ ring,\n * caution = ■ square, serious = ◆ diamond, critical = ▼ triangle, off = · small circle.\n */\n status?: \"off\" | \"standby\" | \"normal\" | \"caution\" | \"serious\" | \"critical\";\n /** Optional status label shown as tooltip or text next to status shape */\n statusLabel?: string;\n /** Right-side slot — arbitrary ReactNode rendered at the end of the item row */\n suffix?: React.ReactNode;\n}\n\nconst TAG_COLORS: Record<string, { bg: string; fg: string; border: string }> = {\n default: { bg: \"#ffffff10\", fg: \"#9590a8\", border: \"#ffffff15\" },\n info: { bg: \"#8a2be218\", fg: \"#c4a0ff\", border: \"#8a2be230\" },\n success: { bg: \"#56f00018\", fg: \"#56f000\", border: \"#56f00030\" },\n warning: { bg: \"#fce83a18\", fg: \"#fce83a\", border: \"#fce83a30\" },\n danger: { bg: \"#ff383818\", fg: \"#ff3838\", border: \"#ff383830\" },\n};\n\nconst SideNavItem = memo(function SideNavItem({\n icon,\n label,\n description,\n tag,\n tagVariant = \"default\",\n href,\n onClick,\n active = false,\n disabled = false,\n badge,\n external = false,\n status,\n statusLabel,\n suffix,\n}: SideNavItemProps): React.ReactElement {\n const { tokens } = useTheme();\n const { collapsed, setMobileOpen, density } = useContext(SideNavContext);\n const compact = density === \"compact\" && !collapsed;\n const [isHovered, setIsHovered] = useState(false);\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return;\n if (onClick && href && !e.metaKey && !e.ctrlKey && !e.shiftKey) {\n e.preventDefault();\n }\n setMobileOpen(false);\n onClick?.();\n },\n [disabled, onClick, href, setMobileOpen],\n );\n\n // Status-aware accent: when an item has a status, tint active/hover with its color\n const statusColor = status\n ? (tokens.colors.status[status] ?? undefined)\n : undefined;\n const accentColor =\n statusColor && active\n ? statusColor\n : safeAccentText(tokens.colors.accent.primary);\n\n const hasDescription = !!description && !collapsed;\n\n const iconElement =\n typeof icon === \"string\" ? (\n <Icon\n name={icon as IconName}\n size={hasDescription ? 22 : 20}\n color={active ? accentColor : tokens.colors.text.secondary}\n />\n ) : (\n icon\n );\n\n const itemStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: hasDescription ? \"flex-start\" : \"center\",\n gap: tokens.spacing.sm,\n // Collapsed keeps the SAME 12px left inset as the expanded row, so the\n // icon holds its horizontal position when the rail expands — it doesn't\n // jump from a centered slot to a left-aligned one. Size the collapsed\n // width so that fixed inset reads as centered.\n padding: collapsed\n ? `${tokens.spacing.sm} 12px`\n : compact\n ? \"7px 8px\"\n : hasDescription\n ? `10px 16px 10px 12px`\n : `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 12px`,\n // Compact: pill-style rounded row (mock parity). Default: square row.\n borderRadius: compact ? tokens.borderRadius.md : 0,\n justifyContent: \"flex-start\",\n color: active\n ? accentColor\n : disabled\n ? tokens.colors.text.tertiary\n : tokens.colors.text.secondary,\n backgroundColor: active\n ? `${accentColor}12`\n : isHovered && !disabled\n ? `${accentColor}08`\n : \"transparent\",\n fontSize: compact\n ? tokens.typography.fontSize.xs\n : tokens.typography.fontSize.sm,\n fontWeight: active\n ? tokens.typography.fontWeight.semibold\n : tokens.typography.fontWeight.normal,\n fontFamily: tokens.typography.fontFamily.primary,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n textDecoration: \"none\",\n borderTop: \"none\",\n borderRight: \"none\",\n borderBottom: \"none\",\n // Compact drops the left accent bar — the active row is conveyed by the\n // bg tint + accent text alone (mock parity). Default keeps the 3px bar.\n borderLeft: compact\n ? \"none\"\n : active\n ? `3px solid ${accentColor}`\n : \"3px solid transparent\",\n outline: \"none\",\n width: \"100%\",\n boxSizing: \"border-box\",\n transition: tokens.animation.fast,\n position: \"relative\",\n opacity: disabled ? 0.5 : 1,\n };\n\n const tagColors = TAG_COLORS[tagVariant] ?? TAG_COLORS.default;\n\n const content = (\n <>\n {/* Icon + collapsed status overlay */}\n {iconElement && (\n <span\n style={{\n flexShrink: 0,\n display: \"flex\",\n position: \"relative\",\n marginTop: hasDescription ? \"2px\" : 0,\n }}\n >\n {iconElement}\n {/* In collapsed mode, show a small status shape overlaid on the icon (top-left) */}\n {collapsed && status && (\n <span\n style={{\n position: \"absolute\",\n top: -3,\n left: -4,\n lineHeight: 0,\n }}\n title={statusLabel ?? status}\n >\n <NavStatusShape status={status} size={7} />\n </span>\n )}\n </span>\n )}\n {/* Label — always mounted and toggled via data-collapsed so it fades and\n slides BOTH on expand and collapse; the icon holds its position as\n the anchor and only the label moves. */}\n <span\n className=\"zsn-label\"\n data-collapsed={collapsed ? \"true\" : \"false\"}\n style={{ flex: 1, minWidth: 0, overflow: \"hidden\" }}\n >\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <span\n style={{\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {label}\n </span>\n {tag && (\n <span\n style={{\n fontSize: \"0.6rem\",\n fontWeight: tokens.typography.fontWeight.bold,\n color: tagColors.fg,\n backgroundColor: tagColors.bg,\n border: `1px solid ${tagColors.border}`,\n padding: \"1px 5px\",\n borderRadius: tokens.borderRadius.sm,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n flexShrink: 0,\n lineHeight: \"1.3\",\n whiteSpace: \"nowrap\",\n }}\n >\n {tag}\n </span>\n )}\n </span>\n {description && !collapsed && (\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xxs,\n color: tokens.colors.text.tertiary,\n lineHeight: tokens.typography.lineHeight.normal,\n marginTop: \"2px\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n fontWeight: tokens.typography.fontWeight.normal,\n }}\n >\n {description}\n </span>\n )}\n </span>\n {/* Right-side trailing elements — expanded only; collapsed shows the\n status overlay on the icon instead. */}\n {!collapsed &&\n ((badge !== undefined && badge > 0) ||\n status ||\n suffix ||\n external) && (\n <span\n className=\"zsn-reveal\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n flexShrink: 0,\n marginTop: hasDescription ? \"2px\" : 0,\n }}\n >\n {/* Badge */}\n {badge !== undefined && badge > 0 && (\n <span\n style={{\n fontSize: \"0.65rem\",\n fontWeight: tokens.typography.fontWeight.bold,\n color: \"#fff\",\n backgroundColor: tokens.colors.status.critical,\n borderRadius: tokens.borderRadius.full,\n minWidth: \"18px\",\n height: \"18px\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"0 5px\",\n flexShrink: 0,\n lineHeight: 1,\n boxSizing: \"border-box\",\n }}\n >\n {badge > 99 ? \"99+\" : badge}\n </span>\n )}\n {/* Status */}\n {status && (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n flexShrink: 0,\n }}\n role=\"status\"\n aria-label={`Status: ${statusLabel ?? status}`}\n title={statusLabel ?? status}\n >\n <NavStatusShape status={status} size={8} />\n </span>\n )}\n {/* Suffix */}\n {suffix && (\n <span\n style={{\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n }}\n >\n {suffix}\n </span>\n )}\n {/* External */}\n {external && (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n style={{ flexShrink: 0, opacity: 0.5 }}\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n )}\n </span>\n )}\n </>\n );\n\n const props = {\n style: itemStyle,\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n title: collapsed ? label : undefined,\n \"aria-current\": active ? (\"page\" as const) : undefined,\n \"aria-disabled\": disabled,\n };\n\n if (href && !disabled) {\n return (\n <a\n href={href}\n onClick={handleClick}\n target={external ? \"_blank\" : undefined}\n rel={external ? \"noopener noreferrer\" : undefined}\n {...props}\n >\n {content}\n </a>\n );\n }\n\n return (\n <button type=\"button\" onClick={handleClick} disabled={disabled} {...props}>\n {content}\n </button>\n );\n});\n\n// ─── Section ─────────────────────────────────────────────────────────────────\n\nexport interface SideNavSectionProps {\n /** Section title */\n title?: string;\n /** Children (SideNav.Item elements) */\n children?: React.ReactNode;\n}\n\nconst SideNavSection = memo(function SideNavSection({\n title,\n children,\n}: SideNavSectionProps): React.ReactElement {\n const { tokens } = useTheme();\n const { collapsed } = useContext(SideNavContext);\n\n return (\n <div style={{ marginTop: tokens.spacing.sm }}>\n {title && !collapsed && (\n <div\n className=\"zsn-reveal\"\n style={{\n padding: `${tokens.spacing.xs} 16px ${tokens.spacing.xs} 15px`,\n fontSize: tokens.typography.fontSize.xxs,\n fontWeight: tokens.typography.fontWeight.bold,\n color: tokens.colors.text.tertiary,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n {title}\n </div>\n )}\n {collapsed && title && (\n <div\n style={{\n width: \"60%\",\n height: \"1px\",\n backgroundColor: tokens.colors.border.muted,\n margin: `${tokens.spacing.xs} auto`,\n }}\n />\n )}\n {children}\n </div>\n );\n});\n\n// ─── Divider ─────────────────────────────────────────────────────────────────\n\nexport interface SideNavDividerProps {\n /** Optional label shown in the center of the divider line */\n label?: string;\n}\n\nconst SideNavDivider = memo(function SideNavDivider({\n label,\n}: SideNavDividerProps): React.ReactElement {\n const { tokens } = useTheme();\n const { collapsed } = useContext(SideNavContext);\n\n if (collapsed) {\n return (\n <div\n style={{\n width: \"60%\",\n height: \"1px\",\n backgroundColor: tokens.colors.border.muted,\n margin: `${tokens.spacing.sm} auto`,\n }}\n />\n );\n }\n\n if (label) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n padding: `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 15px`,\n }}\n >\n <div\n style={{\n flex: 1,\n height: \"1px\",\n backgroundColor: tokens.colors.border.muted,\n }}\n />\n <span\n style={{\n fontSize: tokens.typography.fontSize.xxs,\n color: tokens.colors.text.tertiary,\n textTransform: \"uppercase\",\n letterSpacing: \"0.06em\",\n whiteSpace: \"nowrap\",\n }}\n >\n {label}\n </span>\n <div\n style={{\n flex: 1,\n height: \"1px\",\n backgroundColor: tokens.colors.border.muted,\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n style={{\n height: \"1px\",\n backgroundColor: tokens.colors.border.muted,\n margin: `${tokens.spacing.sm} 16px ${tokens.spacing.sm} 15px`,\n }}\n />\n );\n});\n\n// ─── Footer ──────────────────────────────────────────────────────────────────\n\nexport interface SideNavFooterProps {\n children?: React.ReactNode;\n}\n\nconst SideNavFooter = memo(function SideNavFooter({\n children,\n}: SideNavFooterProps): React.ReactElement {\n const { tokens } = useTheme();\n\n return (\n <div\n style={{\n marginTop: \"auto\",\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n paddingTop: tokens.spacing.xs,\n paddingBottom: tokens.spacing.xs,\n }}\n >\n {children}\n </div>\n );\n});\n\n// ─── Compound Export ─────────────────────────────────────────────────────────\n\ntype SideNavComponent = typeof SideNavRoot & {\n Header: typeof SideNavHeader;\n Item: typeof SideNavItem;\n Section: typeof SideNavSection;\n Divider: typeof SideNavDivider;\n Footer: typeof SideNavFooter;\n};\n\nexport const SideNav: SideNavComponent = Object.assign(SideNavRoot, {\n Header: SideNavHeader,\n Item: SideNavItem,\n Section: SideNavSection,\n Divider: SideNavDivider,\n Footer: SideNavFooter,\n});\n\nexport default SideNav;\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { default as React } from 'react';
2
-
3
2
  export interface TabsProps {
4
3
  /** Active tab value */
5
4
  value: string;
@@ -1,129 +1,123 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { memo, useId, createContext, useContext } from "react";
3
1
  import { useTheme } from "../../theme/ThemeProvider.js";
4
2
  import { classNames, safeAccentText } from "../../utils/index.js";
5
- const TabsContext = createContext(null);
6
- const useTabsContext = () => {
7
- const context = useContext(TabsContext);
8
- if (!context) {
9
- throw new Error("Tabs components must be used within a Tabs provider");
10
- }
11
- return context;
3
+ import { createContext, memo, useContext, useId } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/react/core/navigation/Tabs.tsx
6
+ /**
7
+ * @zendir/ui - Tabs Component
8
+ *
9
+ * Tab navigation following Astro UX Design System.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <Tabs value={activeTab} onChange={setActiveTab}>
14
+ * <Tabs.List>
15
+ * <Tabs.Tab value="overview">Overview</Tabs.Tab>
16
+ * <Tabs.Tab value="telemetry">Telemetry</Tabs.Tab>
17
+ * <Tabs.Tab value="commands">Commands</Tabs.Tab>
18
+ * </Tabs.List>
19
+ * <Tabs.Panel value="overview">Overview content</Tabs.Panel>
20
+ * <Tabs.Panel value="telemetry">Telemetry content</Tabs.Panel>
21
+ * <Tabs.Panel value="commands">Commands content</Tabs.Panel>
22
+ * </Tabs>
23
+ * ```
24
+ */
25
+ var TabsContext = createContext(null);
26
+ var useTabsContext = () => {
27
+ const context = useContext(TabsContext);
28
+ if (!context) throw new Error("Tabs components must be used within a Tabs provider");
29
+ return context;
12
30
  };
13
- const TabsList = memo(function TabsList2({
14
- children,
15
- className = ""
16
- }) {
17
- const { tokens } = useTheme();
18
- return /* @__PURE__ */ jsx(
19
- "div",
20
- {
21
- role: "tablist",
22
- className: classNames("zendir-tabs-list", className),
23
- style: {
24
- display: "flex",
25
- gap: tokens.spacing.xs,
26
- borderBottom: tokens.borders.divider,
27
- marginBottom: tokens.spacing.md
28
- },
29
- children
30
- }
31
- );
31
+ var TabsList = memo(function TabsList({ children, className = "" }) {
32
+ const { tokens } = useTheme();
33
+ return /* @__PURE__ */ jsx("div", {
34
+ role: "tablist",
35
+ className: classNames("zendir-tabs-list", className),
36
+ style: {
37
+ display: "flex",
38
+ gap: tokens.spacing.xs,
39
+ borderBottom: tokens.borders.divider,
40
+ marginBottom: tokens.spacing.md
41
+ },
42
+ children
43
+ });
32
44
  });
33
- const Tab = memo(function Tab2({
34
- value,
35
- disabled = false,
36
- icon,
37
- children,
38
- className = ""
39
- }) {
40
- const { tokens } = useTheme();
41
- const { value: activeValue, onChange, baseId } = useTabsContext();
42
- const isActive = value === activeValue;
43
- return /* @__PURE__ */ jsxs(
44
- "button",
45
- {
46
- type: "button",
47
- role: "tab",
48
- id: `${baseId}-tab-${value}`,
49
- "aria-controls": `${baseId}-panel-${value}`,
50
- "aria-selected": isActive,
51
- "aria-disabled": disabled,
52
- disabled,
53
- onClick: () => !disabled && onChange(value),
54
- className: classNames("zendir-tab", isActive && "zendir-tab--active", className),
55
- style: {
56
- display: "flex",
57
- alignItems: "center",
58
- gap: tokens.spacing.xs,
59
- padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,
60
- fontSize: tokens.typography.fontSize.sm,
61
- fontWeight: isActive ? tokens.typography.fontWeight.semibold : tokens.typography.fontWeight.normal,
62
- fontFamily: tokens.typography.fontFamily.primary,
63
- color: isActive ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.secondary,
64
- backgroundColor: "transparent",
65
- border: "none",
66
- borderBottom: `${tokens.borders.width.thick} solid ${isActive ? tokens.colors.accent.primary : "transparent"}`,
67
- marginBottom: "-1px",
68
- cursor: disabled ? "not-allowed" : "pointer",
69
- opacity: disabled ? 0.5 : 1,
70
- transition: `all ${tokens.animation.fast}`,
71
- outline: "none"
72
- },
73
- onMouseEnter: (e) => {
74
- if (!disabled && !isActive) {
75
- e.currentTarget.style.color = tokens.colors.text.primary;
76
- }
77
- },
78
- onMouseLeave: (e) => {
79
- if (!disabled && !isActive) {
80
- e.currentTarget.style.color = tokens.colors.text.secondary;
81
- }
82
- },
83
- onFocus: (e) => {
84
- e.currentTarget.style.boxShadow = tokens.borders.focusRing.subtle;
85
- },
86
- onBlur: (e) => {
87
- e.currentTarget.style.boxShadow = "none";
88
- },
89
- children: [
90
- icon,
91
- children
92
- ]
93
- }
94
- );
45
+ var Tab = memo(function Tab({ value, disabled = false, icon, children, className = "" }) {
46
+ const { tokens } = useTheme();
47
+ const { value: activeValue, onChange, baseId } = useTabsContext();
48
+ const isActive = value === activeValue;
49
+ return /* @__PURE__ */ jsxs("button", {
50
+ type: "button",
51
+ role: "tab",
52
+ id: `${baseId}-tab-${value}`,
53
+ "aria-controls": `${baseId}-panel-${value}`,
54
+ "aria-selected": isActive,
55
+ "aria-disabled": disabled,
56
+ disabled,
57
+ onClick: () => !disabled && onChange(value),
58
+ className: classNames("zendir-tab", isActive && "zendir-tab--active", className),
59
+ style: {
60
+ display: "flex",
61
+ alignItems: "center",
62
+ gap: tokens.spacing.xs,
63
+ padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,
64
+ fontSize: tokens.typography.fontSize.sm,
65
+ fontWeight: isActive ? tokens.typography.fontWeight.semibold : tokens.typography.fontWeight.normal,
66
+ fontFamily: tokens.typography.fontFamily.primary,
67
+ color: isActive ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.secondary,
68
+ backgroundColor: "transparent",
69
+ border: "none",
70
+ borderBottom: `${tokens.borders.width.thick} solid ${isActive ? tokens.colors.accent.primary : "transparent"}`,
71
+ marginBottom: "-1px",
72
+ cursor: disabled ? "not-allowed" : "pointer",
73
+ opacity: disabled ? .5 : 1,
74
+ transition: `all ${tokens.animation.fast}`,
75
+ outline: "none"
76
+ },
77
+ onMouseEnter: (e) => {
78
+ if (!disabled && !isActive) e.currentTarget.style.color = tokens.colors.text.primary;
79
+ },
80
+ onMouseLeave: (e) => {
81
+ if (!disabled && !isActive) e.currentTarget.style.color = tokens.colors.text.secondary;
82
+ },
83
+ onFocus: (e) => {
84
+ e.currentTarget.style.boxShadow = tokens.borders.focusRing.subtle;
85
+ },
86
+ onBlur: (e) => {
87
+ e.currentTarget.style.boxShadow = "none";
88
+ },
89
+ children: [icon, children]
90
+ });
95
91
  });
96
- const TabsPanel = memo(function TabsPanel2({
97
- value,
98
- children,
99
- className = ""
100
- }) {
101
- const { value: activeValue, baseId } = useTabsContext();
102
- if (value !== activeValue) return null;
103
- return /* @__PURE__ */ jsx(
104
- "div",
105
- {
106
- role: "tabpanel",
107
- id: `${baseId}-panel-${value}`,
108
- "aria-labelledby": `${baseId}-tab-${value}`,
109
- className: classNames("zendir-tabs-panel", className),
110
- children
111
- }
112
- );
92
+ var TabsPanel = memo(function TabsPanel({ value, children, className = "" }) {
93
+ const { value: activeValue, baseId } = useTabsContext();
94
+ if (value !== activeValue) return null;
95
+ return /* @__PURE__ */ jsx("div", {
96
+ role: "tabpanel",
97
+ id: `${baseId}-panel-${value}`,
98
+ "aria-labelledby": `${baseId}-tab-${value}`,
99
+ className: classNames("zendir-tabs-panel", className),
100
+ children
101
+ });
113
102
  });
114
- const Tabs = memo(function Tabs2({
115
- value,
116
- onChange,
117
- children,
118
- className = ""
119
- }) {
120
- const baseId = useId();
121
- return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value, onChange, baseId }, children: /* @__PURE__ */ jsx("div", { className: classNames("zendir-tabs", className), children }) });
103
+ var Tabs = memo(function Tabs({ value, onChange, children, className = "" }) {
104
+ const baseId = useId();
105
+ return /* @__PURE__ */ jsx(TabsContext.Provider, {
106
+ value: {
107
+ value,
108
+ onChange,
109
+ baseId
110
+ },
111
+ children: /* @__PURE__ */ jsx("div", {
112
+ className: classNames("zendir-tabs", className),
113
+ children
114
+ })
115
+ });
122
116
  });
123
117
  Tabs.List = TabsList;
124
118
  Tabs.Tab = Tab;
125
119
  Tabs.Panel = TabsPanel;
126
- export {
127
- Tabs
128
- };
129
- //# sourceMappingURL=Tabs.js.map
120
+ //#endregion
121
+ export { Tabs, Tabs as default };
122
+
123
+ //# sourceMappingURL=Tabs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","sources":["../../../../src/react/core/navigation/Tabs.tsx"],"sourcesContent":["/**\n * @zendir/ui - Tabs Component\n * \n * Tab navigation following Astro UX Design System.\n * \n * @example\n * ```tsx\n * <Tabs value={activeTab} onChange={setActiveTab}>\n * <Tabs.List>\n * <Tabs.Tab value=\"overview\">Overview</Tabs.Tab>\n * <Tabs.Tab value=\"telemetry\">Telemetry</Tabs.Tab>\n * <Tabs.Tab value=\"commands\">Commands</Tabs.Tab>\n * </Tabs.List>\n * <Tabs.Panel value=\"overview\">Overview content</Tabs.Panel>\n * <Tabs.Panel value=\"telemetry\">Telemetry content</Tabs.Panel>\n * <Tabs.Panel value=\"commands\">Commands content</Tabs.Panel>\n * </Tabs>\n * ```\n */\n\nimport React, { memo, createContext, useContext, useId } from 'react';\nimport { useTheme } from '../../theme';\nimport { classNames, safeAccentText } from '../../utils';\n\ninterface TabsContextValue {\n value: string;\n onChange: (value: string) => void;\n baseId: string;\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nconst useTabsContext = () => {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error('Tabs components must be used within a Tabs provider');\n }\n return context;\n};\n\nexport interface TabsProps {\n /** Active tab value */\n value: string;\n /** Change handler */\n onChange: (value: string) => void;\n /** Children */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabsListProps {\n /** Children (Tab components) */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabProps {\n /** Tab value */\n value: string;\n /** Disabled state */\n disabled?: boolean;\n /** Icon before label */\n icon?: React.ReactNode;\n /** Children (label) */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabsPanelProps {\n /** Panel value (must match Tab value) */\n value: string;\n /** Children */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nconst TabsList = memo(function TabsList({\n children,\n className = '',\n}: TabsListProps): React.ReactElement {\n const { tokens } = useTheme();\n \n return (\n <div\n role=\"tablist\"\n className={classNames('zendir-tabs-list', className)}\n style={{\n display: 'flex',\n gap: tokens.spacing.xs,\n borderBottom: tokens.borders.divider,\n marginBottom: tokens.spacing.md,\n }}\n >\n {children}\n </div>\n );\n});\n\nconst Tab = memo(function Tab({\n value,\n disabled = false,\n icon,\n children,\n className = '',\n}: TabProps): React.ReactElement {\n const { tokens } = useTheme();\n const { value: activeValue, onChange, baseId } = useTabsContext();\n \n const isActive = value === activeValue;\n \n return (\n <button\n type=\"button\"\n role=\"tab\"\n id={`${baseId}-tab-${value}`}\n aria-controls={`${baseId}-panel-${value}`}\n aria-selected={isActive}\n aria-disabled={disabled}\n disabled={disabled}\n onClick={() => !disabled && onChange(value)}\n className={classNames('zendir-tab', isActive && 'zendir-tab--active', className)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: tokens.spacing.xs,\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n fontSize: tokens.typography.fontSize.sm,\n fontWeight: isActive ? tokens.typography.fontWeight.semibold : tokens.typography.fontWeight.normal,\n fontFamily: tokens.typography.fontFamily.primary,\n color: isActive ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.secondary,\n backgroundColor: 'transparent',\n border: 'none',\n borderBottom: `${tokens.borders.width.thick} solid ${isActive ? tokens.colors.accent.primary : 'transparent'}`,\n marginBottom: '-1px',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n transition: `all ${tokens.animation.fast}`,\n outline: 'none',\n }}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.color = tokens.colors.text.primary;\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.color = tokens.colors.text.secondary;\n }\n }}\n onFocus={(e) => {\n e.currentTarget.style.boxShadow = tokens.borders.focusRing.subtle;\n }}\n onBlur={(e) => {\n e.currentTarget.style.boxShadow = 'none';\n }}\n >\n {icon}\n {children}\n </button>\n );\n});\n\nconst TabsPanel = memo(function TabsPanel({\n value,\n children,\n className = '',\n}: TabsPanelProps): React.ReactElement | null {\n const { value: activeValue, baseId } = useTabsContext();\n \n if (value !== activeValue) return null;\n \n return (\n <div\n role=\"tabpanel\"\n id={`${baseId}-panel-${value}`}\n aria-labelledby={`${baseId}-tab-${value}`}\n className={classNames('zendir-tabs-panel', className)}\n >\n {children}\n </div>\n );\n});\n\nexport const Tabs = memo(function Tabs({\n value,\n onChange,\n children,\n className = '',\n}: TabsProps): React.ReactElement {\n const baseId = useId();\n return (\n <TabsContext.Provider value={{ value, onChange, baseId }}>\n <div className={classNames('zendir-tabs', className)}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n}) as React.NamedExoticComponent<TabsProps> & {\n List: typeof TabsList;\n Tab: typeof Tab;\n Panel: typeof TabsPanel;\n};\n\n// Attach subcomponents\n(Tabs as any).List = TabsList;\n(Tabs as any).Tab = Tab;\n(Tabs as any).Panel = TabsPanel;\n\nexport default Tabs;\n"],"names":["TabsList","Tab","TabsPanel","Tabs"],"mappings":"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"}
1
+ {"version":3,"file":"Tabs.js","names":[],"sources":["../../../../src/react/core/navigation/Tabs.tsx"],"sourcesContent":["/**\n * @zendir/ui - Tabs Component\n *\n * Tab navigation following Astro UX Design System.\n *\n * @example\n * ```tsx\n * <Tabs value={activeTab} onChange={setActiveTab}>\n * <Tabs.List>\n * <Tabs.Tab value=\"overview\">Overview</Tabs.Tab>\n * <Tabs.Tab value=\"telemetry\">Telemetry</Tabs.Tab>\n * <Tabs.Tab value=\"commands\">Commands</Tabs.Tab>\n * </Tabs.List>\n * <Tabs.Panel value=\"overview\">Overview content</Tabs.Panel>\n * <Tabs.Panel value=\"telemetry\">Telemetry content</Tabs.Panel>\n * <Tabs.Panel value=\"commands\">Commands content</Tabs.Panel>\n * </Tabs>\n * ```\n */\n\nimport React, { memo, createContext, useContext, useId } from \"react\";\nimport { useTheme } from \"../../theme\";\nimport { classNames, safeAccentText } from \"../../utils\";\n\ninterface TabsContextValue {\n value: string;\n onChange: (value: string) => void;\n baseId: string;\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nconst useTabsContext = () => {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error(\"Tabs components must be used within a Tabs provider\");\n }\n return context;\n};\n\nexport interface TabsProps {\n /** Active tab value */\n value: string;\n /** Change handler */\n onChange: (value: string) => void;\n /** Children */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabsListProps {\n /** Children (Tab components) */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabProps {\n /** Tab value */\n value: string;\n /** Disabled state */\n disabled?: boolean;\n /** Icon before label */\n icon?: React.ReactNode;\n /** Children (label) */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nexport interface TabsPanelProps {\n /** Panel value (must match Tab value) */\n value: string;\n /** Children */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n\nconst TabsList = memo(function TabsList({\n children,\n className = \"\",\n}: TabsListProps): React.ReactElement {\n const { tokens } = useTheme();\n\n return (\n <div\n role=\"tablist\"\n className={classNames(\"zendir-tabs-list\", className)}\n style={{\n display: \"flex\",\n gap: tokens.spacing.xs,\n borderBottom: tokens.borders.divider,\n marginBottom: tokens.spacing.md,\n }}\n >\n {children}\n </div>\n );\n});\n\nconst Tab = memo(function Tab({\n value,\n disabled = false,\n icon,\n children,\n className = \"\",\n}: TabProps): React.ReactElement {\n const { tokens } = useTheme();\n const { value: activeValue, onChange, baseId } = useTabsContext();\n\n const isActive = value === activeValue;\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n id={`${baseId}-tab-${value}`}\n aria-controls={`${baseId}-panel-${value}`}\n aria-selected={isActive}\n aria-disabled={disabled}\n disabled={disabled}\n onClick={() => !disabled && onChange(value)}\n className={classNames(\n \"zendir-tab\",\n isActive && \"zendir-tab--active\",\n className,\n )}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.xs,\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n fontSize: tokens.typography.fontSize.sm,\n fontWeight: isActive\n ? tokens.typography.fontWeight.semibold\n : tokens.typography.fontWeight.normal,\n fontFamily: tokens.typography.fontFamily.primary,\n color: isActive\n ? safeAccentText(tokens.colors.accent.primary)\n : tokens.colors.text.secondary,\n backgroundColor: \"transparent\",\n border: \"none\",\n borderBottom: `${tokens.borders.width.thick} solid ${isActive ? tokens.colors.accent.primary : \"transparent\"}`,\n marginBottom: \"-1px\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n transition: `all ${tokens.animation.fast}`,\n outline: \"none\",\n }}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.color = tokens.colors.text.primary;\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.color = tokens.colors.text.secondary;\n }\n }}\n onFocus={(e) => {\n e.currentTarget.style.boxShadow = tokens.borders.focusRing.subtle;\n }}\n onBlur={(e) => {\n e.currentTarget.style.boxShadow = \"none\";\n }}\n >\n {icon}\n {children}\n </button>\n );\n});\n\nconst TabsPanel = memo(function TabsPanel({\n value,\n children,\n className = \"\",\n}: TabsPanelProps): React.ReactElement | null {\n const { value: activeValue, baseId } = useTabsContext();\n\n if (value !== activeValue) return null;\n\n return (\n <div\n role=\"tabpanel\"\n id={`${baseId}-panel-${value}`}\n aria-labelledby={`${baseId}-tab-${value}`}\n className={classNames(\"zendir-tabs-panel\", className)}\n >\n {children}\n </div>\n );\n});\n\nexport const Tabs = memo(function Tabs({\n value,\n onChange,\n children,\n className = \"\",\n}: TabsProps): React.ReactElement {\n const baseId = useId();\n return (\n <TabsContext.Provider value={{ value, onChange, baseId }}>\n <div className={classNames(\"zendir-tabs\", className)}>{children}</div>\n </TabsContext.Provider>\n );\n}) as React.NamedExoticComponent<TabsProps> & {\n List: typeof TabsList;\n Tab: typeof Tab;\n Panel: typeof TabsPanel;\n};\n\n// Attach subcomponents\n(Tabs as any).List = TabsList;\n(Tabs as any).Tab = Tab;\n(Tabs as any).Panel = TabsPanel;\n\nexport default Tabs;\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { default as React } from 'react';
2
-
3
- export type PopoverPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end';
2
+ export type PopoverPlacement = "top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end" | "right" | "right-start" | "right-end";
4
3
  export interface PopoverProps {
5
4
  /** Trigger element */
6
5
  trigger: React.ReactElement;
@@ -17,7 +16,7 @@ export interface PopoverProps {
17
16
  /** Close on content click */
18
17
  closeOnClick?: boolean;
19
18
  /** Width: 'trigger' matches trigger width, number for px, 'auto' */
20
- width?: 'trigger' | 'auto' | number;
19
+ width?: "trigger" | "auto" | number;
21
20
  /** Custom style for popover panel */
22
21
  style?: React.CSSProperties;
23
22
  }