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