entangle-ui 0.10.0 → 0.12.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 (589) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +7 -5
  3. package/dist/esm/assets/src/components/controls/Select/{Select.css.ts.vanilla-oZnFUorL.css → Select.css.ts.vanilla-Cpu2BvWL.css} +3 -0
  4. package/dist/esm/assets/src/components/controls/Slider/{Slider.css.ts.vanilla-Cqm3fQ0S.css → Slider.css.ts.vanilla-CLf_RC0A.css} +50 -47
  5. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyPanel.css.ts.vanilla-RYv_XgOu.css → PropertyPanel.css.ts.vanilla-Dpr_k5I3.css} +4 -1
  6. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyRow.css.ts.vanilla-C3YZnnHb.css → PropertyRow.css.ts.vanilla-pq1Uhd2a.css} +15 -8
  7. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertySection.css.ts.vanilla-DK12opZc.css → PropertySection.css.ts.vanilla-6MWWAqyd.css} +50 -32
  8. package/dist/esm/assets/src/components/navigation/Menu/{Menu.css.ts.vanilla-B5iVe5S2.css → Menu.css.ts.vanilla-Bhh1L5yl.css} +14 -11
  9. package/dist/esm/assets/src/components/primitives/Tooltip/{Tooltip.css.ts.vanilla-CrEFoLBX.css → Tooltip.css.ts.vanilla-BqaiGrFQ.css} +12 -9
  10. package/dist/esm/assets/src/components/shell/AppShell/{AppShell.css.ts.vanilla-BYmtU0O_.css → AppShell.css.ts.vanilla-BLK2-DRL.css} +1 -0
  11. package/dist/esm/assets/src/components/shell/MenuBar/{MenuBar.css.ts.vanilla-TgPcl4yA.css → MenuBar.css.ts.vanilla-Dt3w4f-q.css} +18 -6
  12. package/dist/esm/components/Icons/AddIcon.js.map +1 -1
  13. package/dist/esm/components/Icons/AiChatIcon.js.map +1 -1
  14. package/dist/esm/components/Icons/AiSparklesIcon.js.map +1 -1
  15. package/dist/esm/components/Icons/ArchiveIcon.js.map +1 -1
  16. package/dist/esm/components/Icons/ArrowDownIcon.js.map +1 -1
  17. package/dist/esm/components/Icons/ArrowLeftIcon.js.map +1 -1
  18. package/dist/esm/components/Icons/ArrowRightIcon.js.map +1 -1
  19. package/dist/esm/components/Icons/ArrowUpIcon.js.map +1 -1
  20. package/dist/esm/components/Icons/BookmarkIcon.js.map +1 -1
  21. package/dist/esm/components/Icons/BugIcon.js.map +1 -1
  22. package/dist/esm/components/Icons/BuildingIcon.js.map +1 -1
  23. package/dist/esm/components/Icons/CalendarIcon.js.map +1 -1
  24. package/dist/esm/components/Icons/CameraIcon.js +31 -0
  25. package/dist/esm/components/Icons/CameraIcon.js.map +1 -0
  26. package/dist/esm/components/Icons/CheckIcon.js.map +1 -1
  27. package/dist/esm/components/Icons/ChevronDownIcon.js.map +1 -1
  28. package/dist/esm/components/Icons/ChevronLeftIcon.js.map +1 -1
  29. package/dist/esm/components/Icons/ChevronRightIcon.js.map +1 -1
  30. package/dist/esm/components/Icons/ChevronUpIcon.js.map +1 -1
  31. package/dist/esm/components/Icons/CircleIcon.js.map +1 -1
  32. package/dist/esm/components/Icons/ClockIcon.js.map +1 -1
  33. package/dist/esm/components/Icons/CloseIcon.js.map +1 -1
  34. package/dist/esm/components/Icons/CloudUploadIcon.js.map +1 -1
  35. package/dist/esm/components/Icons/CodeIcon.js.map +1 -1
  36. package/dist/esm/components/Icons/CopyIcon.js.map +1 -1
  37. package/dist/esm/components/Icons/CubeIcon.js +31 -0
  38. package/dist/esm/components/Icons/CubeIcon.js.map +1 -0
  39. package/dist/esm/components/Icons/CutIcon.js.map +1 -1
  40. package/dist/esm/components/Icons/DotsHorizontalIcon.js.map +1 -1
  41. package/dist/esm/components/Icons/DotsVerticalIcon.js.map +1 -1
  42. package/dist/esm/components/Icons/DownloadIcon.js.map +1 -1
  43. package/dist/esm/components/Icons/EditIcon.js.map +1 -1
  44. package/dist/esm/components/Icons/ErrorIcon.js.map +1 -1
  45. package/dist/esm/components/Icons/ExternalLinkIcon.js.map +1 -1
  46. package/dist/esm/components/Icons/EyeDropperIcon.js.map +1 -1
  47. package/dist/esm/components/Icons/EyeIcon.js.map +1 -1
  48. package/dist/esm/components/Icons/FileTextIcon.js.map +1 -1
  49. package/dist/esm/components/Icons/FilterIcon.js.map +1 -1
  50. package/dist/esm/components/Icons/FirstIcon.js.map +1 -1
  51. package/dist/esm/components/Icons/FolderCogIcon.js.map +1 -1
  52. package/dist/esm/components/Icons/FolderIcon.js.map +1 -1
  53. package/dist/esm/components/Icons/FolderOpenIcon.js.map +1 -1
  54. package/dist/esm/components/Icons/FullscreenIcon.js.map +1 -1
  55. package/dist/esm/components/Icons/GitBranchIcon.js.map +1 -1
  56. package/dist/esm/components/Icons/GridIcon.js.map +1 -1
  57. package/dist/esm/components/Icons/HeartIcon.js.map +1 -1
  58. package/dist/esm/components/Icons/HelpIcon.js.map +1 -1
  59. package/dist/esm/components/Icons/HomeIcon.js.map +1 -1
  60. package/dist/esm/components/Icons/ImageIcon.js.map +1 -1
  61. package/dist/esm/components/Icons/InfoIcon.js.map +1 -1
  62. package/dist/esm/components/Icons/LastIcon.js.map +1 -1
  63. package/dist/esm/components/Icons/LinkIcon.js.map +1 -1
  64. package/dist/esm/components/Icons/ListIcon.js.map +1 -1
  65. package/dist/esm/components/Icons/LockIcon.js.map +1 -1
  66. package/dist/esm/components/Icons/MaximizeIcon.js.map +1 -1
  67. package/dist/esm/components/Icons/MenuIcon.js.map +1 -1
  68. package/dist/esm/components/Icons/MinimizeIcon.js.map +1 -1
  69. package/dist/esm/components/Icons/MinusIcon.js.map +1 -1
  70. package/dist/esm/components/Icons/OrbitIcon.js +31 -0
  71. package/dist/esm/components/Icons/OrbitIcon.js.map +1 -0
  72. package/dist/esm/components/Icons/PasteIcon.js.map +1 -1
  73. package/dist/esm/components/Icons/PauseIcon.js.map +1 -1
  74. package/dist/esm/components/Icons/PinIcon.js.map +1 -1
  75. package/dist/esm/components/Icons/PlayIcon.js.map +1 -1
  76. package/dist/esm/components/Icons/RedoIcon.js.map +1 -1
  77. package/dist/esm/components/Icons/RefreshIcon.js.map +1 -1
  78. package/dist/esm/components/Icons/RobotIcon.js.map +1 -1
  79. package/dist/esm/components/Icons/RotateIcon.js +32 -0
  80. package/dist/esm/components/Icons/RotateIcon.js.map +1 -0
  81. package/dist/esm/components/Icons/SaveIcon.js.map +1 -1
  82. package/dist/esm/components/Icons/SearchIcon.js.map +1 -1
  83. package/dist/esm/components/Icons/SendIcon.js.map +1 -1
  84. package/dist/esm/components/Icons/SettingsIcon.js.map +1 -1
  85. package/dist/esm/components/Icons/SortIcon.js.map +1 -1
  86. package/dist/esm/components/Icons/SpinIcon.js +32 -0
  87. package/dist/esm/components/Icons/SpinIcon.js.map +1 -0
  88. package/dist/esm/components/Icons/StarIcon.js.map +1 -1
  89. package/dist/esm/components/Icons/StopIcon.js.map +1 -1
  90. package/dist/esm/components/Icons/SuccessIcon.js.map +1 -1
  91. package/dist/esm/components/Icons/TagIcon.js.map +1 -1
  92. package/dist/esm/components/Icons/TangentAlignedIcon.js.map +1 -1
  93. package/dist/esm/components/Icons/TangentAutoIcon.js.map +1 -1
  94. package/dist/esm/components/Icons/TangentFreeIcon.js.map +1 -1
  95. package/dist/esm/components/Icons/TangentLinearIcon.js.map +1 -1
  96. package/dist/esm/components/Icons/TangentMirroredIcon.js.map +1 -1
  97. package/dist/esm/components/Icons/TangentStepIcon.js.map +1 -1
  98. package/dist/esm/components/Icons/TerminalIcon.js.map +1 -1
  99. package/dist/esm/components/Icons/TrashIcon.js.map +1 -1
  100. package/dist/esm/components/Icons/UndoIcon.js.map +1 -1
  101. package/dist/esm/components/Icons/UnlinkIcon.js.map +1 -1
  102. package/dist/esm/components/Icons/UnlockIcon.js.map +1 -1
  103. package/dist/esm/components/Icons/UploadIcon.js.map +1 -1
  104. package/dist/esm/components/Icons/UserIcon.js.map +1 -1
  105. package/dist/esm/components/Icons/UsersIcon.js.map +1 -1
  106. package/dist/esm/components/Icons/WarningIcon.js.map +1 -1
  107. package/dist/esm/components/Icons/ZoomFitIcon.js +32 -0
  108. package/dist/esm/components/Icons/ZoomFitIcon.js.map +1 -0
  109. package/dist/esm/components/Icons/ZoomInIcon.js.map +1 -1
  110. package/dist/esm/components/Icons/ZoomOutIcon.js.map +1 -1
  111. package/dist/esm/components/controls/CartesianPicker/CartesianPicker.js.map +1 -1
  112. package/dist/esm/components/controls/CartesianPicker/useCartesianInteraction.js.map +1 -1
  113. package/dist/esm/components/controls/CartesianPicker/useCartesianRenderer.js.map +1 -1
  114. package/dist/esm/components/controls/ColorPicker/AlphaSlider.js.map +1 -1
  115. package/dist/esm/components/controls/ColorPicker/ColorArea.js.map +1 -1
  116. package/dist/esm/components/controls/ColorPicker/ColorInputs.js.map +1 -1
  117. package/dist/esm/components/controls/ColorPicker/ColorPalette.js.map +1 -1
  118. package/dist/esm/components/controls/ColorPicker/ColorPicker.js.map +1 -1
  119. package/dist/esm/components/controls/ColorPicker/ColorPresets.js.map +1 -1
  120. package/dist/esm/components/controls/ColorPicker/ColorSwatch.js.map +1 -1
  121. package/dist/esm/components/controls/ColorPicker/EyeDropper.js.map +1 -1
  122. package/dist/esm/components/controls/ColorPicker/HueSlider.js.map +1 -1
  123. package/dist/esm/components/controls/ColorPicker/colorUtils.js.map +1 -1
  124. package/dist/esm/components/controls/ColorPicker/palettes/material.js.map +1 -1
  125. package/dist/esm/components/controls/ColorPicker/palettes/professional.js.map +1 -1
  126. package/dist/esm/components/controls/ColorPicker/palettes/tailwind.js.map +1 -1
  127. package/dist/esm/components/controls/ColorPicker/useColor.js.map +1 -1
  128. package/dist/esm/components/controls/Combobox/Combobox.js.map +1 -1
  129. package/dist/esm/components/controls/CurveEditor/CurveCanvas.js.map +1 -1
  130. package/dist/esm/components/controls/CurveEditor/CurveEditor.js.map +1 -1
  131. package/dist/esm/components/controls/CurveEditor/CurveToolbar.js.map +1 -1
  132. package/dist/esm/components/controls/CurveEditor/curvePresets.js.map +1 -1
  133. package/dist/esm/components/controls/CurveEditor/curveUtils.js.map +1 -1
  134. package/dist/esm/components/controls/CurveEditor/useCurveInteraction.js.map +1 -1
  135. package/dist/esm/components/controls/CurveEditor/useCurveRenderer.js.map +1 -1
  136. package/dist/esm/components/controls/FileTree/FileTree.js +7 -1
  137. package/dist/esm/components/controls/FileTree/FileTree.js.map +1 -1
  138. package/dist/esm/components/controls/FileTree/fileTreeIcons.js.map +1 -1
  139. package/dist/esm/components/controls/FileTree/fileTreeLabels.js.map +1 -1
  140. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js +1 -1
  141. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js.map +1 -1
  142. package/dist/esm/components/controls/FileUploader/FileUploader.js.map +1 -1
  143. package/dist/esm/components/controls/MultiSelect/MultiSelect.js.map +1 -1
  144. package/dist/esm/components/controls/NumberInput/NumberInput.js.map +1 -1
  145. package/dist/esm/components/controls/NumberInput/useNumberInput.js.map +1 -1
  146. package/dist/esm/components/controls/Select/Select.css.js +1 -1
  147. package/dist/esm/components/controls/Select/Select.js +15 -7
  148. package/dist/esm/components/controls/Select/Select.js.map +1 -1
  149. package/dist/esm/components/controls/Slider/Slider.css.js +10 -11
  150. package/dist/esm/components/controls/Slider/Slider.css.js.map +1 -1
  151. package/dist/esm/components/controls/Slider/Slider.js +40 -7
  152. package/dist/esm/components/controls/Slider/Slider.js.map +1 -1
  153. package/dist/esm/components/controls/TagInput/TagInput.js.map +1 -1
  154. package/dist/esm/components/controls/TreeView/TreeNode.js +6 -0
  155. package/dist/esm/components/controls/TreeView/TreeNode.js.map +1 -1
  156. package/dist/esm/components/controls/TreeView/TreeView.js.map +1 -1
  157. package/dist/esm/components/controls/TreeView/useTreeState.js.map +1 -1
  158. package/dist/esm/components/controls/VectorInput/VectorInput.js +6 -0
  159. package/dist/esm/components/controls/VectorInput/VectorInput.js.map +1 -1
  160. package/dist/esm/components/data/DataTable/DataTable.js.map +1 -1
  161. package/dist/esm/components/editor/AssetBrowser/AssetBrowser.js.map +1 -1
  162. package/dist/esm/components/editor/AssetBrowser/AssetBrowserAnnouncementLive.js.map +1 -1
  163. package/dist/esm/components/editor/AssetBrowser/AssetBrowserBreadcrumbs.js.map +1 -1
  164. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js +6 -0
  165. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js.map +1 -1
  166. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContext.js.map +1 -1
  167. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContextMenu.js.map +1 -1
  168. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js +6 -0
  169. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js.map +1 -1
  170. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js +1 -1
  171. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js.map +1 -1
  172. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js +6 -0
  173. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js.map +1 -1
  174. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js +6 -0
  175. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js.map +1 -1
  176. package/dist/esm/components/editor/AssetBrowser/AssetBrowserRenameField.js.map +1 -1
  177. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSidebar.js.map +1 -1
  178. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStatusBar.js.map +1 -1
  179. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStore.js.map +1 -1
  180. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js +6 -0
  181. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js.map +1 -1
  182. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js +6 -0
  183. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js.map +1 -1
  184. package/dist/esm/components/editor/AssetBrowser/assetBrowserFilter.js.map +1 -1
  185. package/dist/esm/components/editor/AssetBrowser/assetBrowserFormat.js.map +1 -1
  186. package/dist/esm/components/editor/AssetBrowser/assetBrowserGeometry.js.map +1 -1
  187. package/dist/esm/components/editor/AssetBrowser/assetBrowserKeyboard.js.map +1 -1
  188. package/dist/esm/components/editor/AssetBrowser/assetBrowserLabels.js.map +1 -1
  189. package/dist/esm/components/editor/AssetBrowser/slots.js.map +1 -1
  190. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserAnnouncement.js.map +1 -1
  191. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js +1 -1
  192. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js.map +1 -1
  193. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js +1 -1
  194. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js.map +1 -1
  195. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js +1 -1
  196. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js.map +1 -1
  197. package/dist/esm/components/editor/AssetBrowser/useAssetGridKeyboardNav.js.map +1 -1
  198. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js +1 -1
  199. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js.map +1 -1
  200. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js +1 -1
  201. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js.map +1 -1
  202. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js +1 -1
  203. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js.map +1 -1
  204. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js +1 -1
  205. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js.map +1 -1
  206. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js +1 -1
  207. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js.map +1 -1
  208. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js +1 -1
  209. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js.map +1 -1
  210. package/dist/esm/components/editor/ChatPanel/ChatActionBar.js.map +1 -1
  211. package/dist/esm/components/editor/ChatPanel/ChatAttachment.js.map +1 -1
  212. package/dist/esm/components/editor/ChatPanel/ChatBubble.js.map +1 -1
  213. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js +6 -0
  214. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js.map +1 -1
  215. package/dist/esm/components/editor/ChatPanel/ChatContextChip.js.map +1 -1
  216. package/dist/esm/components/editor/ChatPanel/ChatEmptyState.js.map +1 -1
  217. package/dist/esm/components/editor/ChatPanel/ChatIcons.js.map +1 -1
  218. package/dist/esm/components/editor/ChatPanel/ChatInput.js +6 -0
  219. package/dist/esm/components/editor/ChatPanel/ChatInput.js.map +1 -1
  220. package/dist/esm/components/editor/ChatPanel/ChatInputToolbar.js.map +1 -1
  221. package/dist/esm/components/editor/ChatPanel/ChatMarkdownRenderer.js.map +1 -1
  222. package/dist/esm/components/editor/ChatPanel/ChatMessage.js +6 -0
  223. package/dist/esm/components/editor/ChatPanel/ChatMessage.js.map +1 -1
  224. package/dist/esm/components/editor/ChatPanel/ChatMessageList.js.map +1 -1
  225. package/dist/esm/components/editor/ChatPanel/ChatPanel.js.map +1 -1
  226. package/dist/esm/components/editor/ChatPanel/ChatToolCall.js.map +1 -1
  227. package/dist/esm/components/editor/ChatPanel/ChatTypingIndicator.js.map +1 -1
  228. package/dist/esm/components/editor/ChatPanel/useChatInput.js.map +1 -1
  229. package/dist/esm/components/editor/ChatPanel/useChatMessages.js.map +1 -1
  230. package/dist/esm/components/editor/ChatPanel/useChatScroll.js.map +1 -1
  231. package/dist/esm/components/editor/Minimap/Minimap.js +1 -1
  232. package/dist/esm/components/editor/Minimap/Minimap.js.map +1 -1
  233. package/dist/esm/components/editor/Minimap/Minimap.types.js.map +1 -1
  234. package/dist/esm/components/editor/Minimap/MinimapContext.js.map +1 -1
  235. package/dist/esm/components/editor/Minimap/MinimapCorner.js.map +1 -1
  236. package/dist/esm/components/editor/Minimap/MinimapFooter.js.map +1 -1
  237. package/dist/esm/components/editor/Minimap/MinimapStore.js.map +1 -1
  238. package/dist/esm/components/editor/Minimap/MinimapTitle.js.map +1 -1
  239. package/dist/esm/components/editor/Minimap/ViewportMinimap.js +1 -1
  240. package/dist/esm/components/editor/Minimap/ViewportMinimap.js.map +1 -1
  241. package/dist/esm/components/editor/Minimap/computeBoundsFromItems.js.map +1 -1
  242. package/dist/esm/components/editor/Minimap/index.js.map +1 -1
  243. package/dist/esm/components/editor/Minimap/minimapCoords.js.map +1 -1
  244. package/dist/esm/components/editor/Minimap/minimapDrawing.js.map +1 -1
  245. package/dist/esm/components/editor/Minimap/minimapHitTest.js.map +1 -1
  246. package/dist/esm/components/editor/Minimap/useMinimapGestures.js +1 -1
  247. package/dist/esm/components/editor/Minimap/useMinimapGestures.js.map +1 -1
  248. package/dist/esm/components/editor/NodeGraph/NodeGraph.js +1 -1
  249. package/dist/esm/components/editor/NodeGraph/NodeGraph.js.map +1 -1
  250. package/dist/esm/components/editor/NodeGraph/NodeGraph.types.js.map +1 -1
  251. package/dist/esm/components/editor/NodeGraph/NodeGraphContext.js.map +1 -1
  252. package/dist/esm/components/editor/NodeGraph/NodeGraphEdgeLabels.js.map +1 -1
  253. package/dist/esm/components/editor/NodeGraph/NodeGraphGroup.js.map +1 -1
  254. package/dist/esm/components/editor/NodeGraph/NodeGraphMinimap.js.map +1 -1
  255. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js +1 -1
  256. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js.map +1 -1
  257. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeContext.js.map +1 -1
  258. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeParts.js.map +1 -1
  259. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js +1 -1
  260. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js.map +1 -1
  261. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSectionContext.js.map +1 -1
  262. package/dist/esm/components/editor/NodeGraph/NodeGraphPin.js.map +1 -1
  263. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js +1 -1
  264. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js.map +1 -1
  265. package/dist/esm/components/editor/NodeGraph/NodeGraphPortVisual.js.map +1 -1
  266. package/dist/esm/components/editor/NodeGraph/NodeGraphSlots.js.map +1 -1
  267. package/dist/esm/components/editor/NodeGraph/NodeGraphSpawnPalette.js.map +1 -1
  268. package/dist/esm/components/editor/NodeGraph/NodeGraphStore.js.map +1 -1
  269. package/dist/esm/components/editor/NodeGraph/NodeGraphToolbar.js.map +1 -1
  270. package/dist/esm/components/editor/NodeGraph/createTypeMatchValidator.js.map +1 -1
  271. package/dist/esm/components/editor/NodeGraph/nodeGraphActions.js.map +1 -1
  272. package/dist/esm/components/editor/NodeGraph/nodeGraphDrawing.js.map +1 -1
  273. package/dist/esm/components/editor/NodeGraph/nodeGraphIds.js.map +1 -1
  274. package/dist/esm/components/editor/NodeGraph/nodeGraphMath.js.map +1 -1
  275. package/dist/esm/components/editor/NodeGraph/sortSlots.js.map +1 -1
  276. package/dist/esm/components/editor/NodeGraph/useDragGesture.js.map +1 -1
  277. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js +1 -1
  278. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js.map +1 -1
  279. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js +1 -1
  280. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js.map +1 -1
  281. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js +1 -1
  282. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js.map +1 -1
  283. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js +1 -1
  284. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js.map +1 -1
  285. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js +1 -1
  286. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js.map +1 -1
  287. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js +1 -1
  288. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js.map +1 -1
  289. package/dist/esm/components/editor/NodeGraph/useStoreSlice.js.map +1 -1
  290. package/dist/esm/components/editor/PropertyInspector/PropertyGroup.js.map +1 -1
  291. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js +4 -3
  292. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js.map +1 -1
  293. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js +5 -4
  294. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js.map +1 -1
  295. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js +7 -6
  296. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js.map +1 -1
  297. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js +18 -3
  298. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js.map +1 -1
  299. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js +11 -10
  300. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js.map +1 -1
  301. package/dist/esm/components/editor/PropertyInspector/PropertySection.js +29 -21
  302. package/dist/esm/components/editor/PropertyInspector/PropertySection.js.map +1 -1
  303. package/dist/esm/components/editor/PropertyInspector/usePropertyUndo.js.map +1 -1
  304. package/dist/esm/components/editor/Timeline/Timeline.js +1 -1
  305. package/dist/esm/components/editor/Timeline/Timeline.js.map +1 -1
  306. package/dist/esm/components/editor/Timeline/Timeline.types.js.map +1 -1
  307. package/dist/esm/components/editor/Timeline/TimelineContext.js.map +1 -1
  308. package/dist/esm/components/editor/Timeline/TimelineFooter.js.map +1 -1
  309. package/dist/esm/components/editor/Timeline/TimelineMinimap.js +1 -1
  310. package/dist/esm/components/editor/Timeline/TimelineMinimap.js.map +1 -1
  311. package/dist/esm/components/editor/Timeline/TimelineStore.js.map +1 -1
  312. package/dist/esm/components/editor/Timeline/TimelineToolbar.js.map +1 -1
  313. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js +1 -1
  314. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js.map +1 -1
  315. package/dist/esm/components/editor/Timeline/TimelineTrackScale.js.map +1 -1
  316. package/dist/esm/components/editor/Timeline/index.js.map +1 -1
  317. package/dist/esm/components/editor/Timeline/timelineCoords.js.map +1 -1
  318. package/dist/esm/components/editor/Timeline/timelineDrawing.js.map +1 -1
  319. package/dist/esm/components/editor/Timeline/timelineEdits.js.map +1 -1
  320. package/dist/esm/components/editor/Timeline/timelineHitTest.js.map +1 -1
  321. package/dist/esm/components/editor/Timeline/timelineLayout.js.map +1 -1
  322. package/dist/esm/components/editor/Timeline/timelineSelection.js.map +1 -1
  323. package/dist/esm/components/editor/Timeline/useTimelineDraw.js +1 -1
  324. package/dist/esm/components/editor/Timeline/useTimelineDraw.js.map +1 -1
  325. package/dist/esm/components/editor/Timeline/useTimelineGestures.js +1 -1
  326. package/dist/esm/components/editor/Timeline/useTimelineGestures.js.map +1 -1
  327. package/dist/esm/components/editor/Timeline/useTimelinePlayback.js.map +1 -1
  328. package/dist/esm/components/editor/TransformControl/TransformControl.js.map +1 -1
  329. package/dist/esm/components/editor/ViewportGizmo/ViewportGizmo.js.map +1 -1
  330. package/dist/esm/components/editor/ViewportGizmo/gizmoMath.js.map +1 -1
  331. package/dist/esm/components/editor/ViewportGizmo/useGizmoInteraction.js.map +1 -1
  332. package/dist/esm/components/editor/ViewportGizmo/useGizmoRenderer.js.map +1 -1
  333. package/dist/esm/components/feedback/Alert/Alert.js.map +1 -1
  334. package/dist/esm/components/feedback/Alert/AlertActions.js.map +1 -1
  335. package/dist/esm/components/feedback/Alert/AlertDescription.js.map +1 -1
  336. package/dist/esm/components/feedback/Alert/AlertTitle.js.map +1 -1
  337. package/dist/esm/components/feedback/CommandPalette/CommandPalette.js.map +1 -1
  338. package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js.map +1 -1
  339. package/dist/esm/components/feedback/CommandPalette/useRecentItems.js.map +1 -1
  340. package/dist/esm/components/feedback/Dialog/Dialog.js.map +1 -1
  341. package/dist/esm/components/feedback/Dialog/DialogBody.js.map +1 -1
  342. package/dist/esm/components/feedback/Dialog/DialogClose.js.map +1 -1
  343. package/dist/esm/components/feedback/Dialog/DialogFooter.js.map +1 -1
  344. package/dist/esm/components/feedback/Dialog/DialogHeader.js.map +1 -1
  345. package/dist/esm/components/feedback/Dialog/useDialogAnimation.js.map +1 -1
  346. package/dist/esm/components/feedback/Drawer/Drawer.js.map +1 -1
  347. package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js.map +1 -1
  348. package/dist/esm/components/feedback/EmptyState/EmptyState.js.map +1 -1
  349. package/dist/esm/components/feedback/LogView/LogView.js.map +1 -1
  350. package/dist/esm/components/feedback/LogView/LogViewBody.js.map +1 -1
  351. package/dist/esm/components/feedback/LogView/LogViewContext.js.map +1 -1
  352. package/dist/esm/components/feedback/LogView/LogViewParts.js.map +1 -1
  353. package/dist/esm/components/feedback/LogView/LogViewStore.js.map +1 -1
  354. package/dist/esm/components/feedback/LogView/logViewLabels.js.map +1 -1
  355. package/dist/esm/components/feedback/LogView/logViewLevels.js.map +1 -1
  356. package/dist/esm/components/feedback/LogView/logViewUtils.js.map +1 -1
  357. package/dist/esm/components/feedback/LogView/useFollowTail.js.map +1 -1
  358. package/dist/esm/components/feedback/LogView/useLogSelection.js.map +1 -1
  359. package/dist/esm/components/feedback/ProgressBar/CircularProgress.js.map +1 -1
  360. package/dist/esm/components/feedback/ProgressBar/ProgressBar.js.map +1 -1
  361. package/dist/esm/components/feedback/Skeleton/Skeleton.js.map +1 -1
  362. package/dist/esm/components/feedback/Skeleton/SkeletonGroup.js.map +1 -1
  363. package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js.map +1 -1
  364. package/dist/esm/components/feedback/Spinner/Spinner.js +12 -3
  365. package/dist/esm/components/feedback/Spinner/Spinner.js.map +1 -1
  366. package/dist/esm/components/feedback/Stat/Stat.js.map +1 -1
  367. package/dist/esm/components/feedback/Toast/ToastContainer.js.map +1 -1
  368. package/dist/esm/components/feedback/Toast/ToastItem.js.map +1 -1
  369. package/dist/esm/components/feedback/Toast/ToastProvider.js.map +1 -1
  370. package/dist/esm/components/feedback/Toast/useToast.js.map +1 -1
  371. package/dist/esm/components/form/FormHelperText.js.map +1 -1
  372. package/dist/esm/components/form/FormLabel.js.map +1 -1
  373. package/dist/esm/components/form/InputWrapper.js.map +1 -1
  374. package/dist/esm/components/layout/Accordion/Accordion.js.map +1 -1
  375. package/dist/esm/components/layout/Accordion/AccordionContent.js.map +1 -1
  376. package/dist/esm/components/layout/Accordion/AccordionItem.js.map +1 -1
  377. package/dist/esm/components/layout/Accordion/AccordionTrigger.js.map +1 -1
  378. package/dist/esm/components/layout/Card/Card.js.map +1 -1
  379. package/dist/esm/components/layout/Divider/Divider.js.map +1 -1
  380. package/dist/esm/components/layout/Flex/Flex.js.map +1 -1
  381. package/dist/esm/components/layout/Grid/Grid.js.map +1 -1
  382. package/dist/esm/components/layout/ListItem/ListItem.js.map +1 -1
  383. package/dist/esm/components/layout/PageHeader/PageHeader.js.map +1 -1
  384. package/dist/esm/components/layout/PanelSurface/PanelSurface.js.map +1 -1
  385. package/dist/esm/components/layout/ScrollArea/ScrollArea.js.map +1 -1
  386. package/dist/esm/components/layout/Spacer/Spacer.js.map +1 -1
  387. package/dist/esm/components/layout/SplitPane/SplitPane.js.map +1 -1
  388. package/dist/esm/components/layout/SplitPane/SplitPanePanel.js.map +1 -1
  389. package/dist/esm/components/layout/Stack/Stack.js.map +1 -1
  390. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js.map +1 -1
  391. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js.map +1 -1
  392. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbSeparator.js.map +1 -1
  393. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js +6 -0
  394. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js.map +1 -1
  395. package/dist/esm/components/navigation/ContextMenu/ContextMenu.js +2 -2
  396. package/dist/esm/components/navigation/ContextMenu/ContextMenu.js.map +1 -1
  397. package/dist/esm/components/navigation/Menu/Menu.css.js +11 -10
  398. package/dist/esm/components/navigation/Menu/Menu.css.js.map +1 -1
  399. package/dist/esm/components/navigation/Menu/Menu.js +2 -2
  400. package/dist/esm/components/navigation/Menu/Menu.js.map +1 -1
  401. package/dist/esm/components/navigation/Menu/MenuGapContext.js.map +1 -1
  402. package/dist/esm/components/navigation/Pagination/Pagination.js.map +1 -1
  403. package/dist/esm/components/navigation/Pagination/usePagination.js.map +1 -1
  404. package/dist/esm/components/navigation/PathBar/PathBar.js +7 -1
  405. package/dist/esm/components/navigation/PathBar/PathBar.js.map +1 -1
  406. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js +6 -0
  407. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js.map +1 -1
  408. package/dist/esm/components/navigation/PathBar/pathUtils.js.map +1 -1
  409. package/dist/esm/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -1
  410. package/dist/esm/components/navigation/SegmentedControl/SegmentedControlItem.js.map +1 -1
  411. package/dist/esm/components/navigation/Tabs/Tab.js.map +1 -1
  412. package/dist/esm/components/navigation/Tabs/TabList.js.map +1 -1
  413. package/dist/esm/components/navigation/Tabs/TabPanel.js.map +1 -1
  414. package/dist/esm/components/navigation/Tabs/Tabs.js.map +1 -1
  415. package/dist/esm/components/primitives/Avatar/Avatar.js +6 -0
  416. package/dist/esm/components/primitives/Avatar/Avatar.js.map +1 -1
  417. package/dist/esm/components/primitives/Avatar/AvatarGroup.js.map +1 -1
  418. package/dist/esm/components/primitives/Badge/Badge.js +6 -0
  419. package/dist/esm/components/primitives/Badge/Badge.js.map +1 -1
  420. package/dist/esm/components/primitives/Button/Button.js.map +1 -1
  421. package/dist/esm/components/primitives/Checkbox/Checkbox.js.map +1 -1
  422. package/dist/esm/components/primitives/Checkbox/CheckboxGroup.js.map +1 -1
  423. package/dist/esm/components/primitives/Code/Code.js.map +1 -1
  424. package/dist/esm/components/primitives/Collapsible/Collapsible.js.map +1 -1
  425. package/dist/esm/components/primitives/HoverCard/HoverCard.js.map +1 -1
  426. package/dist/esm/components/primitives/Icon/Icon.js.map +1 -1
  427. package/dist/esm/components/primitives/IconButton/IconButton.js +4 -2
  428. package/dist/esm/components/primitives/IconButton/IconButton.js.map +1 -1
  429. package/dist/esm/components/primitives/Input/Input.js.map +1 -1
  430. package/dist/esm/components/primitives/Kbd/Kbd.js.map +1 -1
  431. package/dist/esm/components/primitives/Link/Link.js.map +1 -1
  432. package/dist/esm/components/primitives/Paper/Paper.js.map +1 -1
  433. package/dist/esm/components/primitives/Popover/Popover.js.map +1 -1
  434. package/dist/esm/components/primitives/Popover/PopoverClose.js.map +1 -1
  435. package/dist/esm/components/primitives/Popover/PopoverContent.js.map +1 -1
  436. package/dist/esm/components/primitives/Popover/PopoverTrigger.js.map +1 -1
  437. package/dist/esm/components/primitives/Radio/Radio.js.map +1 -1
  438. package/dist/esm/components/primitives/Radio/RadioGroup.js.map +1 -1
  439. package/dist/esm/components/primitives/Switch/Switch.js.map +1 -1
  440. package/dist/esm/components/primitives/Text/Text.js.map +1 -1
  441. package/dist/esm/components/primitives/TextArea/TextArea.js.map +1 -1
  442. package/dist/esm/components/primitives/Tooltip/Arrow.js.map +1 -1
  443. package/dist/esm/components/primitives/Tooltip/Tooltip.css.js +6 -5
  444. package/dist/esm/components/primitives/Tooltip/Tooltip.css.js.map +1 -1
  445. package/dist/esm/components/primitives/Tooltip/Tooltip.js +12 -2
  446. package/dist/esm/components/primitives/Tooltip/Tooltip.js.map +1 -1
  447. package/dist/esm/components/primitives/Tooltip/utils.js.map +1 -1
  448. package/dist/esm/components/primitives/VisuallyHidden/VisuallyHidden.js.map +1 -1
  449. package/dist/esm/components/primitives/canvas/CanvasContainer.js.map +1 -1
  450. package/dist/esm/components/primitives/canvas/canvasCoords.js.map +1 -1
  451. package/dist/esm/components/primitives/canvas/canvasDrawing.js.map +1 -1
  452. package/dist/esm/components/primitives/canvas/canvasTheme.js.map +1 -1
  453. package/dist/esm/components/primitives/canvas/useCanvasRenderer.js.map +1 -1
  454. package/dist/esm/components/primitives/viewport/Viewport.js +6 -3
  455. package/dist/esm/components/primitives/viewport/Viewport.js.map +1 -1
  456. package/dist/esm/components/primitives/viewport/ViewportContext.js.map +1 -1
  457. package/dist/esm/components/primitives/viewport/ViewportLayer.js +1 -1
  458. package/dist/esm/components/primitives/viewport/ViewportLayer.js.map +1 -1
  459. package/dist/esm/components/primitives/viewport/ViewportOverlay.js.map +1 -1
  460. package/dist/esm/components/primitives/viewport/ViewportStore.js.map +1 -1
  461. package/dist/esm/components/primitives/viewport/ViewportWorld.js.map +1 -1
  462. package/dist/esm/components/primitives/viewport/useViewportGestures.js +1 -1
  463. package/dist/esm/components/primitives/viewport/useViewportGestures.js.map +1 -1
  464. package/dist/esm/components/primitives/viewport/viewportCoords.js.map +1 -1
  465. package/dist/esm/components/primitives/viewport/viewportMath.js.map +1 -1
  466. package/dist/esm/components/shell/AppShell/AppShell.css.js +1 -1
  467. package/dist/esm/components/shell/AppShell/AppShell.js.map +1 -1
  468. package/dist/esm/components/shell/FloatingPanel/FloatingPanel.js.map +1 -1
  469. package/dist/esm/components/shell/MenuBar/MenuBar.css.js +7 -6
  470. package/dist/esm/components/shell/MenuBar/MenuBar.css.js.map +1 -1
  471. package/dist/esm/components/shell/MenuBar/MenuBar.js +52 -3
  472. package/dist/esm/components/shell/MenuBar/MenuBar.js.map +1 -1
  473. package/dist/esm/components/shell/StatusBar/StatusBar.js.map +1 -1
  474. package/dist/esm/components/shell/Toolbar/Toolbar.js.map +1 -1
  475. package/dist/esm/context/KeyboardContext.js.map +1 -1
  476. package/dist/esm/hooks/useBreakpoint/useBreakpoint.js.map +1 -1
  477. package/dist/esm/hooks/useClickOutside/useClickOutside.js.map +1 -1
  478. package/dist/esm/hooks/useClipboard/useClipboard.js.map +1 -1
  479. package/dist/esm/hooks/useControlledState/useControlledState.js.map +1 -1
  480. package/dist/esm/hooks/useDebounced/useDebouncedCallback.js.map +1 -1
  481. package/dist/esm/hooks/useDebounced/useDebouncedValue.js.map +1 -1
  482. package/dist/esm/hooks/useDisclosure/useDisclosure.js.map +1 -1
  483. package/dist/esm/hooks/useEventCallback/useEventCallback.js.map +1 -1
  484. package/dist/esm/hooks/useFocusTrap/useFocusTrap.js.map +1 -1
  485. package/dist/esm/hooks/useHotkey/useHotkey.js.map +1 -1
  486. package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js.map +1 -1
  487. package/dist/esm/hooks/useIsMounted/useIsMounted.js.map +1 -1
  488. package/dist/esm/hooks/useKeyboard/useKeyboard.js.map +1 -1
  489. package/dist/esm/hooks/useKeyboard/utils.js.map +1 -1
  490. package/dist/esm/hooks/useLatest/useLatest.js.map +1 -1
  491. package/dist/esm/hooks/useListboxNav/useListboxNav.js.map +1 -1
  492. package/dist/esm/hooks/useMediaQuery/useMediaQuery.js.map +1 -1
  493. package/dist/esm/hooks/useMergedRef/useMergedRef.js.map +1 -1
  494. package/dist/esm/hooks/useNavigationHistory/useNavigationHistory.js.map +1 -1
  495. package/dist/esm/hooks/useResizeObserver/useResizeObserver.js.map +1 -1
  496. package/dist/esm/hooks/useTheme/useTheme.js +1 -1
  497. package/dist/esm/hooks/useTheme/useTheme.js.map +1 -1
  498. package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js.map +1 -1
  499. package/dist/esm/index.js +6 -0
  500. package/dist/esm/index.js.map +1 -1
  501. package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
  502. package/dist/esm/styles.css.js +3 -0
  503. package/dist/esm/styles.css.js.map +1 -0
  504. package/dist/esm/theme/ThemeProvider.js +5 -3
  505. package/dist/esm/theme/ThemeProvider.js.map +1 -1
  506. package/dist/esm/theme/VanillaThemeProvider.js.map +1 -1
  507. package/dist/esm/theme/breakpoints.js.map +1 -1
  508. package/dist/esm/theme/createCustomTheme.js +1 -1
  509. package/dist/esm/theme/createCustomTheme.js.map +1 -1
  510. package/dist/esm/theme/createLightTheme.js.map +1 -1
  511. package/dist/esm/theme/darkThemeValues.js.map +1 -1
  512. package/dist/esm/theme/lightThemeValues.js.map +1 -1
  513. package/dist/esm/theme/themeContractData.js.map +1 -1
  514. package/dist/esm/utils/cx.js.map +1 -1
  515. package/dist/esm/utils/devWarn.js.map +1 -1
  516. package/dist/esm/utils/mathExpression.js.map +1 -1
  517. package/dist/esm/utils/mathUtils.js.map +1 -1
  518. package/dist/esm/utils/objects.js.map +1 -1
  519. package/dist/esm/utils/platform.js.map +1 -1
  520. package/dist/tokens/tokens.dark.css +1 -1
  521. package/dist/tokens/tokens.json +1 -1
  522. package/dist/tokens/tokens.light.css +1 -1
  523. package/dist/types/components/Icons/CameraIcon.d.ts +34 -0
  524. package/dist/types/components/Icons/CubeIcon.d.ts +34 -0
  525. package/dist/types/components/Icons/OrbitIcon.d.ts +34 -0
  526. package/dist/types/components/Icons/RotateIcon.d.ts +35 -0
  527. package/dist/types/components/Icons/SpinIcon.d.ts +35 -0
  528. package/dist/types/components/Icons/ZoomFitIcon.d.ts +35 -0
  529. package/dist/types/components/controls/Select/Select.d.ts +1 -1
  530. package/dist/types/components/controls/Select/Select.types.d.ts +43 -9
  531. package/dist/types/components/controls/Slider/Slider.d.ts +7 -0
  532. package/dist/types/components/editor/PropertyInspector/PropertyInspector.types.d.ts +49 -3
  533. package/dist/types/components/feedback/Spinner/Spinner.d.ts +6 -1
  534. package/dist/types/components/feedback/Spinner/Spinner.types.d.ts +8 -0
  535. package/dist/types/components/primitives/Button/Button.d.ts +1 -1
  536. package/dist/types/components/primitives/IconButton/IconButton.d.ts +3 -2
  537. package/dist/types/components/primitives/viewport/Viewport.d.ts +5 -2
  538. package/dist/types/components/shell/MenuBar/MenuBar.d.ts +862 -0
  539. package/dist/types/index.d.ts +6 -0
  540. package/dist/types/theme/ThemeProvider.d.ts +5 -3
  541. package/package.json +6 -2
  542. package/dist/esm/_virtual/_commonjsHelpers.js +0 -6
  543. package/dist/esm/_virtual/_commonjsHelpers.js.map +0 -1
  544. package/dist/esm/_virtual/cjs.js +0 -4
  545. package/dist/esm/_virtual/cjs.js.map +0 -1
  546. package/dist/esm/_virtual/cssesc.js +0 -8
  547. package/dist/esm/_virtual/cssesc.js.map +0 -1
  548. package/dist/esm/_virtual/picocolors.js +0 -8
  549. package/dist/esm/_virtual/picocolors.js.map +0 -1
  550. package/dist/esm/_virtual/picocolors2.js +0 -4
  551. package/dist/esm/_virtual/picocolors2.js.map +0 -1
  552. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js +0 -56
  553. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +0 -1
  554. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js +0 -46
  555. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js.map +0 -1
  556. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js +0 -13
  557. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js.map +0 -1
  558. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js +0 -962
  559. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js.map +0 -1
  560. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js +0 -309
  561. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js.map +0 -1
  562. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js +0 -18
  563. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js.map +0 -1
  564. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js +0 -23
  565. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js.map +0 -1
  566. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js +0 -1543
  567. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js.map +0 -1
  568. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js +0 -38
  569. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js.map +0 -1
  570. package/dist/esm/node_modules/css-what/lib/es/parse.js +0 -424
  571. package/dist/esm/node_modules/css-what/lib/es/parse.js.map +0 -1
  572. package/dist/esm/node_modules/css-what/lib/es/types.js +0 -29
  573. package/dist/esm/node_modules/css-what/lib/es/types.js.map +0 -1
  574. package/dist/esm/node_modules/cssesc/cssesc.js +0 -120
  575. package/dist/esm/node_modules/cssesc/cssesc.js.map +0 -1
  576. package/dist/esm/node_modules/dedent/dist/dedent.js +0 -100
  577. package/dist/esm/node_modules/dedent/dist/dedent.js.map +0 -1
  578. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js +0 -40
  579. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js.map +0 -1
  580. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js +0 -9
  581. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js.map +0 -1
  582. package/dist/esm/node_modules/deepmerge/dist/cjs.js +0 -143
  583. package/dist/esm/node_modules/deepmerge/dist/cjs.js.map +0 -1
  584. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js +0 -1386
  585. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js.map +0 -1
  586. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js +0 -102
  587. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js.map +0 -1
  588. package/dist/esm/node_modules/picocolors/picocolors.js +0 -87
  589. package/dist/esm/node_modules/picocolors/picocolors.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pathUtils.js","sources":["../../../../../../src/components/navigation/PathBar/pathUtils.ts"],"sourcesContent":[null],"names":[],"mappings":"AAEA;;;;;AAKG;AAEI,MAAM,iBAAiB,GAAG;AAUjC;AACA,SAAS,WAAW,CAAC,IAAY,EAAE,SAAiB,EAAA;;AAElD,IAAA,IAAI,SAAS,KAAK,EAAE,EAAE;AACpB,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE;IACtC;AACA,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D;AAEA;AACA,SAAS,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAA;IACjD,OAAO,SAAS,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;AACvD;AAEA;;;;;;;;AAQG;AACG,SAAU,QAAQ,CACtB,MAAyB,EACzB,KAAa,EACb,SAAA,GAAoB,iBAAiB,EACrC,QAAQ,GAAG,KAAK,EAAA;IAEhB,MAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,EAAE;AACxC,IAAA,OAAO,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5D;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACG,SAAU,aAAa,CAAC,OAA4B,EAAA;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;AAC5E;AAEA;;;;;;;;;;;AAWG;SACa,SAAS,CACvB,IAAY,EACZ,YAAoB,iBAAiB,EAAA;IAErC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;IAC5C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,MAAM;QACnC,KAAK;QACL,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AACpD,KAAA,CAAC,CAAC;AACL;AAEA;;;;;;;;;AASG;SACa,aAAa,CAC3B,KAAgB,EAChB,YAAoB,iBAAiB,EAAA;AAErC,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,OAAO,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC;IACpC;IAEA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,IAC5B,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,CAChD;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AAChC,QAAA,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK;QACtD,OAAO;AACL,YAAA,GAAG,OAAO;AACV,YAAA,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;SAC3D;AACH,IAAA,CAAC,CAAC;AACJ;AAEA;;;;;;;;AAQG;AACG,SAAU,eAAe,CAC7B,MAA2B,EAC3B,OAA4C,EAAA;AAE5C,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;AACpC,IAAA,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAG;AACzB,QAAA,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK;QACtD,OAAO;AACL,YAAA,GAAG,OAAO;YACV,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,GAAG,OAAO,CAAC,KAAK;SAC/C;AACH,IAAA,CAAC,CAAC;AACJ;;;;"}
1
+ {"version":3,"file":"pathUtils.js","sources":["src/components/navigation/PathBar/pathUtils.ts"],"sourcesContent":["import type { PathInput, PathSegment } from './PathBar.types';\n\n/**\n * Pure helpers for turning file-path-like input into breadcrumb segments.\n *\n * No React, no DOM — safe to unit test in isolation and import without a\n * `'use client'` boundary.\n */\n\nexport const DEFAULT_DELIMITER = '/';\n\n/**\n * A segment whose navigation `value` has been resolved. PathBar works with\n * these internally so every crumb is guaranteed a stable path to navigate to.\n */\nexport interface ResolvedPathSegment extends PathSegment {\n value: string;\n}\n\n/** Split a raw string path into its non-empty label parts. */\nfunction splitLabels(path: string, delimiter: string): string[] {\n // An empty delimiter cannot split — treat the whole string as one label.\n if (delimiter === '') {\n return path.length > 0 ? [path] : [];\n }\n return path.split(delimiter).filter(part => part.length > 0);\n}\n\n/** True when a string path begins with the delimiter (an absolute path). */\nfunction isAbsolute(path: string, delimiter: string): boolean {\n return delimiter !== '' && path.startsWith(delimiter);\n}\n\n/**\n * Build the cumulative navigation value for the segment at `index`: the path\n * from the root up to and including that segment.\n *\n * @param labels Ordered segment labels.\n * @param index Index of the segment whose value is wanted.\n * @param delimiter Joiner placed between labels.\n * @param absolute When true, the result keeps a leading delimiter.\n */\nexport function joinPath(\n labels: readonly string[],\n index: number,\n delimiter: string = DEFAULT_DELIMITER,\n absolute = false\n): string {\n const prefix = absolute ? delimiter : '';\n return prefix + labels.slice(0, index + 1).join(delimiter);\n}\n\n/**\n * The path prefix of a resolved segment — its `value` with the trailing label\n * removed. Useful for building a sibling's value: it shares this prefix and\n * only swaps the final label. Works for absolute paths (the leading delimiter\n * stays in the prefix) and relative ones alike.\n *\n * @example\n * segmentPrefix({ label: 'src', value: '/src' }) // '/'\n * segmentPrefix({ label: 'b', value: 'a/b' }) // 'a/'\n * segmentPrefix({ label: 'src', value: 'src' }) // ''\n *\n * @remarks\n * Assumes `value` ends with `label` — always true for parsed paths and for\n * cumulative array values. If a consumer supplies a structured segment whose\n * `value` is unrelated to its `label`, the derived prefix is meaningless; in\n * that case provide explicit `value`s on that segment's siblings too so they\n * don't fall back to this prefix.\n */\nexport function segmentPrefix(segment: ResolvedPathSegment): string {\n return segment.value.slice(0, segment.value.length - segment.label.length);\n}\n\n/**\n * Parse a raw string path into resolved segments. Each segment carries the\n * cumulative `value` (the path up to and including it).\n *\n * Normalization rules:\n * - A leading delimiter marks the path absolute; resolved values keep it.\n * - Trailing delimiters and doubled delimiters collapse (empty parts dropped).\n * - An empty string (or a string of only delimiters) yields `[]`.\n *\n * Windows-style `\\` separators are out of scope for v1 — pass\n * `delimiter=\"\\\\\"` explicitly if a consumer needs them.\n */\nexport function parsePath(\n path: string,\n delimiter: string = DEFAULT_DELIMITER\n): ResolvedPathSegment[] {\n const labels = splitLabels(path, delimiter);\n const absolute = isAbsolute(path, delimiter);\n return labels.map((label, index) => ({\n label,\n value: joinPath(labels, index, delimiter, absolute),\n }));\n}\n\n/**\n * Normalize the public path input (a delimited string, or an array of strings\n * / `PathSegment` objects) into resolved segments with a guaranteed `value`.\n *\n * - String input is delegated to {@link parsePath}.\n * - Array entries that already provide a `value` keep it; otherwise the\n * cumulative path is computed from the labels (relative — array input\n * carries no leading-delimiter information).\n * - Per-segment `icon` is preserved.\n */\nexport function normalizePath(\n input: PathInput,\n delimiter: string = DEFAULT_DELIMITER\n): ResolvedPathSegment[] {\n if (typeof input === 'string') {\n return parsePath(input, delimiter);\n }\n\n const labels = input.map(entry =>\n typeof entry === 'string' ? entry : entry.label\n );\n\n return input.map((entry, index) => {\n const segment: PathSegment =\n typeof entry === 'string' ? { label: entry } : entry;\n return {\n ...segment,\n value: segment.value ?? joinPath(labels, index, delimiter),\n };\n });\n}\n\n/**\n * Resolve a `getSiblings` result into segments with concrete navigation\n * values. A sibling lives in the same parent as `anchor`, so it inherits that\n * segment's prefix (see {@link segmentPrefix}) and only swaps the trailing\n * label. Entries that already carry an explicit `value` keep it.\n *\n * @param anchor The resolved segment the siblings sit beside.\n * @param entries Raw sibling entries — plain labels or structured segments.\n */\nexport function resolveSiblings(\n anchor: ResolvedPathSegment,\n entries: ReadonlyArray<string | PathSegment>\n): ResolvedPathSegment[] {\n const prefix = segmentPrefix(anchor);\n return entries.map(entry => {\n const segment: PathSegment =\n typeof entry === 'string' ? { label: entry } : entry;\n return {\n ...segment,\n value: segment.value ?? prefix + segment.label,\n };\n });\n}\n"],"names":[],"mappings":"AAEA;;;;;AAKG;AAEI,MAAM,iBAAiB,GAAG;AAUjC;AACA,SAAS,WAAW,CAAC,IAAY,EAAE,SAAiB,EAAA;;AAElD,IAAA,IAAI,SAAS,KAAK,EAAE,EAAE;AACpB,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE;IACtC;AACA,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D;AAEA;AACA,SAAS,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAA;IACjD,OAAO,SAAS,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;AACvD;AAEA;;;;;;;;AAQG;AACG,SAAU,QAAQ,CACtB,MAAyB,EACzB,KAAa,EACb,SAAA,GAAoB,iBAAiB,EACrC,QAAQ,GAAG,KAAK,EAAA;IAEhB,MAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,EAAE;AACxC,IAAA,OAAO,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5D;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACG,SAAU,aAAa,CAAC,OAA4B,EAAA;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;AAC5E;AAEA;;;;;;;;;;;AAWG;SACa,SAAS,CACvB,IAAY,EACZ,YAAoB,iBAAiB,EAAA;IAErC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;IAC5C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,MAAM;QACnC,KAAK;QACL,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AACpD,KAAA,CAAC,CAAC;AACL;AAEA;;;;;;;;;AASG;SACa,aAAa,CAC3B,KAAgB,EAChB,YAAoB,iBAAiB,EAAA;AAErC,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,OAAO,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC;IACpC;IAEA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,IAC5B,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,CAChD;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AAChC,QAAA,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK;QACtD,OAAO;AACL,YAAA,GAAG,OAAO;AACV,YAAA,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;SAC3D;AACH,IAAA,CAAC,CAAC;AACJ;AAEA;;;;;;;;AAQG;AACG,SAAU,eAAe,CAC7B,MAA2B,EAC3B,OAA4C,EAAA;AAE5C,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;AACpC,IAAA,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAG;AACzB,QAAA,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK;QACtD,OAAO;AACL,YAAA,GAAG,OAAO;YACV,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,GAAG,OAAO,CAAC,KAAK;SAC/C;AACH,IAAA,CAAC,CAAC;AACJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.js","sources":["../../../../../../src/components/navigation/SegmentedControl/SegmentedControl.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AA2BA;AAEA;AACE;;AAGA;;AAEE;;AAIF;AACF;AAWA;;;AAOE;AACA;AACA;AACA;AAEA;AACE;;;;AAII;;AAEA;;;;;;;AAOF;;;;;;AAON;AAEA;AAEA;AAGA;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACI;;AAoBL;;AAGA;;;;AAKI;AACE;;;;AAQN;;AAGA;AAEI;AACA;;;;AAGE;;AAEJ;;;;;;AASI;;;;;;AAWN;AACE;;;;;;;;;;;;AAaA;;;;;;AAMF;;;;;;;;;AASC;;;;;AAMC;AACA;;AACA;AAKA;;AAIE;;AAEJ;;;;;AAKE;AACA;;AAEA;;AAEI;AACF;AACA;AACA;AACE;AACF;;AAGF;AACE;AACF;AACA;AACA;AACE;AACF;AACA;;AAEA;AACF;;AAIA;AAEI;AACA;;AAEA;;;AAIA;;;AAIE;AACF;;AAEA;AAKA;;AAEA;;AAGA;AACA;AACE;;;AAGM;AACA;;AAEN;AACE;;AAEF;;;AAGA;AACE;;AAEF;;;;AAKF;;;;AAIE;;;;AAIJ;;AAMF;AAEI;;;;;;AAMA;;AAED;;;;;;;;;AAUA;;AAKH;;AAuBY;AACA;;AAED;AAOb;AAEA;;"}
1
+ {"version":3,"file":"SegmentedControl.js","sources":["src/components/navigation/SegmentedControl/SegmentedControl.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n segmentedControlRecipe,\n segmentedIndicatorRecipe,\n} from './SegmentedControl.css';\n\nimport type {\n SegmentedControlContextValue,\n SegmentedControlOrientation,\n SegmentedControlProps,\n SegmentedControlVariant,\n} from './SegmentedControl.types';\n\n// --- Context ---\n\nconst SegmentedControlContext =\n /*#__PURE__*/ createContext<SegmentedControlContextValue | null>(null);\n\nexport function useSegmentedControlContext(): SegmentedControlContextValue {\n const ctx = useContext(SegmentedControlContext);\n if (!ctx) {\n throw new Error(\n 'SegmentedControlItem must be used within <SegmentedControl>'\n );\n }\n return ctx;\n}\n\n// --- Indicator geometry helpers ---\n\ninterface IndicatorRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nfunction computeIndicatorRect(\n itemEl: HTMLElement,\n variant: SegmentedControlVariant,\n orientation: SegmentedControlOrientation\n): IndicatorRect {\n // Use offsetLeft/offsetTop (padding-box-relative) so the indicator\n // aligns with the absolutely-positioned reference frame inside the root.\n const x = itemEl.offsetLeft;\n const y = itemEl.offsetTop;\n const width = itemEl.offsetWidth;\n const height = itemEl.offsetHeight;\n\n if (variant === 'outline') {\n if (orientation === 'horizontal') {\n // 2px bar at the bottom of the item\n return {\n x,\n y: y + height - 2,\n width,\n height: 2,\n };\n }\n // vertical: 2px bar at the left of the item\n return {\n x,\n y,\n width: 2,\n height,\n };\n }\n\n // subtle / solid: full-segment background\n return { x, y, width, height };\n}\n\n// --- Use isomorphic layout effect for SSR safety ---\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\n// --- Component ---\n\n/**\n * SegmentedControl — toolbar-density mutually exclusive selector.\n *\n * Use when you have 2-5 mutually exclusive states without separate panels\n * (viewport mode, list/grid toggle, alignment). For content panels use Tabs;\n * for form-style selection use RadioGroup.\n *\n * Compound API: pair `SegmentedControl` with `SegmentedControlItem`.\n *\n * @example\n * ```tsx\n * <SegmentedControl defaultValue=\"day\">\n * <SegmentedControlItem value=\"day\">Day</SegmentedControlItem>\n * <SegmentedControlItem value=\"week\">Week</SegmentedControlItem>\n * <SegmentedControlItem value=\"month\">Month</SegmentedControlItem>\n * </SegmentedControl>\n * ```\n */\nexport const SegmentedControl: React.FC<SegmentedControlProps> = ({\n value: valueProp,\n defaultValue,\n size = 'md',\n orientation = 'horizontal',\n variant = 'subtle',\n fullWidth = false,\n disabled = false,\n onChange,\n children,\n className,\n style,\n testId,\n ref,\n 'aria-label': ariaLabel = 'Segmented control',\n ...rest\n}) => {\n const [internalValue, setInternalValue] = useState<string | undefined>(\n defaultValue\n );\n const isControlled = valueProp !== undefined;\n const activeValue = isControlled ? valueProp : internalValue;\n\n const setActiveValue = useCallback(\n (next: string) => {\n if (!isControlled) {\n setInternalValue(next);\n }\n if (next !== activeValue) {\n onChange?.(next);\n }\n },\n [isControlled, onChange, activeValue]\n );\n\n // --- Item registry for sliding indicator ---\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n const itemsRef = useRef<Map<string, HTMLElement>>(new Map());\n\n const setRootRef = useCallback(\n (node: HTMLDivElement | null) => {\n rootRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n const registerItem = useCallback(\n (itemValue: string, node: HTMLElement | null) => {\n if (node) {\n itemsRef.current.set(itemValue, node);\n } else {\n itemsRef.current.delete(itemValue);\n }\n },\n []\n );\n\n // --- Sliding indicator state ---\n\n const [indicator, setIndicator] = useState<IndicatorRect | null>(null);\n const [hasMeasured, setHasMeasured] = useState(false);\n\n const updateIndicator = useCallback(() => {\n if (activeValue === undefined) {\n setIndicator(null);\n return;\n }\n const item = itemsRef.current.get(activeValue);\n if (!item) {\n setIndicator(null);\n return;\n }\n setIndicator(computeIndicatorRect(item, variant, orientation));\n }, [activeValue, variant, orientation]);\n\n useIsomorphicLayoutEffect(() => {\n updateIndicator();\n // After first measure flip the flag so the indicator can transition on\n // subsequent updates instead of animating from (0,0).\n if (!hasMeasured) {\n setHasMeasured(true);\n }\n }, [\n updateIndicator,\n activeValue,\n variant,\n orientation,\n size,\n fullWidth,\n children,\n hasMeasured,\n ]);\n\n // Roving-tabindex fallback: when no item matches activeValue, the group\n // is otherwise unreachable via Tab. Promote the first non-disabled item\n // to tabIndex=0 so users can enter the group with the keyboard.\n useIsomorphicLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const items = Array.from(\n root.querySelectorAll<HTMLButtonElement>(\n '[data-segmented-item=\"true\"]:not([data-disabled=\"true\"])'\n )\n );\n const hasSelected = items.some(\n el => el.getAttribute('aria-pressed') === 'true'\n );\n if (!hasSelected && items[0]) {\n items[0].tabIndex = 0;\n }\n }, [activeValue, children]);\n\n // Re-measure on resize\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const root = rootRef.current;\n if (!root) return;\n\n if (typeof ResizeObserver === 'undefined') {\n const onResize = () => {\n updateIndicator();\n };\n window.addEventListener('resize', onResize);\n return () => {\n window.removeEventListener('resize', onResize);\n };\n }\n\n const ro = new ResizeObserver(() => {\n updateIndicator();\n });\n ro.observe(root);\n itemsRef.current.forEach(node => {\n ro.observe(node);\n });\n return () => {\n ro.disconnect();\n };\n }, [updateIndicator]);\n\n // --- Keyboard navigation (roving) ---\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n const root = rootRef.current;\n if (!root) return;\n\n const isHorizontal = orientation === 'horizontal';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n\n const isNavKey =\n e.key === nextKey ||\n e.key === prevKey ||\n e.key === 'Home' ||\n e.key === 'End';\n if (!isNavKey) return;\n\n const items = Array.from(\n root.querySelectorAll<HTMLButtonElement>(\n '[data-segmented-item=\"true\"]:not([data-disabled=\"true\"])'\n )\n );\n if (items.length === 0) return;\n\n const current = e.target as HTMLButtonElement;\n const currentIndex = items.indexOf(current);\n\n let nextIndex: number;\n switch (e.key) {\n case nextKey:\n nextIndex =\n currentIndex === -1 || currentIndex === items.length - 1\n ? 0\n : currentIndex + 1;\n break;\n case prevKey:\n nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = items.length - 1;\n break;\n default:\n return;\n }\n\n e.preventDefault();\n const target = items[nextIndex];\n if (target) {\n target.focus();\n const nextValue = target.dataset['value'];\n if (nextValue !== undefined) {\n setActiveValue(nextValue);\n }\n }\n },\n [orientation, setActiveValue]\n );\n\n // --- Context value ---\n\n const contextValue = useMemo<SegmentedControlContextValue>(\n () => ({\n value: activeValue,\n size,\n variant,\n orientation,\n disabled,\n fullWidth,\n onChange: setActiveValue,\n registerItem,\n }),\n [\n activeValue,\n size,\n variant,\n orientation,\n disabled,\n fullWidth,\n setActiveValue,\n registerItem,\n ]\n );\n\n const indicatorClass = segmentedIndicatorRecipe({ variant, orientation });\n\n return (\n <SegmentedControlContext.Provider value={contextValue}>\n <div\n ref={setRootRef}\n role=\"toolbar\"\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-orientation={orientation}\n className={cx(\n segmentedControlRecipe({ orientation, variant, fullWidth }),\n className\n )}\n style={style}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {indicator && (\n <span\n aria-hidden=\"true\"\n className={indicatorClass}\n style={{\n transform: `translate(${indicator.x}px, ${indicator.y}px)`,\n width: `${indicator.width}px`,\n height: `${indicator.height}px`,\n opacity: hasMeasured ? 1 : 0,\n }}\n />\n )}\n {children}\n </div>\n </SegmentedControlContext.Provider>\n );\n};\n\nSegmentedControl.displayName = 'SegmentedControl';\n"],"names":[],"mappings":";;;;;;AA2BA;AAEA;AACE;;AAGA;;AAEE;;AAIF;AACF;AAWA;;;AAOE;AACA;AACA;AACA;AAEA;AACE;;;;AAII;;AAEA;;;;;;;AAOF;;;;;;AAON;AAEA;AAEA;AAGA;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACI;;AAoBL;;AAGA;;;;AAKI;AACE;;;;AAQN;;AAGA;AAEI;AACA;;;;AAGE;;AAEJ;;;;;;AASI;;;;;;AAWN;AACE;;;;;;;;;;;;AAaA;;;;;;AAMF;;;;;;;;;AASC;;;;;AAMC;AACA;;AACA;AAKA;;AAIE;;AAEJ;;;;;AAKE;AACA;;AAEA;;AAEI;AACF;AACA;AACA;AACE;AACF;;AAGF;AACE;AACF;AACA;AACA;AACE;AACF;AACA;;AAEA;AACF;;AAIA;AAEI;AACA;;AAEA;;;AAIA;;;AAIE;AACF;;AAEA;AAKA;;AAEA;;AAGA;AACA;AACE;;;AAGM;AACA;;AAEN;AACE;;AAEF;;;AAGA;AACE;;AAEF;;;;AAKF;;;;AAIE;;;;AAIJ;;AAMF;AAEI;;;;;;AAMA;;AAED;;;;;;;;;AAUA;;AAKH;;AAuBY;AACA;;AAED;AAOb;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControlItem.js","sources":["../../../../../../src/components/navigation/SegmentedControl/SegmentedControlItem.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAqBA;;AAEI;AACE;AACF;AACE;AACF;AACA;AACE;;AAEN;AAEA;;;;;AAKG;AACI;;AAyBL;AACA;AACA;;AAIA;AACA;;;;;;;AASQ;;AAGR;;;;;;AAOA;AACA;AAEI;AACA;AACF;;AAKA;AACE;AACF;AACF;AAEA;AAEI;;;AAEA;;;AAMJ;AACA;AAGA;;AAkBQ;;AAED;;;;AAoBD;;;AAOR;AAEA;;"}
1
+ {"version":3,"file":"SegmentedControlItem.js","sources":["src/components/navigation/SegmentedControl/SegmentedControlItem.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback, useEffect, useRef } from 'react';\n\nimport { Tooltip } from '@/components/primitives/Tooltip/Tooltip';\nimport { cx } from '@/utils/cx';\nimport { devWarn } from '@/utils/devWarn';\n\nimport { useSegmentedControlContext } from './SegmentedControl';\nimport {\n itemOutlineStyle,\n itemSolidStyle,\n itemSubtleStyle,\n segmentedItemBaseStyle,\n segmentedItemIconStyle,\n segmentedItemRecipe,\n segmentedItemWrapperRecipe,\n} from './SegmentedControl.css';\n\nimport type { SegmentedControlItemProps } from './SegmentedControl.types';\n\nfunction getVariantClass(variant: 'subtle' | 'solid' | 'outline'): string {\n switch (variant) {\n case 'solid':\n return itemSolidStyle;\n case 'outline':\n return itemOutlineStyle;\n case 'subtle':\n default:\n return itemSubtleStyle;\n }\n}\n\n/**\n * Individual segment inside a `SegmentedControl`.\n *\n * Supports text, icon-only, or icon + label segments. Pair icon-only\n * segments with a `tooltip` so the action remains discoverable.\n */\nexport const SegmentedControlItem: React.FC<SegmentedControlItemProps> = ({\n value,\n children,\n icon,\n tooltip,\n disabled: itemDisabled = false,\n className,\n style,\n testId,\n onClick,\n onFocus,\n ref,\n ...rest\n}) => {\n const {\n value: activeValue,\n size,\n variant,\n orientation,\n disabled: groupDisabled,\n fullWidth,\n onChange,\n registerItem,\n } = useSegmentedControlContext();\n\n const isSelected = activeValue === value;\n const isDisabled = groupDisabled || itemDisabled;\n const hasLabel =\n children !== undefined && children !== null && children !== '';\n const isIconOnly = !hasLabel && Boolean(icon);\n\n const ariaLabelProp = rest['aria-label'];\n const ariaLabelledByProp = rest['aria-labelledby'];\n\n // Warn when an icon-only segment has no accessible name. Runs in an\n // effect so it does not fire from the render path (which would double in\n // StrictMode and on every rerender).\n useEffect(() => {\n if (isIconOnly && !tooltip && !ariaLabelProp && !ariaLabelledByProp) {\n devWarn(\n `[SegmentedControl] Icon-only segment \"${value}\" has no tooltip or aria-label. ` +\n 'Add a tooltip prop or aria-label so the segment is accessible.'\n );\n }\n }, [isIconOnly, tooltip, ariaLabelProp, ariaLabelledByProp, value]);\n\n // Wrapper ref: this is the direct child of the SegmentedControl root and\n // the measurement target for the sliding indicator. When `tooltip` is set\n // the Tooltip introduces its own positioned wrapper between us and the\n // button, which is why measuring the button itself would yield (0, 0)\n // relative to that intermediate wrapper.\n const wrapperRef = useRef<HTMLSpanElement | null>(null);\n const setWrapperRef = useCallback(\n (node: HTMLSpanElement | null) => {\n wrapperRef.current = node;\n registerItem(value, node);\n },\n [registerItem, value]\n );\n\n useEffect(() => {\n return () => {\n registerItem(value, null);\n };\n }, [registerItem, value]);\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n onChange(value);\n onClick?.(e);\n },\n [isDisabled, onChange, value, onClick]\n );\n\n // Resolve aria-label fallback for icon-only segments\n const tooltipString = typeof tooltip === 'string' ? tooltip : undefined;\n const resolvedAriaLabel =\n ariaLabelProp ?? (isIconOnly ? tooltipString : undefined);\n\n const button = (\n <button\n ref={ref}\n type=\"button\"\n data-segmented-item=\"true\"\n data-value={value}\n data-disabled={isDisabled || undefined}\n aria-pressed={isSelected}\n aria-disabled={isDisabled || undefined}\n aria-label={resolvedAriaLabel}\n tabIndex={isSelected && !isDisabled ? 0 : -1}\n disabled={isDisabled}\n onClick={handleClick}\n onFocus={onFocus}\n className={cx(\n segmentedItemBaseStyle,\n segmentedItemRecipe({\n size,\n iconOnly: isIconOnly,\n orientation,\n }),\n getVariantClass(variant),\n className\n )}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {icon && <span className={segmentedItemIconStyle}>{icon}</span>}\n {hasLabel && <span>{children}</span>}\n </button>\n );\n\n return (\n <span\n ref={setWrapperRef}\n data-segmented-item-wrapper=\"true\"\n className={segmentedItemWrapperRecipe({\n fullWidth,\n orientation,\n iconOnly: isIconOnly,\n size,\n })}\n >\n {tooltip ? <Tooltip title={tooltip}>{button}</Tooltip> : button}\n </span>\n );\n};\n\nSegmentedControlItem.displayName = 'SegmentedControlItem';\n"],"names":[],"mappings":";;;;;;;;;AAqBA;;AAEI;AACE;AACF;AACE;AACF;AACA;AACE;;AAEN;AAEA;;;;;AAKG;AACI;;AAyBL;AACA;AACA;;AAIA;AACA;;;;;;;AASQ;;AAGR;;;;;;AAOA;AACA;AAEI;AACA;AACF;;AAKA;AACE;AACF;AACF;AAEA;AAEI;;;AAEA;;;AAMJ;AACA;AAGA;;AAkBQ;;AAED;;;;AAoBD;;;AAOR;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.js","sources":["../../../../../../src/components/navigation/Tabs/Tab.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAqCA;AACE;AACA;AACA;;AAGF;AAEA;;AAMI;AACE;;AAKM;AACA;;AAGR;AACE;AAIF;AACE;;AAIM;AACA;;AAGR;AACE;;AAEN;AAEA;AAEO;AAaL;AASA;AACA;AACA;AAEA;AACA;AAEA;;;;;AAMA;AAEI;;;;;;;;;;AAUF;AAIF;;AAGI;AACF;AAIF;AAEI;;;AAGE;;AAEJ;;AAMF;AAmBM;AACA;AACD;AAQK;AACA;;AAqBZ;AAEA;;"}
1
+ {"version":3,"file":"Tab.js","sources":["src/components/navigation/Tabs/Tab.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { CloseIcon } from '@/components/Icons/CloseIcon';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport { useTabsContext } from './Tabs';\nimport {\n tabBaseStyle,\n tabRecipe,\n tabUnderlineStyle,\n tabUnderlineActiveStyle,\n tabUnderlineInactiveStyle,\n tabUnderlineActiveHorizontalStyle,\n tabUnderlineActiveVerticalStyle,\n tabUnderlineInactiveIndicatorStyle,\n tabPillsStyle,\n tabPillsActiveStyle,\n tabPillsInactiveStyle,\n tabEnclosedStyle,\n tabEnclosedActiveHorizontalStyle,\n tabEnclosedActiveVerticalStyle,\n tabEnclosedInactiveStyle,\n tabIconStyle,\n tabCloseButtonStyle,\n} from './Tabs.css';\n\nimport type { TabProps, TabsSize } from './Tabs.types';\n\n// --- Size maps ---\n\ninterface TabSizeConfig {\n iconSize: number;\n}\n\nconst TAB_SIZE_MAP: Record<TabsSize, TabSizeConfig> = {\n sm: { iconSize: 11 },\n md: { iconSize: 13 },\n lg: { iconSize: 15 },\n};\n\n// --- Helper to compute variant classes ---\n\nfunction getVariantClasses(\n variant: string,\n isActive: boolean,\n orientation: 'horizontal' | 'vertical'\n): string {\n switch (variant) {\n case 'underline':\n return cx(\n tabUnderlineStyle,\n isActive ? tabUnderlineActiveStyle : tabUnderlineInactiveStyle,\n isActive\n ? orientation === 'vertical'\n ? tabUnderlineActiveVerticalStyle\n : tabUnderlineActiveHorizontalStyle\n : tabUnderlineInactiveIndicatorStyle\n );\n case 'pills':\n return cx(\n tabPillsStyle,\n isActive ? tabPillsActiveStyle : tabPillsInactiveStyle\n );\n case 'enclosed':\n return cx(\n tabEnclosedStyle,\n isActive\n ? orientation === 'vertical'\n ? tabEnclosedActiveVerticalStyle\n : tabEnclosedActiveHorizontalStyle\n : tabEnclosedInactiveStyle\n );\n default:\n return '';\n }\n}\n\n// --- Component ---\n\nexport const Tab: React.FC<TabProps> = ({\n value,\n children,\n icon,\n disabled = false,\n closable = false,\n onClose,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const {\n activeValue,\n setActiveValue,\n variant,\n size,\n orientation,\n fullWidth,\n tabsId,\n } = useTabsContext();\n const isActive = activeValue === value;\n const sizeConfig = TAB_SIZE_MAP[size];\n const closeIconSize = size === 'lg' ? 'md' : 'sm';\n\n const tabId = `tabs-${tabsId}-tab-${value}`;\n const panelId = `tabs-${tabsId}-panel-${value}`;\n\n const handleClick = useCallback(() => {\n if (!disabled) {\n setActiveValue(value);\n }\n }, [disabled, setActiveValue, value]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (!disabled) {\n setActiveValue(value);\n }\n }\n if (e.key === 'Delete' && closable && onClose) {\n e.preventDefault();\n onClose(value);\n }\n },\n [disabled, setActiveValue, value, closable, onClose]\n );\n\n const handleClose = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onClose?.(value);\n },\n [onClose, value]\n );\n\n const handleCloseKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n onClose?.(value);\n }\n },\n [onClose, value]\n );\n\n const variantClasses = getVariantClasses(variant, isActive, orientation);\n\n return (\n <button\n ref={ref}\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-controls={panelId}\n aria-disabled={disabled || undefined}\n tabIndex={isActive ? 0 : -1}\n disabled={disabled}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n className={cx(\n tabBaseStyle,\n tabRecipe({ size, disabled, fullWidth }),\n variantClasses,\n className\n )}\n style={{\n gap: vars.spacing.xs,\n ...style,\n }}\n data-testid={testId}\n {...rest}\n >\n {icon && (\n <span\n className={tabIconStyle}\n style={{\n width: `${sizeConfig.iconSize}px`,\n height: `${sizeConfig.iconSize}px`,\n }}\n >\n {icon}\n </span>\n )}\n {children}\n {closable && (\n <span\n className={tabCloseButtonStyle}\n role=\"button\"\n tabIndex={0}\n aria-label={`Close ${typeof children === 'string' ? children : value}`}\n onClick={handleClose}\n onKeyDown={handleCloseKeyDown}\n >\n <CloseIcon size={closeIconSize} decorative />\n </span>\n )}\n </button>\n );\n};\n\nTab.displayName = 'Tab';\n"],"names":[],"mappings":";;;;;;;;;AAqCA;AACE;AACA;AACA;;AAGF;AAEA;;AAMI;AACE;;AAKM;AACA;;AAGR;AACE;AAIF;AACE;;AAIM;AACA;;AAGR;AACE;;AAEN;AAEA;AAEO;AAaL;AASA;AACA;AACA;AAEA;AACA;AAEA;;;;;AAMA;AAEI;;;;;;;;;;AAUF;AAIF;;AAGI;AACF;AAIF;AAEI;;;AAGE;;AAEJ;;AAMF;AAmBM;AACA;AACD;AAQK;AACA;;AAqBZ;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.js","sources":["../../../../../../src/components/navigation/Tabs/TabList.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;AAWA;;;AAWE;AAEA;AAEI;AACA;;;;AAGE;;AAEJ;AAIF;AAEI;AACA;;AAEA;;;;AAMA;;;;AAMA;AACE;;AAEE;AACA;;;AAEF;;AAEE;;AACmB;;AAErB;;;;AAIA;;AAEE;;;AAIJ;AACE;;AAEJ;;;;AAUE;AAcN;AAEA;;"}
1
+ {"version":3,"file":"TabList.js","sources":["src/components/navigation/Tabs/TabList.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback, useRef } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { useTabsContext } from './Tabs';\nimport { tabListRecipe } from './Tabs.css';\n\nimport type { TabListProps } from './Tabs.types';\n\n// --- Component ---\n\nexport const TabList: React.FC<TabListProps> = ({\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const { orientation, variant, pillsFrame } = useTabsContext();\n const listRef = useRef<HTMLDivElement | null>(null);\n\n const setListRef = useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const list = listRef.current;\n if (!list) return;\n\n const tabs = Array.from(\n list.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')\n );\n const currentIndex = tabs.indexOf(e.target as HTMLButtonElement);\n if (currentIndex === -1) return;\n\n const isHorizontal = orientation === 'horizontal';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n\n let nextIndex: number | null = null;\n\n switch (e.key) {\n case nextKey:\n e.preventDefault();\n nextIndex = currentIndex + 1;\n if (nextIndex >= tabs.length) nextIndex = 0;\n break;\n case prevKey:\n e.preventDefault();\n nextIndex = currentIndex - 1;\n if (nextIndex < 0) nextIndex = tabs.length - 1;\n break;\n case 'Home':\n e.preventDefault();\n nextIndex = 0;\n break;\n case 'End':\n e.preventDefault();\n nextIndex = tabs.length - 1;\n break;\n }\n\n if (nextIndex !== null) {\n tabs[nextIndex]?.focus();\n }\n },\n [orientation]\n );\n\n return (\n <div\n ref={setListRef}\n role=\"tablist\"\n // Roving tabindex lives on the individual tabs; the list itself is only\n // focusable programmatically while it manages arrow-key navigation.\n tabIndex={-1}\n aria-orientation={orientation}\n className={cx(\n tabListRecipe({ orientation, variant, pillsFrame }),\n className\n )}\n style={style}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {children}\n </div>\n );\n};\n\nTabList.displayName = 'TabList';\n"],"names":[],"mappings":";;;;;;;AAWA;;;AAWE;AAEA;AAEI;AACA;;;;AAGE;;AAEJ;AAIF;AAEI;AACA;;AAEA;;;;AAMA;;;;AAMA;AACE;;AAEE;AACA;;;AAEF;;AAEE;;AACmB;;AAErB;;;;AAIA;;AAEE;;;AAIJ;AACE;;AAEJ;;;;AAUE;AAcN;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabPanel.js","sources":["../../../../../../src/components/navigation/Tabs/TabPanel.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAWA;AAEO;AAUL;AACA;AACA;;AAGA;AAEA;AACA;AAEA;AACE;;;AAaI;AACA;AACD;AAOP;AAEA;;"}
1
+ {"version":3,"file":"TabPanel.js","sources":["src/components/navigation/Tabs/TabPanel.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { useTabsContext } from './Tabs';\nimport { tabPanelStyle } from './Tabs.css';\n\nimport type { TabPanelProps } from './Tabs.types';\n\n// --- Component ---\n\nexport const TabPanel: React.FC<TabPanelProps> = ({\n value,\n children,\n keepMounted,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const ctx = useTabsContext();\n const { activeValue, tabsId } = ctx;\n const isActive = activeValue === value;\n\n // Explicit child prop wins over the parent cascade. Undefined = inherit.\n const effectiveKeepMounted = keepMounted ?? ctx.keepMounted;\n\n const tabId = `tabs-${tabsId}-tab-${value}`;\n const panelId = `tabs-${tabsId}-panel-${value}`;\n\n if (!isActive && !effectiveKeepMounted) {\n return null;\n }\n\n return (\n <div\n ref={ref}\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n tabIndex={isActive ? 0 : -1}\n hidden={!isActive || undefined}\n className={cx(tabPanelStyle, className)}\n style={{\n ...style,\n ...(isActive ? undefined : { display: 'none' }),\n }}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n );\n};\n\nTabPanel.displayName = 'TabPanel';\n"],"names":[],"mappings":";;;;;;AAWA;AAEO;AAUL;AACA;AACA;;AAGA;AAEA;AACA;AAEA;AACE;;;AAaI;AACA;AACD;AAOP;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","sources":["../../../../../../src/components/navigation/Tabs/Tabs.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAiBA;AAEA;;AAGE;;AAEE;;AAEF;AACF;AAEA;AAEA;;;;;;;;;;;;;;;;AAgBG;AACI;AAiBL;;AAGA;AACA;;AAGA;;;;AAKI;AACF;AAIF;;;;;;;;;;AAWG;;;;;;;;;;AAWA;AAGH;AAaF;AAEA;;"}
1
+ {"version":3,"file":"Tabs.js","sources":["src/components/navigation/Tabs/Tabs.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useId,\n useMemo,\n useState,\n} from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { tabsRootRecipe } from './Tabs.css';\n\nimport type { TabsContextValue, TabsProps } from './Tabs.types';\n\n// --- Context ---\n\nconst TabsContext = /*#__PURE__*/ createContext<TabsContextValue | null>(null);\n\nexport function useTabsContext(): TabsContextValue {\n const ctx = useContext(TabsContext);\n if (!ctx) {\n throw new Error('Tabs compound components must be used within <Tabs>');\n }\n return ctx;\n}\n\n// --- Component ---\n\n/**\n * Tabs component for switching between views within a panel.\n *\n * Compound component pattern: use with TabList, Tab, and TabPanel.\n *\n * @example\n * ```tsx\n * <Tabs defaultValue=\"properties\">\n * <TabList>\n * <Tab value=\"properties\">Properties</Tab>\n * <Tab value=\"materials\">Materials</Tab>\n * </TabList>\n * <TabPanel value=\"properties\">Properties content</TabPanel>\n * <TabPanel value=\"materials\">Materials content</TabPanel>\n * </Tabs>\n * ```\n */\nexport const Tabs: React.FC<TabsProps> = ({\n value: valueProp,\n defaultValue,\n variant = 'underline',\n size = 'md',\n orientation = 'horizontal',\n fullWidth = false,\n pillsFrame = true,\n keepMounted = false,\n children,\n onChange,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const autoId = useId();\n const tabsId = autoId;\n\n const [internalValue, setInternalValue] = useState(defaultValue ?? '');\n const isControlled = valueProp !== undefined;\n const activeValue = isControlled ? valueProp : internalValue;\n\n const setActiveValue = useCallback(\n (val: string) => {\n if (!isControlled) {\n setInternalValue(val);\n }\n onChange?.(val);\n },\n [isControlled, onChange]\n );\n\n const contextValue = useMemo<TabsContextValue>(\n () => ({\n activeValue,\n setActiveValue,\n variant,\n size,\n orientation,\n fullWidth,\n pillsFrame,\n keepMounted,\n tabsId,\n }),\n [\n activeValue,\n setActiveValue,\n variant,\n size,\n orientation,\n fullWidth,\n pillsFrame,\n keepMounted,\n tabsId,\n ]\n );\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cx(tabsRootRecipe({ orientation }), className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n </TabsContext.Provider>\n );\n};\n\nTabs.displayName = 'Tabs';\n"],"names":[],"mappings":";;;;;;AAiBA;AAEA;;AAGE;;AAEE;;AAEF;AACF;AAEA;AAEA;;;;;;;;;;;;;;;;AAgBG;AACI;AAiBL;;AAGA;AACA;;AAGA;;;;AAKI;AACF;AAIF;;;;;;;;;;AAWG;;;;;;;;;;AAWA;AAGH;AAaF;AAEA;;"}
@@ -89,6 +89,12 @@ import '../../Icons/GitBranchIcon.js';
89
89
  import '../../Icons/BugIcon.js';
90
90
  import '../../Icons/MinusIcon.js';
91
91
  import '../../Icons/PinIcon.js';
92
+ import '../../Icons/OrbitIcon.js';
93
+ import '../../Icons/RotateIcon.js';
94
+ import '../../Icons/SpinIcon.js';
95
+ import '../../Icons/CameraIcon.js';
96
+ import '../../Icons/CubeIcon.js';
97
+ import '../../Icons/ZoomFitIcon.js';
92
98
  import { vars } from '../../../theme/contract.css.js';
93
99
  import { cx } from '../../../utils/cx.js';
94
100
  import { avatarFallbackStyle, avatarImageInheritRadius, avatarImageStyle, avatarStatusRecipe, avatarRecipe, avatarBgVar, avatarStatusVar } from './Avatar.css.js';
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","sources":["../../../../../../src/components/primitives/Avatar/Avatar.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA;AACE;AACA;AACA;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;;AAGF;;AAEE;AACE;;AAEF;AACF;AAEA;;;;;AAKG;AACG;AACJ;AACA;AAAc;;;AAGd;;;AAGA;;;;AAIF;AAEA;AAIE;AACE;AACE;;;AAGF;;AAEF;AACA;AAAW;AACX;AACF;AAEA;AAIA;;;;;;;;;;;;;;;;;;AAkBG;AACI;;AAsBH;;;AAIA;;;AAIA;AAEI;;AACA;;;;AAIF;;;AAOE;AACE;;AAGN;;;AAIA;AAEA;;;;;;AAOA;;;;;;AAWO;AA8CT;AAGF;;"}
1
+ {"version":3,"file":"Avatar.js","sources":["src/components/primitives/Avatar/Avatar.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useState } from 'react';\n\nimport { UserIcon } from '@/components/Icons';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n avatarBgVar,\n avatarFallbackStyle,\n avatarImageInheritRadius,\n avatarImageStyle,\n avatarRecipe,\n avatarStatusRecipe,\n avatarStatusVar,\n} from './Avatar.css';\n\nimport type { AvatarColor, AvatarProps, AvatarStatus } from './Avatar.types';\n\nconst NAMED_COLOR_MAP: Record<string, string> = {\n neutral: vars.colors.text.muted,\n primary: vars.colors.accent.primary,\n info: vars.colors.accent.primary,\n success: vars.colors.accent.success,\n warning: vars.colors.accent.warning,\n error: vars.colors.accent.error,\n};\n\nconst AUTO_PALETTE: readonly string[] = [\n vars.colors.accent.primary,\n vars.colors.accent.secondary,\n vars.colors.accent.success,\n vars.colors.accent.warning,\n vars.colors.accent.error,\n];\n\nconst STATUS_COLOR_MAP: Record<AvatarStatus, string> = {\n online: vars.colors.accent.success,\n away: vars.colors.accent.warning,\n busy: vars.colors.accent.error,\n offline: vars.colors.text.muted,\n};\n\nconst STATUS_LABEL_MAP: Record<AvatarStatus, string> = {\n online: 'Online',\n away: 'Away',\n busy: 'Busy',\n offline: 'Offline',\n};\n\nfunction hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i += 1) {\n hash = (hash * 31 + str.charCodeAt(i)) | 0;\n }\n return Math.abs(hash);\n}\n\n/**\n * Derive 1- or 2-letter initials from a display name.\n *\n * Single-word names contribute their first two characters; multi-word names\n * contribute the first character of the first and last word.\n */\nexport function getAvatarInitials(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) return '';\n const parts = trimmed.split(/\\s+/);\n const firstWord = parts[0] ?? '';\n if (parts.length === 1) {\n return firstWord.slice(0, 2).toUpperCase();\n }\n const lastWord = parts[parts.length - 1] ?? '';\n const first = firstWord[0] ?? '';\n const last = lastWord[0] ?? '';\n return (first + last).toUpperCase();\n}\n\nfunction resolveBackgroundColor(\n color: AvatarColor,\n name: string | undefined\n): string {\n if (color === 'auto') {\n if (!name?.trim()) {\n return vars.colors.text.muted;\n }\n const index = hashString(name) % AUTO_PALETTE.length;\n return AUTO_PALETTE[index] ?? vars.colors.text.muted;\n }\n const named = NAMED_COLOR_MAP[color];\n if (named) return named;\n return color;\n}\n\nconst DefaultUserIcon: React.FC = () => (\n <UserIcon size=\"60%\" color=\"currentColor\" decorative />\n);\n\n/**\n * Display a person, agent, or named entity.\n *\n * Renders an image when `src` is provided; if it fails to load (or no `src`\n * was given) falls back to initials derived from `name`, then to a generic\n * user icon. A deterministic auto color keeps a given `name` looking the\n * same across renders while different names look distinct.\n *\n * Provide `onClick` to render the avatar as an interactive button (focusable,\n * Enter/Space-activatable, hover affordance).\n *\n * @example\n * ```tsx\n * <Avatar src=\"/users/alice.png\" name=\"Alice Wong\" />\n * <Avatar name=\"Sebastian Kowalski\" status=\"online\" />\n * <Avatar name=\"Bot\" color=\"primary\" shape=\"rounded\" />\n * <Avatar name=\"Owner\" size=\"xl\" onClick={openProfile} />\n * ```\n */\nexport const Avatar = /*#__PURE__*/ React.memo<AvatarProps>(\n ({\n src,\n alt,\n name,\n initials,\n fallbackIcon,\n size = 'md',\n shape = 'circle',\n color = 'auto',\n status,\n onClick,\n bordered = false,\n className,\n style,\n testId,\n 'aria-label': ariaLabelProp,\n ref,\n ...rest\n }) => {\n const [imageOk, setImageOk] = useState<boolean>(true);\n\n const handleImageError = useCallback(() => {\n setImageOk(false);\n }, []);\n\n const handleImageLoad = useCallback(() => {\n setImageOk(true);\n }, []);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLSpanElement>) => {\n if (!onClick) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onClick(event);\n }\n },\n [onClick]\n );\n\n const resolvedInitials =\n initials !== undefined && initials !== ''\n ? initials.slice(0, 2).toUpperCase()\n : name\n ? getAvatarInitials(name)\n : '';\n\n const hasInitials = resolvedInitials.length > 0;\n const showImage = Boolean(src) && imageOk;\n\n const bg = resolveBackgroundColor(color, name);\n const accessibleName = ariaLabelProp ?? name ?? alt;\n\n const inlineVars: Record<string, string> = {\n [avatarBgVar]: bg,\n };\n if (status) {\n inlineVars[avatarStatusVar] = STATUS_COLOR_MAP[status];\n }\n\n const interactive = Boolean(onClick);\n\n return (\n <span\n ref={ref}\n className={cx(\n avatarRecipe({\n size,\n shape,\n bordered: bordered || undefined,\n interactive: interactive || undefined,\n }),\n className\n )}\n style={{ ...assignInlineVars(inlineVars), ...style }}\n data-testid={testId}\n data-size={size}\n data-shape={shape}\n role={interactive ? 'button' : 'img'}\n tabIndex={interactive ? 0 : undefined}\n onClick={onClick}\n onKeyDown={interactive ? handleKeyDown : undefined}\n aria-label={accessibleName}\n {...rest}\n >\n <span className={avatarFallbackStyle} aria-hidden={showImage}>\n {hasInitials ? (\n resolvedInitials\n ) : fallbackIcon !== undefined ? (\n fallbackIcon\n ) : (\n <DefaultUserIcon />\n )}\n </span>\n\n {src && (\n <img\n src={src}\n alt={alt ?? name ?? ''}\n className={cx(avatarImageStyle, avatarImageInheritRadius)}\n data-loaded={imageOk ? 'true' : 'false'}\n onError={handleImageError}\n onLoad={handleImageLoad}\n draggable={false}\n />\n )}\n\n {status && (\n <span\n className={avatarStatusRecipe({ size })}\n data-status={status}\n role=\"status\"\n aria-label={`Status: ${STATUS_LABEL_MAP[status]}`}\n />\n )}\n </span>\n );\n }\n);\n\nAvatar.displayName = 'Avatar';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA;AACE;AACA;AACA;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;AACA;;AAGF;;AAEE;AACE;;AAEF;AACF;AAEA;;;;;AAKG;AACG;AACJ;AACA;AAAc;;;AAGd;;;AAGA;;;;AAIF;AAEA;AAIE;AACE;AACE;;;AAGF;;AAEF;AACA;AAAW;AACX;AACF;AAEA;AAIA;;;;;;;;;;;;;;;;;;AAkBG;AACI;;AAsBH;;;AAIA;;;AAIA;AAEI;;AACA;;;;AAIF;;;AAOE;AACE;;AAGN;;;AAIA;AAEA;;;;;;AAOA;;;;;;AAWO;AA8CT;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.js","sources":["../../../../../../src/components/primitives/Avatar/AvatarGroup.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAoBA;AACA;AAEA;AACE;AACF;AAEA;AAGE;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;AAqBG;;;AAoBC;;;AAGA;;AAGE;AACD;AAED;AAGO;AACA;;;AAKmB;AAExB;;AAIM;;AAED;;AAGA;AAQL;;;;AAYA;AAKF;AAEA;AASM;AACA;AACA;;;AASK;AAGP;AAIN;AAGF;;"}
1
+ {"version":3,"file":"AvatarGroup.js","sources":["src/components/primitives/Avatar/AvatarGroup.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useMemo } from 'react';\n\nimport { Tooltip } from '@/components/primitives/Tooltip';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport { Avatar } from './Avatar';\nimport {\n avatarBgVar,\n avatarGroupItemStyle,\n avatarGroupRootStyle,\n avatarGroupSpacingVar,\n avatarRecipe,\n} from './Avatar.css';\n\nimport type { AvatarGroupProps, AvatarProps } from './Avatar.types';\n\nconst DEFAULT_MAX = 4;\nconst DEFAULT_SPACING = -8;\n\nfunction resolveSpacing(spacing: number | string): string {\n return typeof spacing === 'number' ? `${spacing}px` : spacing;\n}\n\nfunction isAvatarElement(\n node: React.ReactNode\n): node is React.ReactElement<AvatarProps> {\n return React.isValidElement(node) && node.type === Avatar;\n}\n\n/**\n * Display a row of `Avatar`s with optional overlap and overflow handling.\n *\n * Children are rendered in order, with negative margin (controlled via the\n * `spacing` prop) creating the classic overlapping cluster. When the number\n * of children exceeds `max`, the remainder collapses into a `+N` indicator;\n * hovering it reveals the names of the hidden avatars.\n *\n * `size` and `bordered` are applied to every child — the group always wins\n * over per-avatar values to keep the visual treatment uniform.\n *\n * @example\n * ```tsx\n * <AvatarGroup max={4}>\n * <Avatar name=\"Alice\" />\n * <Avatar name=\"Bob\" />\n * <Avatar name=\"Carol\" />\n * <Avatar name=\"Dave\" />\n * <Avatar name=\"Eve\" />\n * </AvatarGroup>\n * ```\n */\nexport const AvatarGroup = /*#__PURE__*/ React.memo<AvatarGroupProps>(\n ({\n max = DEFAULT_MAX,\n spacing = DEFAULT_SPACING,\n size = 'md',\n bordered = true,\n showOverflowTooltip = true,\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const items = useMemo(\n () => React.Children.toArray(children).filter(isAvatarElement),\n [children]\n );\n\n const visibleCount = Math.min(items.length, max);\n const visibleItems = items.slice(0, visibleCount);\n const hiddenItems = items.slice(visibleCount);\n const overflowCount = hiddenItems.length;\n\n const spacingStyle = assignInlineVars({\n [avatarGroupSpacingVar]: resolveSpacing(spacing),\n });\n\n const hiddenNames = useMemo(\n () =>\n hiddenItems\n .map(child => child.props.name ?? child.props.alt)\n .filter((value): value is string => Boolean(value)),\n [hiddenItems]\n );\n\n const renderOverflow = () => {\n if (overflowCount <= 0) return null;\n\n const overflowEl = (\n <span\n className={avatarRecipe({\n size,\n shape: 'circle',\n bordered: bordered || undefined,\n })}\n style={assignInlineVars({\n [avatarBgVar]: vars.colors.surface.active,\n })}\n data-overflow=\"true\"\n aria-label={`${overflowCount} more`}\n >\n {`+${overflowCount}`}\n </span>\n );\n\n const wrapped =\n showOverflowTooltip && hiddenNames.length > 0 ? (\n <Tooltip title={hiddenNames.join(', ')} placement=\"top\">\n {overflowEl}\n </Tooltip>\n ) : (\n overflowEl\n );\n\n // The wrapper span owns the spacing rule (`:not(:first-child)`), so the\n // overlap stays correct whether or not Tooltip injects its own trigger\n // div between this wrapper and the +N span.\n return (\n <span className={avatarGroupItemStyle} style={{ zIndex: 0 }}>\n {wrapped}\n </span>\n );\n };\n\n return (\n <div\n ref={ref}\n className={cx(avatarGroupRootStyle, className)}\n style={{ ...spacingStyle, ...style }}\n data-testid={testId}\n {...rest}\n >\n {visibleItems.map((child, index) => {\n const childKey = child.key ?? index;\n const itemZIndex = visibleItems.length - index;\n return (\n <span\n key={childKey}\n className={avatarGroupItemStyle}\n style={{ zIndex: itemZIndex }}\n >\n {React.cloneElement(child, {\n size,\n bordered,\n })}\n </span>\n );\n })}\n {renderOverflow()}\n </div>\n );\n }\n);\n\nAvatarGroup.displayName = 'AvatarGroup';\n"],"names":[],"mappings":";;;;;;;;;;AAoBA;AACA;AAEA;AACE;AACF;AAEA;AAGE;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;AAqBG;;;AAoBC;;;AAGA;;AAGE;AACD;AAED;AAGO;AACA;;;AAKmB;AAExB;;AAIM;;AAED;;AAGA;AAQL;;;;AAYA;AAKF;AAEA;AASM;AACA;AACA;;;AASK;AAGP;AAIN;AAGF;;"}
@@ -89,6 +89,12 @@ import '../../Icons/GitBranchIcon.js';
89
89
  import '../../Icons/BugIcon.js';
90
90
  import '../../Icons/MinusIcon.js';
91
91
  import '../../Icons/PinIcon.js';
92
+ import '../../Icons/OrbitIcon.js';
93
+ import '../../Icons/RotateIcon.js';
94
+ import '../../Icons/SpinIcon.js';
95
+ import '../../Icons/CameraIcon.js';
96
+ import '../../Icons/CubeIcon.js';
97
+ import '../../Icons/ZoomFitIcon.js';
92
98
  import { vars } from '../../../theme/contract.css.js';
93
99
  import { cx } from '../../../utils/cx.js';
94
100
  import { badgeContrastVar, badgeColorVar, badgeDotStyle, badgeIconStyle, badgeRemoveButtonStyle, badgeRecipe } from './Badge.css.js';
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","sources":["../../../../../../src/components/primitives/Badge/Badge.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA;AACE;AACA;AACA;AACA;AACA;AACA;;AAGF;;;;;AAKG;AACH;AAIE;;;;AAKE;;AAEF;AACF;AAEA;AAIA;;;;;;;;;;;;;;AAcG;;AAiBC;AAEA;;AAGI;AACF;;AAKA;AACA;AACD;;;;;AAUM;AA0BT;AAGF;;"}
1
+ {"version":3,"file":"Badge.js","sources":["src/components/primitives/Badge/Badge.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback } from 'react';\n\nimport { CloseIcon } from '@/components/Icons';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n badgeColorVar,\n badgeContrastVar,\n badgeDotStyle,\n badgeIconStyle,\n badgeRecipe,\n badgeRemoveButtonStyle,\n} from './Badge.css';\n\nimport type { BadgeColor, BadgeProps } from './Badge.types';\n\nconst NAMED_COLOR_MAP: Record<string, string> = {\n neutral: vars.colors.text.muted,\n primary: vars.colors.accent.primary,\n info: vars.colors.accent.primary,\n success: vars.colors.accent.success,\n warning: vars.colors.accent.warning,\n error: vars.colors.accent.error,\n};\n\n/**\n * Resolve a `BadgeColor` to a CSS color value.\n *\n * Named values produce a `var(...)` reference into the theme; everything\n * else is treated as a raw CSS color string (hex, rgb, hsl, …).\n */\nfunction resolveBadgeColor(color: BadgeColor): {\n color: string;\n contrast: string;\n} {\n const named = NAMED_COLOR_MAP[color];\n if (named) {\n // For neutral we keep contrast as the text primary so solid reads well.\n const contrast =\n color === 'neutral' ? vars.colors.text.primary : vars.colors.text.primary;\n return { color: named, contrast };\n }\n return { color, contrast: '#ffffff' };\n}\n\nconst RemoveIcon: React.FC = () => (\n <CloseIcon size={10} color=\"currentColor\" decorative />\n);\n\n/**\n * A small inline status indicator / tag.\n *\n * Badges are visual labels for status, counts, or tags. Pair with an\n * editor item to indicate its state (e.g. \"DRAFT\", \"ERROR\", \"3 NEW\").\n *\n * @example\n * ```tsx\n * <Badge color=\"success\">Saved</Badge>\n * <Badge variant=\"outline\" color=\"warning\" icon={<WarningIcon />}>\n * Warning\n * </Badge>\n * <Badge removable onRemove={handleRemove}>feature/foo</Badge>\n * ```\n */\nexport const Badge = /*#__PURE__*/ React.memo<BadgeProps>(\n ({\n variant = 'subtle',\n size = 'sm',\n color = 'neutral',\n uppercase = false,\n icon,\n removable = false,\n onRemove,\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const resolved = resolveBadgeColor(color);\n\n const handleRemoveClick = useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onRemove?.(event);\n },\n [onRemove]\n );\n\n const inlineVars = assignInlineVars({\n [badgeColorVar]: resolved.color,\n [badgeContrastVar]: resolved.contrast,\n });\n\n return (\n <span\n ref={ref}\n className={cx(\n badgeRecipe({\n variant,\n size,\n uppercase: uppercase || undefined,\n }),\n className\n )}\n style={{ ...inlineVars, ...style }}\n data-testid={testId}\n {...rest}\n >\n {variant === 'dot' && <span className={badgeDotStyle} aria-hidden />}\n {icon && (\n <span className={badgeIconStyle} aria-hidden>\n {icon}\n </span>\n )}\n {children && <span>{children}</span>}\n {removable && (\n <button\n type=\"button\"\n className={badgeRemoveButtonStyle}\n onClick={handleRemoveClick}\n aria-label=\"Remove\"\n >\n <RemoveIcon />\n </button>\n )}\n </span>\n );\n }\n);\n\nBadge.displayName = 'Badge';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA;AACE;AACA;AACA;AACA;AACA;AACA;;AAGF;;;;;AAKG;AACH;AAIE;;;;AAKE;;AAEF;AACF;AAEA;AAIA;;;;;;;;;;;;;;AAcG;;AAiBC;AAEA;;AAGI;AACF;;AAKA;AACA;AACD;;;;;AAUM;AA0BT;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sources":["../../../../../../src/components/primitives/Button/Button.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAwGA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;;AAiBC;AAsBF;AAGF;;"}
1
+ {"version":3,"file":"Button.js","sources":["src/components/primitives/Button/Button.tsx"],"sourcesContent":["'use client';\n\n// src/primitives/Button/Button.tsx\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n buttonRecipe,\n loadingSpinnerStyle,\n iconWrapperStyle,\n} from './Button.css';\n\nimport type { Size, Variant } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\n\n/**\n * Button sizes optimized for editor interfaces\n */\nexport type ButtonSize = Size;\n\n/**\n * Visual variants for the button\n */\nexport type ButtonVariant = Variant;\n\n/**\n * Base props for the Button component\n */\nexport interface ButtonBaseProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'css'\n> {\n /**\n * Button content — text, icons, or other React elements\n * @example \"Save\", <><SaveIcon /> Save</>\n */\n children?: React.ReactNode;\n\n /**\n * Size variant optimized for editor interfaces\n * - `sm`: 20px height, compact for toolbars\n * - `md`: 24px height, standard for panels\n * - `lg`: 32px height, prominent actions\n * @default \"md\"\n */\n size?: ButtonSize;\n\n /**\n * Visual variant of the button\n * - `default`: Transparent with border, fills on hover\n * - `ghost`: No border, subtle hover state\n * - `filled`: Solid background with accent color\n * @default \"default\"\n */\n variant?: ButtonVariant;\n\n /**\n * Whether the button is disabled\n * When true, button becomes non-interactive with reduced opacity\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Loading state — shows spinner and disables interaction\n * Use for async operations like saving, loading data\n * @default false\n */\n loading?: boolean;\n\n /**\n * Icon element to display before text\n * Should be 16x16px for optimal appearance\n * @example <SaveIcon />, <PlayIcon />\n */\n icon?: React.ReactNode;\n\n /**\n * Whether the button should take the full width of the container\n * Useful for form actions and modal buttons\n * @default false\n */\n fullWidth?: boolean;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n /**\n * Click event handler\n * Called when button is clicked (not when disabled/loading)\n */\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Props for the Button component with prettified type for better IntelliSense\n */\nexport type ButtonProps = Prettify<ButtonBaseProps>;\n\n/**\n * Versatile button component for editor interfaces.\n *\n * Supports multiple variants, sizes, and states. Optimized for professional\n * editor interfaces with compact dimensions and precise interactions.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <Button variant=\"default\" size=\"md\">Save</Button>\n *\n * // With icon and loading state\n * <Button\n * icon={<SaveIcon />}\n * loading={isSaving}\n * onClick={handleSave}\n * >\n * Save Project\n * </Button>\n *\n * // Full width button\n * <Button variant=\"filled\" fullWidth>\n * Confirm\n * </Button>\n * ```\n */\nexport const Button = /*#__PURE__*/ React.memo<ButtonProps>(\n ({\n children,\n className,\n size = 'md',\n variant = 'default',\n disabled = false,\n loading = false,\n icon,\n fullWidth = false,\n onClick,\n testId,\n style,\n ref,\n ...props\n }) => {\n return (\n <button\n ref={ref}\n className={cx(\n buttonRecipe({ variant, size, fullWidth: fullWidth || undefined }),\n className\n )}\n disabled={disabled || loading}\n onClick={onClick}\n data-testid={testId}\n style={style}\n {...props}\n >\n {loading ? (\n <div className={loadingSpinnerStyle} />\n ) : icon ? (\n <span className={iconWrapperStyle}>{icon}</span>\n ) : null}\n\n {children && <span>{children}</span>}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n"],"names":[],"mappings":";;;;;;AAwGA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;;AAiBC;AAsBF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","sources":["../../../../../../src/components/primitives/Checkbox/Checkbox.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;AAoBA;AAEA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;;AAaG;AACI;AAuBL;AACA;AACA;AACA;;;;;;;;;;AAaA;AAEA;;;;;;;;;;AASA;AACE;;AAEA;AAEA;AACE;;AAGF;;;AAIA;AACF;;;;;;;;AAQC;AAED;AACA;;AAGE;AACA;AACE;;AAGJ;;;AAIC;;;;AAKD;AAEE;AACA;;;;;;AAmBG;AAUK;;;AAGA;AACE;AACA;;AAiBZ;AACE;;AAGF;;;;AAOO;AAYT;AAEA;;"}
1
+ {"version":3,"file":"Checkbox.js","sources":["src/components/primitives/Checkbox/Checkbox.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useId, useContext, useState } from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { CheckIcon } from '@/components/Icons/CheckIcon';\nimport { MinusIcon } from '@/components/Icons/MinusIcon';\nimport { cx } from '@/utils/cx';\n\nimport {\n checkboxContainerStyle,\n checkboxLabelRecipe,\n checkboxBoxRecipe,\n boxSizeVar,\n} from './Checkbox.css';\nimport { CheckboxGroupContext } from './CheckboxGroup';\n\nimport type { CheckboxProps, CheckboxSize } from './Checkbox.types';\n\n// --- Size maps ---\n\nconst BOX_SIZES: Record<CheckboxSize, number> = {\n sm: 14,\n md: 16,\n lg: 20,\n};\n\nconst ICON_SIZES: Record<CheckboxSize, number> = {\n sm: 10,\n md: 12,\n lg: 14,\n};\n\n/**\n * Checkbox component for boolean selection in settings panels,\n * property inspectors, and form interfaces.\n *\n * Supports controlled/uncontrolled modes, indeterminate state,\n * label positioning, sizes, variants, and error states.\n *\n * @example\n * ```tsx\n * <Checkbox label=\"Enable shadows\" />\n * <Checkbox checked={value} onChange={setValue} label=\"Auto-save\" />\n * <Checkbox indeterminate label=\"Select all\" />\n * ```\n */\nexport const Checkbox: React.FC<CheckboxProps> = ({\n checked: checkedProp,\n defaultChecked = false,\n indeterminate = false,\n label,\n labelPosition = 'right',\n size: sizeProp,\n variant = 'default',\n disabled: disabledProp = false,\n required = false,\n error = false,\n helperText,\n errorMessage,\n value,\n name,\n onChange,\n className,\n style,\n testId,\n ref,\n id: idProp,\n ...rest\n}) => {\n const groupContext = useContext(CheckboxGroupContext);\n const autoId = useId();\n const checkboxId = idProp ?? autoId;\n const helperId = `${checkboxId}-helper`;\n\n // Internal state for uncontrolled mode\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n\n // Resolve group context\n const disabled = disabledProp || (groupContext?.disabled ?? false);\n // Size resolves from the checkbox prop, then the group, then the default —\n // mirroring how `disabled` above falls back to the group context.\n const size = sizeProp ?? groupContext?.size ?? 'md';\n\n // Determine checked state for group integration\n const isGrouped = groupContext !== null && value !== undefined;\n const isControlled = checkedProp !== undefined;\n\n let resolvedChecked: boolean;\n if (isGrouped) {\n resolvedChecked = groupContext.groupValue.includes(value);\n } else if (isControlled) {\n resolvedChecked = checkedProp;\n } else {\n resolvedChecked = internalChecked;\n }\n\n const handleClick = useCallback(() => {\n if (disabled) return;\n\n const newChecked = !resolvedChecked;\n\n if (isGrouped && value) {\n groupContext.toggleValue(value);\n }\n\n if (!isControlled && !isGrouped) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [\n disabled,\n resolvedChecked,\n isGrouped,\n value,\n groupContext,\n isControlled,\n onChange,\n ]);\n\n const iconSize = ICON_SIZES[size];\n const showHelperText = error && errorMessage ? errorMessage : helperText;\n\n const ariaChecked: 'true' | 'false' | 'mixed' = indeterminate\n ? 'mixed'\n : resolvedChecked\n ? 'true'\n : 'false';\n\n const isActive = resolvedChecked || indeterminate;\n\n const boxInlineVars = assignInlineVars({\n [boxSizeVar]: `${BOX_SIZES[size]}px`,\n });\n\n // Respect OS-level reduced-motion preference for the inline check-mark\n // animation. Stylesheet @media queries cover CSS-driven motion elsewhere;\n // this style is set inline, so the check has to happen here.\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const checkboxBox = (\n <button\n ref={ref}\n type=\"button\"\n role=\"checkbox\"\n aria-checked={ariaChecked}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={error || undefined}\n aria-describedby={showHelperText ? helperId : undefined}\n disabled={disabled}\n onClick={handleClick}\n className={checkboxBoxRecipe({\n active: isActive || undefined,\n variant,\n disabled: disabled || undefined,\n error: error || undefined,\n })}\n style={boxInlineVars}\n data-testid={testId}\n {...rest}\n >\n {indeterminate ? (\n <MinusIcon size={iconSize} color=\"white\" decorative />\n ) : (\n <span\n style={{\n display: 'inline-flex',\n opacity: resolvedChecked ? 1 : 0,\n transform: resolvedChecked ? 'scale(1)' : 'scale(0)',\n transition: prefersReducedMotion\n ? 'none'\n : 'opacity 150ms ease-out, transform 150ms ease-out',\n }}\n aria-hidden=\"true\"\n >\n <CheckIcon size={iconSize} color=\"white\" decorative />\n </span>\n )}\n {name && (\n <input\n type=\"hidden\"\n name={name}\n value={resolvedChecked ? (value ?? 'on') : ''}\n />\n )}\n </button>\n );\n\n if (!label && !showHelperText) {\n return checkboxBox;\n }\n\n return (\n <div className={cx(checkboxContainerStyle, className)} style={style}>\n <label\n className={checkboxLabelRecipe({\n labelPosition,\n disabled: disabled || undefined,\n size,\n })}\n >\n {checkboxBox}\n {label && <span>{label}</span>}\n </label>\n {showHelperText && (\n <FormHelperText id={helperId} error={error}>\n {showHelperText}\n </FormHelperText>\n )}\n </div>\n );\n};\n\nCheckbox.displayName = 'Checkbox';\n"],"names":[],"mappings":";;;;;;;;;;;AAoBA;AAEA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;;AAaG;AACI;AAuBL;AACA;AACA;AACA;;;;;;;;;;AAaA;AAEA;;;;;;;;;;AASA;AACE;;AAEA;AAEA;AACE;;AAGF;;;AAIA;AACF;;;;;;;;AAQC;AAED;AACA;;AAGE;AACA;AACE;;AAGJ;;;AAIC;;;;AAKD;AAEE;AACA;;;;;;AAmBG;AAUK;;;AAGA;AACE;AACA;;AAiBZ;AACE;;AAGF;;;;AAOO;AAYT;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxGroup.js","sources":["../../../../../../src/components/primitives/Checkbox/CheckboxGroup.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAsBE;AAEF;;;;;;;;;;;;;;;;;;AAkBG;AACI;AAqBL;AACA;AACA;AACA;;AAGA;;AAGA;AAEI;AACE;AACA;;;;AAKF;;AAKJ;AACE;;;;;AAMF;AAEA;;AAqBU;;AAaZ;AAEA;;"}
1
+ {"version":3,"file":"CheckboxGroup.js","sources":["src/components/primitives/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { createContext, useCallback, useId, useState } from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { FormLabel } from '@/components/form/FormLabel';\nimport { cx } from '@/utils/cx';\n\nimport {\n groupContainerStyle,\n groupItemsStyle,\n groupDirectionVar,\n groupGapVar,\n} from './Checkbox.css';\n\nimport type {\n CheckboxGroupProps,\n CheckboxGroupContextValue,\n} from './Checkbox.types';\n\nexport const CheckboxGroupContext =\n /*#__PURE__*/ createContext<CheckboxGroupContextValue | null>(null);\n\n/**\n * Groups multiple Checkbox components with shared state management.\n *\n * Manages a `string[]` value, propagates `disabled` and `size` to children\n * via React Context. Supports controlled and uncontrolled modes.\n *\n * @example\n * ```tsx\n * <CheckboxGroup\n * label=\"Render passes\"\n * value={selected}\n * onChange={setSelected}\n * >\n * <Checkbox value=\"diffuse\" label=\"Diffuse\" />\n * <Checkbox value=\"specular\" label=\"Specular\" />\n * <Checkbox value=\"shadow\" label=\"Shadow\" />\n * </CheckboxGroup>\n * ```\n */\nexport const CheckboxGroup: React.FC<CheckboxGroupProps> = ({\n value: valueProp,\n defaultValue = [],\n label,\n direction = 'column',\n gap = 2,\n disabled = false,\n size = 'md',\n helperText,\n error = false,\n errorMessage,\n required = false,\n children,\n onChange,\n className,\n style,\n testId,\n ref,\n id: idProp,\n ...rest\n}) => {\n const autoId = useId();\n const groupId = idProp ?? autoId;\n const labelId = `${groupId}-label`;\n const helperId = `${groupId}-helper`;\n\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue);\n const isControlled = valueProp !== undefined;\n const currentValue = isControlled ? valueProp : internalValue;\n\n const toggleValue = useCallback(\n (itemValue: string) => {\n const nextValue = currentValue.includes(itemValue)\n ? currentValue.filter(v => v !== itemValue)\n : [...currentValue, itemValue];\n\n if (!isControlled) {\n setInternalValue(nextValue);\n }\n onChange?.(nextValue);\n },\n [currentValue, isControlled, onChange]\n );\n\n const contextValue: CheckboxGroupContextValue = {\n groupValue: currentValue,\n toggleValue,\n disabled,\n size,\n };\n\n const showHelperText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={showHelperText ? helperId : undefined}\n className={cx(groupContainerStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {label && (\n <FormLabel id={labelId} required={required} disabled={disabled}>\n {label}\n </FormLabel>\n )}\n <CheckboxGroupContext.Provider value={contextValue}>\n <div\n className={groupItemsStyle}\n style={assignInlineVars({\n [groupDirectionVar]: direction,\n [groupGapVar]: `${8 * gap}px`,\n })}\n >\n {children}\n </div>\n </CheckboxGroupContext.Provider>\n {showHelperText && (\n <FormHelperText id={helperId} error={error}>\n {showHelperText}\n </FormHelperText>\n )}\n </div>\n );\n};\n\nCheckboxGroup.displayName = 'CheckboxGroup';\n"],"names":[],"mappings":";;;;;;;;;;AAsBE;AAEF;;;;;;;;;;;;;;;;;;AAkBG;AACI;AAqBL;AACA;AACA;AACA;;AAGA;;AAGA;AAEI;AACE;AACA;;;;AAKF;;AAKJ;AACE;;;;;AAMF;AAEA;;AAqBU;;AAaZ;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Code.js","sources":["../../../../../../src/components/primitives/Code/Code.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAUA;;;;;;;;;;AAUG;AACI;AAEH;AAWF;AAGF;;"}
1
+ {"version":3,"file":"Code.js","sources":["src/components/primitives/Code/Code.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { codeRecipe } from './Code.css';\n\nimport type { CodeProps } from './Code.types';\n\n/**\n * Small inline `<code>` primitive with theme-aware background and font.\n *\n * Complements `ChatCodeBlock` (block-level) — use `Code` for short inline\n * snippets inside sentences and markdown renderers.\n *\n * @example\n * ```tsx\n * <Text>Run <Code>npm install</Code> to add the package.</Text>\n * ```\n */\nexport const Code = /*#__PURE__*/ React.memo<CodeProps>(\n ({ children, size = 'sm', className, style, testId, ref, ...rest }) => {\n return (\n <code\n ref={ref}\n className={cx(codeRecipe({ size }), className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </code>\n );\n }\n);\n\nCode.displayName = 'Code';\n"],"names":[],"mappings":";;;;;;AAUA;;;;;;;;;;AAUG;AACI;AAEH;AAWF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Collapsible.js","sources":["../../../../../../src/components/primitives/Collapsible/Collapsible.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAmCA;AACE;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;;AAQH;AACE;AACA;AACA;;AAGF;;AAkBE;AACA;AACA;;AAGA;;AAGA;AACE;;AAEA;;;;AAMA;;AAGF;AACA;AACA;;AAGE;AACA;AACA;AACD;;AAGC;AACA;AACD;;;AAoBM;;AAOI;AAEC;AACD;;AAcF;AAeX;AAEA;;"}
1
+ {"version":3,"file":"Collapsible.js","sources":["src/components/primitives/Collapsible/Collapsible.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useId, useState } from 'react';\n\nimport { ChevronRightIcon } from '@/components/Icons/ChevronRightIcon';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n collapsibleRootStyle,\n triggerRecipe,\n triggerHeightVar,\n triggerPaddingVar,\n triggerFontSizeVar,\n chevronRecipe,\n chevronSizeVar,\n contentWrapperRecipe,\n contentInnerStyle,\n contentBodyStyle,\n contentPaddingVVar,\n contentPaddingHVar,\n} from './Collapsible.css';\n\nimport type { CollapsibleProps, CollapsibleSize } from './Collapsible.types';\n\n// --- Size maps ---\n\ninterface TriggerSizeConfig {\n height: string;\n padding: string;\n fontSize: string;\n chevronSize: number;\n}\n\nconst TRIGGER_SIZE_MAP: Record<CollapsibleSize, TriggerSizeConfig> = {\n sm: {\n height: '24px',\n padding: vars.spacing.md,\n fontSize: vars.typography.fontSize.xs,\n chevronSize: 10,\n },\n md: {\n height: '28px',\n padding: vars.spacing.md,\n fontSize: vars.typography.fontSize.sm,\n chevronSize: 12,\n },\n lg: {\n height: '32px',\n padding: vars.spacing.lg,\n fontSize: vars.typography.fontSize.md,\n chevronSize: 14,\n },\n};\n\ninterface ContentSizeConfig {\n paddingV: string;\n paddingH: string;\n}\n\nconst CONTENT_SIZE_MAP: Record<CollapsibleSize, ContentSizeConfig> = {\n sm: { paddingV: vars.spacing.sm, paddingH: vars.spacing.md },\n md: { paddingV: vars.spacing.md, paddingH: vars.spacing.lg },\n lg: { paddingV: vars.spacing.lg, paddingH: vars.spacing.xl },\n};\n\n// --- Component ---\n\nexport const Collapsible: React.FC<CollapsibleProps> = ({\n trigger,\n open: openProp,\n defaultOpen = false,\n size = 'sm',\n indicator,\n disabled = false,\n keepMounted = false,\n onChange,\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const autoId = useId();\n const triggerId = `collapsible-${autoId}-trigger`;\n const contentId = `collapsible-${autoId}-content`;\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = openProp !== undefined;\n const resolvedOpen = isControlled ? openProp : internalOpen;\n\n const handleToggle = useCallback(() => {\n if (disabled) return;\n\n const nextOpen = !resolvedOpen;\n\n if (!isControlled) {\n setInternalOpen(nextOpen);\n }\n\n onChange?.(nextOpen);\n }, [disabled, resolvedOpen, isControlled, onChange]);\n\n const showIndicator = indicator !== null;\n const sizeConfig = TRIGGER_SIZE_MAP[size];\n const contentConfig = CONTENT_SIZE_MAP[size];\n\n const triggerInlineVars = assignInlineVars({\n [triggerHeightVar]: sizeConfig.height,\n [triggerPaddingVar]: sizeConfig.padding,\n [triggerFontSizeVar]: sizeConfig.fontSize,\n });\n\n const contentInlineVars = assignInlineVars({\n [contentPaddingVVar]: contentConfig.paddingV,\n [contentPaddingHVar]: contentConfig.paddingH,\n });\n\n return (\n <div\n ref={ref}\n className={cx(collapsibleRootStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n <button\n type=\"button\"\n id={triggerId}\n aria-expanded={resolvedOpen}\n aria-controls={contentId}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n onClick={handleToggle}\n className={triggerRecipe({\n disabled: disabled || undefined,\n })}\n style={triggerInlineVars}\n >\n {showIndicator && (\n <span\n className={chevronRecipe({\n open: resolvedOpen || undefined,\n })}\n style={assignInlineVars({\n [chevronSizeVar]: `${sizeConfig.chevronSize}px`,\n })}\n >\n {indicator ?? (\n <ChevronRightIcon size={sizeConfig.chevronSize} decorative />\n )}\n </span>\n )}\n <span>{trigger}</span>\n </button>\n\n {(resolvedOpen || keepMounted) && (\n <div\n className={contentWrapperRecipe({\n open: resolvedOpen || undefined,\n })}\n role=\"region\"\n id={contentId}\n aria-labelledby={triggerId}\n hidden={!resolvedOpen || undefined}\n >\n <div className={contentInnerStyle}>\n <div className={contentBodyStyle} style={contentInlineVars}>\n {children}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\nCollapsible.displayName = 'Collapsible';\n"],"names":[],"mappings":";;;;;;;;;AAmCA;AACE;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;;AAQH;AACE;AACA;AACA;;AAGF;;AAkBE;AACA;AACA;;AAGA;;AAGA;AACE;;AAEA;;;;AAMA;;AAGF;AACA;AACA;;AAGE;AACA;AACA;AACD;;AAGC;AACA;AACD;;;AAoBM;;AAOI;AAEC;AACD;;AAcF;AAeX;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"HoverCard.js","sources":["../../../../../../src/components/primitives/HoverCard/HoverCard.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AAoCA;AACE;AAEF;AACE;;AAEE;;AAIF;AACF;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH;AAaE;AACA;AACA;;AAGA;AACA;AAEA;;;;;;AAMI;;;AAMF;AACA;AACA;AACA;AACA;AACD;AAED;;;;AAIE;AACD;AACD;AAEA;;;AAGC;AAED;;AAGI;;;;AAIA;;AAEA;;;AAGD;;;;;;;;;AAUA;AAGH;AAKF;AAEA;AAEA;AACE;AAEA;AAEA;AAEI;AACA;AACF;AAIF;AAAqC;AAErC;AAEA;AAGI;AACA;;AAED;AAEL;AAEA;AAEA;AAWE;;AAWA;AAEA;AAEI;AACA;AACA;;;AAEO;AACL;;;;;AAQF;;AAEA;AACA;;AAEA;;;;;;AAMF;AACF;AAEA;AAAa;;AAGb;AACE;AACE;;AAEJ;AACE;AACE;AACF;;AAGF;;;;AAWO;AAID;AACA;AACA;;AAUN;;;AAGA;AACF;AAEA;;AAQE;AACA;AACD;;"}
1
+ {"version":3,"file":"HoverCard.js","sources":["src/components/primitives/HoverCard/HoverCard.tsx"],"sourcesContent":["'use client';\n\nimport {\n autoUpdate,\n flip,\n offset as offsetMiddleware,\n safePolygon,\n shift,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n} from '@floating-ui/react';\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { cx } from '@/utils/cx';\n\nimport { hoverCardContentRecipe } from './HoverCard.css';\n\nimport type {\n HoverCardContentProps,\n HoverCardContextValue,\n HoverCardProps,\n HoverCardTriggerProps,\n} from './HoverCard.types';\n\nconst HoverCardContext =\n /*#__PURE__*/ createContext<HoverCardContextValue | null>(null);\n\nfunction useHoverCardContext(): HoverCardContextValue {\n const ctx = useContext(HoverCardContext);\n if (!ctx) {\n throw new Error(\n 'HoverCard compound components must be used within <HoverCard>'\n );\n }\n return ctx;\n}\n\n/**\n * A floating content container anchored to a trigger and shown on hover.\n * Cursor can move from the trigger onto the content without closing\n * (safe-polygon based). Also opens on keyboard focus for accessibility.\n *\n * @example\n * ```tsx\n * <HoverCard>\n * <HoverCard.Trigger>\n * <Link>@octocat</Link>\n * </HoverCard.Trigger>\n * <HoverCard.Content width={280}>\n * <UserPreview user={...} />\n * </HoverCard.Content>\n * </HoverCard>\n * ```\n */\nconst HoverCardRoot: React.FC<HoverCardProps> = ({\n open: openProp,\n defaultOpen = false,\n placement = 'bottom-start',\n offset = 8,\n openDelay = 400,\n closeDelay = 150,\n portal = true,\n disableSafePolygon = false,\n disabled = false,\n onOpenChange,\n children,\n}) => {\n const autoId = useId();\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = openProp !== undefined;\n const isOpen = disabled ? false : isControlled ? openProp : internalOpen;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean) => {\n if (disabled && nextOpen) return;\n if (!isControlled) {\n setInternalOpen(nextOpen);\n }\n onOpenChange?.(nextOpen);\n },\n [disabled, isControlled, onOpenChange]\n );\n\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: handleOpenChange,\n placement: placement,\n middleware: [offsetMiddleware(offset), flip(), shift({ padding: 8 })],\n whileElementsMounted: autoUpdate,\n });\n\n const hover = useHover(context, {\n enabled: !disabled,\n delay: { open: openDelay, close: closeDelay },\n handleClose: disableSafePolygon ? null : safePolygon(),\n move: false,\n });\n const focus = useFocus(context, { enabled: !disabled });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n hover,\n focus,\n ]);\n\n const contextValue: HoverCardContextValue = useMemo(\n () => ({\n isOpen,\n hoverCardId: autoId,\n portal,\n triggerRef,\n contentRef,\n floatingRefs: refs,\n floatingStyles,\n floatingContext: context,\n getReferenceProps,\n getFloatingProps,\n }),\n [\n isOpen,\n autoId,\n portal,\n refs,\n floatingStyles,\n context,\n getReferenceProps,\n getFloatingProps,\n ]\n );\n\n return (\n <HoverCardContext.Provider value={contextValue}>\n {children}\n </HoverCardContext.Provider>\n );\n};\n\nHoverCardRoot.displayName = 'HoverCard';\n\nconst HoverCardTrigger: React.FC<HoverCardTriggerProps> = ({ children }) => {\n const { isOpen, hoverCardId, triggerRef, floatingRefs, getReferenceProps } =\n useHoverCardContext();\n const contentId = `hovercard-${hoverCardId}-content`;\n\n const setRef = useCallback(\n (node: HTMLElement | null) => {\n triggerRef.current = node;\n floatingRefs.setReference(node);\n },\n [triggerRef, floatingRefs]\n );\n\n if (!React.isValidElement(children)) return null;\n\n const referenceProps = getReferenceProps();\n\n return React.cloneElement(\n children as React.ReactElement<Record<string, unknown>>,\n {\n ref: setRef,\n ...referenceProps,\n 'aria-describedby': isOpen ? contentId : undefined,\n }\n );\n};\n\nHoverCardTrigger.displayName = 'HoverCard.Trigger';\n\nconst HoverCardContent: React.FC<HoverCardContentProps> = ({\n children,\n width,\n maxHeight,\n padding = 'md',\n className,\n style,\n testId,\n ref: externalRef,\n ...rest\n}) => {\n const {\n isOpen,\n contentRef,\n portal,\n hoverCardId,\n floatingRefs,\n floatingStyles,\n getFloatingProps,\n } = useHoverCardContext();\n\n const [visible, setVisible] = useState(false);\n const contentId = `hovercard-${hoverCardId}-content`;\n\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n contentRef.current = node;\n floatingRefs.setFloating(node);\n if (typeof externalRef === 'function') {\n externalRef(node);\n } else if (externalRef && typeof externalRef === 'object') {\n externalRef.current = node;\n }\n },\n [contentRef, floatingRefs, externalRef]\n );\n\n useEffect(() => {\n if (isOpen) {\n const handle = requestAnimationFrame(() => {\n setVisible(true);\n });\n return () => {\n cancelAnimationFrame(handle);\n };\n }\n // Reset enter-animation state on close; gated by the `isOpen` prop, so this\n // is a one-shot transition rather than continuous state synchronization.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setVisible(false);\n return undefined;\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const dimensionStyles: React.CSSProperties = {};\n if (width != null) {\n dimensionStyles.width =\n typeof width === 'number' ? `${String(width)}px` : width;\n }\n if (maxHeight != null) {\n dimensionStyles.maxHeight =\n typeof maxHeight === 'number' ? `${String(maxHeight)}px` : maxHeight;\n dimensionStyles.overflowY = 'auto';\n }\n\n const floatingProps = getFloatingProps();\n\n const element = (\n <div\n ref={setRef}\n role=\"tooltip\"\n id={contentId}\n className={cx(\n hoverCardContentRecipe({\n padding,\n visible: visible || undefined,\n }),\n className\n )}\n style={{\n ...floatingStyles,\n ...dimensionStyles,\n ...style,\n }}\n data-testid={testId}\n {...floatingProps}\n {...rest}\n >\n {children}\n </div>\n );\n\n if (portal && typeof document !== 'undefined') {\n return createPortal(element, document.body);\n }\n return element;\n};\n\nHoverCardContent.displayName = 'HoverCard.Content';\n\ninterface HoverCardComponent extends React.FC<HoverCardProps> {\n Trigger: React.FC<HoverCardTriggerProps>;\n Content: React.FC<HoverCardContentProps>;\n}\n\nexport const HoverCard = Object.assign(HoverCardRoot, {\n Trigger: HoverCardTrigger,\n Content: HoverCardContent,\n}) as HoverCardComponent;\n"],"names":[],"mappings":";;;;;;;;AAoCA;AACE;AAEF;AACE;;AAEE;;AAIF;AACF;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH;AAaE;AACA;AACA;;AAGA;AACA;AAEA;;;;;;AAMI;;;AAMF;AACA;AACA;AACA;AACA;AACD;AAED;;;;AAIE;AACD;AACD;AAEA;;;AAGC;AAED;;AAGI;;;;AAIA;;AAEA;;;AAGD;;;;;;;;;AAUA;AAGH;AAKF;AAEA;AAEA;AACE;AAEA;AAEA;AAEI;AACA;AACF;AAIF;AAAqC;AAErC;AAEA;AAGI;AACA;;AAED;AAEL;AAEA;AAEA;AAWE;;AAWA;AAEA;AAEI;AACA;AACA;;;AAEO;AACL;;;;;AAQF;;AAEA;AACA;;AAEA;;;;;;AAMF;AACF;AAEA;AAAa;;AAGb;AACE;AACE;;AAEJ;AACE;AACE;AACF;;AAGF;;;;AAWO;AAID;AACA;AACA;;AAUN;;;AAGA;AACF;AAEA;;AAQE;AACA;AACD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.js","sources":["../../../../../../src/components/primitives/Icon/Icon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAgDA;;AAEG;AACH;;;;;;;;AAQC;AAED;AAEO;;AAaH;;AAGE;AACA;;;;AAKF;AAAsB;AACtB;AACE;AACA;;;;AASM;AACE;AAQA;AACH;AAeT;AAGF;;"}
1
+ {"version":3,"file":"Icon.js","sources":["src/components/primitives/Icon/Icon.tsx"],"sourcesContent":["'use client';\n\n// src/primitives/Icon/Icon.tsx\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { iconRecipe } from './Icon.css';\n\nimport type { Size } from '@/types/common';\nimport type { Prettify, LiteralUnion } from '@/types/utilities';\n\nexport type IconSize = LiteralUnion<Size> | number;\nexport type IconColor = LiteralUnion<\n 'primary' | 'secondary' | 'muted' | 'accent' | 'success' | 'warning' | 'error'\n>;\n\nexport interface IconBaseProps {\n children: React.ReactNode;\n /**\n * Icon size. `'sm' | 'md' | 'lg'` map to 12 / 16 / 20 px through the theme\n * recipe. Pass a `number` for a custom pixel size, or a `string` for any\n * CSS length (e.g. `'1.5em'`, `'24px'`).\n * @default \"md\"\n */\n size?: IconSize;\n /**\n * Icon color. Standard tokens (`'primary' | 'secondary' | 'muted' |\n * 'accent' | 'success' | 'warning' | 'error'`) map to theme variables;\n * any other string is forwarded as an inline `color` value (hex,\n * `currentColor`, `var(--…)`, etc.).\n * @default \"primary\"\n */\n color?: IconColor;\n className?: string;\n title?: string;\n decorative?: boolean;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<SVGSVGElement>;\n}\n\nexport type IconProps = Prettify<IconBaseProps>;\n\n/**\n * Standard color keys that map to recipe variants\n */\nconst STANDARD_COLORS = new Set([\n 'primary',\n 'secondary',\n 'muted',\n 'accent',\n 'success',\n 'warning',\n 'error',\n]);\n\nconst STANDARD_SIZES = new Set(['sm', 'md', 'lg']);\n\nexport const Icon = /*#__PURE__*/ React.memo<IconProps>(\n ({\n children,\n size = 'md',\n color = 'primary',\n className,\n title,\n decorative = false,\n testId,\n ref,\n ...props\n }) => {\n const isStandardColor = STANDARD_COLORS.has(color);\n const isStandardSize = typeof size === 'string' && STANDARD_SIZES.has(size);\n\n const resolvedSize = isStandardSize\n ? undefined\n : typeof size === 'number'\n ? `${size}px`\n : size;\n\n const inlineStyle: React.CSSProperties = {};\n if (!isStandardColor) inlineStyle.color = color;\n if (resolvedSize !== undefined) {\n inlineStyle.width = resolvedSize;\n inlineStyle.height = resolvedSize;\n }\n\n return (\n <svg\n ref={ref}\n className={cx(\n iconRecipe({\n size: isStandardSize ? (size as Size) : undefined,\n color: isStandardColor\n ? (color as\n | 'primary'\n | 'secondary'\n | 'muted'\n | 'accent'\n | 'success'\n | 'warning'\n | 'error')\n : undefined,\n }),\n className\n )}\n style={Object.keys(inlineStyle).length > 0 ? inlineStyle : undefined}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden={decorative}\n role={decorative ? 'presentation' : 'img'}\n data-testid={testId}\n {...props}\n >\n {title && !decorative && <title>{title}</title>}\n {children}\n </svg>\n );\n }\n);\n\nIcon.displayName = 'Icon';\n"],"names":[],"mappings":";;;;;;AAgDA;;AAEG;AACH;;;;;;;;AAQC;AAED;AAEO;;AAaH;;AAGE;AACA;;;;AAKF;AAAsB;AACtB;AACE;AACA;;;;AASM;AACE;AAQA;AACH;AAeT;AAGF;;"}
@@ -48,13 +48,15 @@ import { loadingSpinnerRecipe, iconButtonRecipe } from './IconButton.css.js';
48
48
  * </IconButton>
49
49
  * ```
50
50
  */
51
- const IconButton = /*#__PURE__*/ React.memo(({ children, className, size = 'md', variant = 'ghost', radius = 'md', disabled = false, loading = false, pressed = false, onClick, 'aria-label': ariaLabel, testId, style, ref, ...props }) => {
51
+ const IconButton = /*#__PURE__*/ React.memo(({ children, icon, className, size = 'md', variant = 'ghost', radius = 'md', disabled = false, loading = false, pressed = false, onClick, 'aria-label': ariaLabel, testId, style, ref, ...props }) => {
52
+ // `icon` mirrors Button's API; fall back to `children` for back-compat.
53
+ const glyph = icon ?? children;
52
54
  return (jsx("button", { ref: ref, className: cx(iconButtonRecipe({
53
55
  size,
54
56
  variant,
55
57
  radius,
56
58
  pressed: pressed || undefined,
57
- }), className), disabled: disabled || loading, onClick: onClick, "aria-label": ariaLabel, "aria-pressed": pressed, "data-testid": testId, style: style, ...props, children: loading ? (jsx("div", { className: loadingSpinnerRecipe({ size }) })) : (children) }));
59
+ }), className), disabled: disabled || loading, onClick: onClick, "aria-label": ariaLabel, "aria-pressed": pressed, "data-testid": testId, style: style, ...props, children: loading ? jsx("div", { className: loadingSpinnerRecipe({ size }) }) : glyph }));
58
60
  });
59
61
  IconButton.displayName = 'IconButton';
60
62
 
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.js","sources":["../../../../../../src/components/primitives/IconButton/IconButton.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAqHA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CG;AACI;;;;;;;AA4CL;AAGF;;"}
1
+ {"version":3,"file":"IconButton.js","sources":["src/components/primitives/IconButton/IconButton.tsx"],"sourcesContent":["'use client';\n\n// src/primitives/IconButton/IconButton.tsx\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { iconButtonRecipe, loadingSpinnerRecipe } from './IconButton.css';\n\nimport type { Size, Variant } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\n\n/**\n * Standard size variants for IconButton using library sizing.\n */\nexport type IconButtonSize = Size;\n\n/**\n * Visual variants for IconButton - strict typing for controlled API.\n */\nexport type IconButtonVariant = Variant;\n\n/**\n * Border radius variants for IconButton shape control.\n */\nexport type IconButtonRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';\n\nexport interface IconButtonBaseProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'css' | 'children'\n> {\n /**\n * Icon component to display inside the button.\n * Should be an Icon component or similar icon element.\n * The button will automatically size itself based on the icon size.\n *\n * Equivalent to the `icon` prop — provide the glyph either way. When both are\n * set, `icon` wins. Kept optional so `<IconButton icon={…} />` matches\n * `Button`'s `icon` API.\n *\n * @example <SaveIcon />, <AddIcon />\n */\n children?: React.ReactNode;\n\n /**\n * Icon element to display inside the button, mirroring `Button`'s `icon`\n * prop so the two components share one API. Takes precedence over\n * `children` when both are provided.\n *\n * @example <SaveIcon />, <AddIcon />\n */\n icon?: React.ReactNode;\n\n /**\n * Button size using standard library sizing\n * Button will be square and sized appropriately for the icon\n * - `sm`: 20px square (for 12px icons)\n * - `md`: 24px square (for 16px icons)\n * - `lg`: 32px square (for 20px icons)\n * @default \"md\"\n */\n size?: IconButtonSize;\n\n /**\n * Button visual variant\n * - `default`: Transparent with border, fills on hover\n * - `ghost`: No border, subtle hover state\n * - `filled`: Solid background with accent color\n * @default \"ghost\"\n */\n variant?: IconButtonVariant;\n\n /**\n * Border radius for button shape control\n * - `none`: Sharp corners (0px)\n * - `sm`: Slightly rounded (2px)\n * - `md`: Moderately rounded (4px)\n * - `lg`: More rounded (6px)\n * - `full`: Fully circular\n * @default \"md\"\n */\n radius?: IconButtonRadius;\n\n /**\n * Whether the button is disabled\n * When true, button becomes non-interactive with reduced opacity\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Whether the button is in a loading state\n * Shows spinner and disables interaction\n * @default false\n */\n loading?: boolean;\n\n /**\n * Whether the button appears pressed/active\n * Useful for toggle states and active tool indicators\n * @default false\n */\n pressed?: boolean;\n\n /**\n * Accessible label for screen readers\n * Required for proper accessibility\n * @example \"Save file\", \"Delete item\", \"Close dialog\"\n */\n 'aria-label': string;\n\n /**\n * Click event handler\n * Called when button is clicked (not when disabled/loading)\n */\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Props for the IconButton component with prettified type for better IntelliSense\n */\nexport type IconButtonProps = Prettify<IconButtonBaseProps>;\n\n/**\n * A specialized square button component for displaying icons in editor interfaces.\n *\n * Designed for toolbar actions, quick controls, and icon-based interactions.\n * Always square and sized appropriately for the contained icon.\n * Supports various border radius options from sharp corners to fully circular.\n *\n * @example\n * ```tsx\n * // Basic ghost button (default)\n * <IconButton aria-label=\"Save file\">\n * <SaveIcon />\n * </IconButton>\n *\n * // Circular filled button\n * <IconButton\n * variant=\"filled\"\n * radius=\"full\"\n * size=\"lg\"\n * aria-label=\"Add item\"\n * >\n * <AddIcon />\n * </IconButton>\n *\n * // Sharp corners for toolbar\n * <IconButton\n * variant=\"default\"\n * radius=\"none\"\n * aria-label=\"Settings\"\n * >\n * <SettingsIcon />\n * </IconButton>\n *\n * // Toggle state\n * <IconButton\n * pressed={isVisible}\n * radius=\"sm\"\n * aria-label=\"Toggle visibility\"\n * onClick={toggleVisibility}\n * >\n * <EyeIcon />\n * </IconButton>\n * ```\n */\nexport const IconButton = /*#__PURE__*/ React.memo<IconButtonProps>(\n ({\n children,\n icon,\n className,\n size = 'md',\n variant = 'ghost',\n radius = 'md',\n disabled = false,\n loading = false,\n pressed = false,\n onClick,\n 'aria-label': ariaLabel,\n testId,\n style,\n ref,\n ...props\n }) => {\n // `icon` mirrors Button's API; fall back to `children` for back-compat.\n const glyph = icon ?? children;\n return (\n <button\n ref={ref}\n className={cx(\n iconButtonRecipe({\n size,\n variant,\n radius,\n pressed: pressed || undefined,\n }),\n className\n )}\n disabled={disabled || loading}\n onClick={onClick}\n aria-label={ariaLabel}\n aria-pressed={pressed}\n data-testid={testId}\n style={style}\n {...props}\n >\n {loading ? <div className={loadingSpinnerRecipe({ size })} /> : glyph}\n </button>\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n"],"names":[],"mappings":";;;;;;AAkIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CG;AACI;;AAmBH;;;;;;;AAwBF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sources":["../../../../../../src/components/primitives/Input/Input.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;AAoJA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCG;AACI;AAyBL;AACA;AAEA;;AAEE;AACF;AAEA;;AAEE;AACF;AAEA;;AAEA;;;;;;AAoBO;AAiCT;AAEA;;"}
1
+ {"version":3,"file":"Input.js","sources":["src/components/primitives/Input/Input.tsx"],"sourcesContent":["'use client';\n\n// src/primitives/Input/Input.tsx\nimport React from 'react';\n\nimport { inputWrapperRecipe } from '@/components/form/InputWrapper.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n inputContainerStyle,\n labelRecipe,\n inputRecipe,\n iconStartStyle,\n iconEndStyle,\n helperTextRecipe,\n} from './Input.css';\n\nimport type { Size } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\n\n/**\n * Standard input sizes using library sizing.\n */\nexport type InputSize = Size;\n\nexport interface InputBaseProps extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'size' | 'css'\n> {\n /**\n * Input value (controlled)\n */\n value?: string | undefined;\n\n /**\n * Default value (uncontrolled)\n */\n defaultValue?: string | undefined;\n\n /**\n * Placeholder text\n */\n placeholder?: string | undefined;\n\n /**\n * Input type\n */\n type?:\n | 'text'\n | 'email'\n | 'password'\n | 'number'\n | 'search'\n | 'url'\n | 'tel'\n | undefined;\n\n /**\n * Input size using standard library sizing\n * - `sm`: 20px height, compact for toolbars\n * - `md`: 24px height, standard for forms\n * - `lg`: 32px height, prominent inputs\n * @default \"md\"\n */\n size?: InputSize;\n\n /**\n * Whether the input is disabled\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Whether the input has an error state\n * @default false\n */\n error?: boolean;\n\n /**\n * Whether the input is required\n * @default false\n */\n required?: boolean;\n\n /**\n * Whether the input is read-only\n * @default false\n */\n readOnly?: boolean;\n\n /**\n * Input label\n */\n label?: string | undefined;\n\n /**\n * Helper text displayed below the input\n */\n helperText?: string | undefined;\n\n /**\n * Error message displayed when error is true\n */\n errorMessage?: string | undefined;\n\n /**\n * Icon displayed at the start of the input\n */\n startIcon?: React.ReactNode;\n\n /**\n * Icon displayed at the end of the input\n */\n endIcon?: React.ReactNode;\n\n /**\n * Change event handler — receives the new string value directly\n */\n onChange?: (value: string) => void;\n\n /**\n * Focus event handler\n */\n onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;\n\n /**\n * Blur event handler\n */\n onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;\n\n /**\n * Key down event handler\n */\n onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<HTMLInputElement>;\n}\n\n/**\n * Props for the Input component with prettified type for better IntelliSense\n */\nexport type InputProps = Prettify<InputBaseProps>;\n\n/**\n * A versatile input component for text entry in editor interfaces.\n *\n * Provides a clean, consistent text input with support for labels, helper text,\n * icons, and various states. Optimized for editor UIs with compact sizing.\n *\n * @example\n * ```tsx\n * // Basic text input\n * <Input\n * placeholder=\"Enter text...\"\n * value={text}\n * onChange={setText}\n * />\n *\n * // With label and helper text\n * <Input\n * label=\"Project Name\"\n * placeholder=\"My Project\"\n * helperText=\"Choose a unique name for your project\"\n * value={name}\n * onChange={setName}\n * />\n *\n * // With icons and error state\n * <Input\n * label=\"Email\"\n * type=\"email\"\n * startIcon={<SearchIcon />}\n * error={!!emailError}\n * errorMessage={emailError}\n * value={email}\n * onChange={setEmail}\n * />\n * ```\n */\nexport const Input: React.FC<InputProps> = ({\n value,\n defaultValue,\n placeholder,\n type = 'text',\n size = 'md',\n disabled = false,\n error = false,\n required = false,\n readOnly = false,\n label,\n helperText,\n errorMessage,\n startIcon,\n endIcon,\n className,\n style,\n onChange,\n onFocus,\n onBlur,\n onKeyDown,\n testId,\n ref,\n ...props\n}) => {\n const [focused, setFocused] = React.useState(false);\n const inputId = React.useId();\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n setFocused(true);\n onFocus?.(event);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n setFocused(false);\n onBlur?.(event);\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(event.target.value);\n };\n\n return (\n <div className={cx(inputContainerStyle, className)} style={style}>\n {label && (\n <label\n htmlFor={inputId}\n className={labelRecipe({ disabled: disabled || undefined })}\n >\n {label}\n {required && <span style={{ color: 'var(--accent-error)' }}> *</span>}\n </label>\n )}\n\n <div\n className={inputWrapperRecipe({\n size,\n error,\n disabled,\n focused,\n })}\n >\n {startIcon && <div className={iconStartStyle}>{startIcon}</div>}\n\n <input\n ref={ref}\n id={inputId}\n type={type}\n value={value}\n defaultValue={defaultValue}\n placeholder={placeholder}\n disabled={disabled}\n required={required}\n readOnly={readOnly}\n className={inputRecipe({ size })}\n onChange={onChange ? handleChange : undefined}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n data-testid={testId}\n {...props}\n />\n\n {endIcon && <div className={iconEndStyle}>{endIcon}</div>}\n </div>\n\n {(helperText ?? (error && errorMessage)) && (\n <div className={helperTextRecipe({ error: error || undefined })}>\n {error && errorMessage ? errorMessage : helperText}\n </div>\n )}\n </div>\n );\n};\n\nInput.displayName = 'Input';\n"],"names":[],"mappings":";;;;;;;AAoJA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCG;AACI;AAyBL;AACA;AAEA;;AAEE;AACF;AAEA;;AAEE;AACF;AAEA;;AAEA;;;;;;AAoBO;AAiCT;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Kbd.js","sources":["../../../../../../src/components/primitives/Kbd/Kbd.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;AAYA;AACE;AACE;;;AAIJ;AAEA;;;;;;;;;;;AAWG;;;;AAmBG;AACE;;AAEJ;AAEA;AACA;AAEA;AACE;AACE;;AAGF;AACF;;AA0BF;AAGF;;"}
1
+ {"version":3,"file":"Kbd.js","sources":["src/components/primitives/Kbd/Kbd.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\n\nimport { cx } from '@/utils/cx';\nimport { getKeyGlyph, getPlatform, parseShortcut } from '@/utils/platform';\n\nimport { kbdRoot, keycapRecipe, separatorStyle } from './Kbd.css';\n\nimport type { KbdProps } from './Kbd.types';\nimport type { Platform } from '@/utils/platform';\n\nfunction getKeys(children: React.ReactNode): React.ReactNode[] {\n if (typeof children === 'string') {\n return parseShortcut(children);\n }\n\n return React.Children.toArray(children);\n}\n\n/**\n * Render keyboard shortcuts with consistent keycap styling and platform-aware glyphs.\n *\n * Use Kbd for shortcut hints in menus, tooltips, command palettes, help overlays,\n * and keyboard reference panels.\n *\n * @example\n * ```tsx\n * <Kbd>Ctrl+S</Kbd>\n * <Kbd platform=\"mac\" separator={null}>Cmd+S</Kbd>\n * ```\n */\nexport const Kbd = /*#__PURE__*/ React.memo<KbdProps>(\n ({\n children,\n size = 'md',\n variant = 'outline',\n glyphs = true,\n platform = 'auto',\n separator = '+',\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const [platformDetected, setPlatformDetected] =\n useState<Platform>('windows');\n\n useEffect(() => {\n if (platform === 'auto') {\n setPlatformDetected(getPlatform());\n }\n }, [platform]);\n\n const platformResolved = platform === 'auto' ? platformDetected : platform;\n const keys = useMemo(() => getKeys(children), [children]);\n\n const renderKey = (key: React.ReactNode): React.ReactNode => {\n if (glyphs && typeof key === 'string') {\n return getKeyGlyph(key, platformResolved);\n }\n\n return key;\n };\n\n return (\n <span\n ref={ref}\n className={cx(kbdRoot, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {keys.map((key, index) => (\n <React.Fragment\n key={`${typeof key === 'string' ? key : index}-${index}`}\n >\n {index > 0 && separator !== null && (\n <span className={separatorStyle} aria-hidden=\"true\">\n {separator}\n </span>\n )}\n <kbd className={keycapRecipe({ size, variant })}>\n {renderKey(key)}\n </kbd>\n </React.Fragment>\n ))}\n </span>\n );\n }\n);\n\nKbd.displayName = 'Kbd';\n"],"names":[],"mappings":";;;;;;;AAYA;AACE;AACE;;;AAIJ;AAEA;;;;;;;;;;;AAWG;;;;AAmBG;AACE;;AAEJ;AAEA;AACA;AAEA;AACE;AACE;;AAGF;AACF;;AA0BF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Link.js","sources":["../../../../../../src/components/primitives/Link/Link.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AAmBA;AAEA;;;AAGG;AACH;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACE;AACA;AACD;AACD;AACE;AACA;AACD;AACD;AACE;AACA;AACD;;AAGH;AACE;AACA;AAAW;;AAEb;AAEA;;;;;;;AAOG;AACH;;;;;;;;;;;;;;;;;;;;AAqBA;;AAIE;AACE;;;AAGA;;AAEF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACH;AAGE;AAkBA;AACA;AACA;;;;;;;;AAWE;;;;;AAMD;;;;;AAMD;;AAGE;;;;;;;;;;AAcA;AACI;;AAEE;AACH;;AAGL;AAEI;AACA;AACA;;;AAMJ;AA4BF;AAiBO;AACP;;"}
1
+ {"version":3,"file":"Link.js","sources":["src/components/primitives/Link/Link.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React from 'react';\n\nimport { ExternalLinkIcon } from '@/components/Icons/ExternalLinkIcon';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n externalIconStyle,\n linkColorVar,\n linkHoverColorVar,\n linkRecipe,\n srOnlyStyle,\n} from './Link.css';\n\nimport type { LinkColor, LinkProps, LinkVariant } from './Link.types';\n\nconst EXTERNAL_PROTOCOL_RE = /^https?:\\/\\//i;\n\n/**\n * Defaults — keep variant and color in sync so consumers can pass either\n * (or both) without surprising results.\n */\nconst VARIANT_DEFAULT_COLOR: Record<LinkVariant, LinkColor> = {\n default: 'primary',\n subtle: 'secondary',\n inline: 'inherit',\n};\n\nconst VARIANT_DEFAULT_UNDERLINE = {\n default: 'hover',\n subtle: 'hover',\n inline: 'always',\n} as const;\n\nconst NAMED_COLOR_TOKENS: Record<string, { base: string; hover: string }> = {\n primary: {\n base: vars.colors.accent.primary,\n hover: vars.colors.accent.secondary,\n },\n secondary: {\n base: vars.colors.text.secondary,\n hover: vars.colors.accent.primary,\n },\n inherit: {\n base: 'inherit',\n hover: vars.colors.accent.primary,\n },\n};\n\nfunction resolveLinkColor(color: LinkColor): { base: string; hover: string } {\n const named = NAMED_COLOR_TOKENS[color];\n if (named) return named;\n return { base: color, hover: color };\n}\n\n/**\n * Props stripped from the rest spread when the link is disabled.\n *\n * Without this, `<Link as={RouterLink} disabled to=\"/x\" onClick={fn} />`\n * would still navigate / fire the handler — `aria-disabled` and CSS\n * pointer-events alone don't block keyboard activation or programmatic\n * triggers fired by router libraries.\n */\nconst NAV_PROPS_TO_STRIP_WHEN_DISABLED = [\n 'href',\n 'to',\n 'onClick',\n 'onClickCapture',\n 'onPointerDown',\n 'onPointerDownCapture',\n 'onMouseDown',\n 'onMouseDownCapture',\n 'onKeyDown',\n 'onKeyDownCapture',\n 'onKeyUp',\n 'onKeyUpCapture',\n 'onAuxClick',\n 'replace',\n 'reloadDocument',\n 'preventScrollReset',\n 'state',\n 'relative',\n] as const;\n\nfunction stripNavProps(\n props: Record<string, unknown>\n): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if ((NAV_PROPS_TO_STRIP_WHEN_DISABLED as readonly string[]).includes(key)) {\n continue;\n }\n cleaned[key] = value;\n }\n return cleaned;\n}\n\n/**\n * Styled anchor primitive.\n *\n * Standardises link color, underline behavior, hover/focus states, and\n * external-link affordances. Polymorphic via `as` so it can wrap a\n * router's link component (react-router, TanStack Router, Next.js).\n *\n * Scope: **styling-only**, not router-aware. Pass your router's link\n * component via `as` for client-side navigation — the router's props\n * (`to`, `replace`, …) are type-checked automatically.\n *\n * @example\n * ```tsx\n * <Link href=\"/docs\">Documentation</Link>\n *\n * <Link href=\"https://example.com\">External</Link> // auto-detected\n *\n * <Link as={RouterLink} to=\"/profile\">\n * Profile\n * </Link>\n *\n * <Text>\n * Read the <Link variant=\"inline\" href=\"/guide\">guide</Link> first.\n * </Text>\n * ```\n */\nfunction LinkImpl<E extends React.ElementType = 'a'>(\n props: LinkProps<E>\n): React.ReactElement {\n const {\n href,\n as,\n variant,\n color,\n underline,\n size,\n external,\n disabled,\n children,\n className,\n style,\n testId,\n ref,\n 'aria-label': ariaLabel,\n ...rest\n } = props;\n\n const resolvedVariant: LinkVariant = variant ?? 'default';\n const resolvedSize = size ?? 'md';\n const isDisabled = disabled === true;\n const resolvedColor = color ?? VARIANT_DEFAULT_COLOR[resolvedVariant];\n const resolvedUnderline =\n underline ?? VARIANT_DEFAULT_UNDERLINE[resolvedVariant];\n\n // External affordances only apply when the link is actually navigable.\n // A disabled link with `external` would be misleading: no target, no\n // rel, no real navigation — but icon + \"opens in new tab\" suggest\n // otherwise. So we suppress all of it.\n const isExternal =\n !isDisabled &&\n (external ?? (typeof href === 'string' && EXTERNAL_PROTOCOL_RE.test(href)));\n\n const { base, hover } = resolveLinkColor(resolvedColor);\n const inlineVars = assignInlineVars({\n [linkColorVar]: base,\n [linkHoverColorVar]: hover,\n });\n\n // Disabled forces a non-navigating <span> regardless of `as`. If we\n // honored `as` while disabled, a router link would still respond to\n // `to` / `onClick` because pointer-events: none and aria-disabled are\n // visual hints, not functional locks for programmatic triggers.\n const Component: React.ElementType = isDisabled ? 'span' : (as ?? 'a');\n\n const cleanedRest = isDisabled\n ? stripNavProps(rest)\n : (rest as Record<string, unknown>);\n\n // Only set `href` when rendering a plain anchor and not disabled. For\n // custom `as` components (router links) the navigation prop is the\n // router's own (`to`, `href`, …), passed through `...rest`.\n const hrefProp =\n !isDisabled && Component === 'a' && href !== undefined ? { href } : {};\n\n const externalAttrs = isExternal\n ? { target: '_blank', rel: 'noopener noreferrer' }\n : {};\n\n const ariaLabelProp = ariaLabel\n ? {\n 'aria-label': isExternal\n ? `${ariaLabel} (opens in new tab)`\n : ariaLabel,\n }\n : {};\n\n const linkClassName = cx(\n linkRecipe({\n variant: resolvedVariant,\n underline: resolvedUnderline,\n size: resolvedSize,\n disabled: isDisabled || undefined,\n }),\n className\n );\n\n return (\n <Component\n {...cleanedRest}\n {...hrefProp}\n {...externalAttrs}\n {...ariaLabelProp}\n ref={ref}\n className={linkClassName}\n style={{ ...inlineVars, ...style }}\n data-testid={testId}\n data-disabled={isDisabled || undefined}\n aria-disabled={isDisabled || undefined}\n >\n {children}\n {isExternal && (\n <>\n <ExternalLinkIcon\n className={externalIconStyle}\n size=\"0.75em\"\n decorative\n />\n {!ariaLabel && (\n <span className={srOnlyStyle}> (opens in new tab)</span>\n )}\n </>\n )}\n </Component>\n );\n}\n\n/**\n * Public Link signature.\n *\n * Modelled as a callable interface so the polymorphic generic\n * (`<Link as={RouterLink} to=\"/x\" />`) survives the export. `React.memo`\n * is intentionally not applied here — wrapping a generic function in\n * `memo` collapses the call signature and forces an `as unknown as` cast,\n * which the codebase forbids. The library has precedent for non-memoised\n * primitives (e.g. `Switch`), and Link's render is cheap.\n */\ninterface LinkComponent {\n <E extends React.ElementType = 'a'>(props: LinkProps<E>): React.ReactElement;\n displayName?: string;\n}\n\nexport const Link = LinkImpl as LinkComponent;\nLink.displayName = 'Link';\n"],"names":[],"mappings":";;;;;;;;AAmBA;AAEA;;;AAGG;AACH;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACE;AACA;AACD;AACD;AACE;AACA;AACD;AACD;AACE;AACA;AACD;;AAGH;AACE;AACA;AAAW;;AAEb;AAEA;;;;;;;AAOG;AACH;;;;;;;;;;;;;;;;;;;;AAqBA;;AAIE;AACE;;;AAGA;;AAEF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACH;AAGE;AAkBA;AACA;AACA;;;;;;;;AAWE;;;;;AAMD;;;;;AAMD;;AAGE;;;;;;;;;;AAcA;AACI;;AAEE;AACH;;AAGL;AAEI;AACA;AACA;;;AAMJ;AA4BF;AAiBO;AACP;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Paper.js","sources":["../../../../../../src/components/primitives/Paper/Paper.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAwGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CG;;AAgBC;AAEI;AACI;;AAGI;AACL;;;;;;;;;AAuBT;AAGF;;"}
1
+ {"version":3,"file":"Paper.js","sources":["src/components/primitives/Paper/Paper.tsx"],"sourcesContent":["'use client';\n\n// src/components/primitives/Paper/Paper.tsx\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { paperRecipe } from './Paper.css';\n\nimport type { Prettify } from '@/types/utilities';\n\n/**\n * Paper elevation levels (shadow intensity)\n */\nexport type PaperElevation = 0 | 1 | 2 | 3;\n\n/**\n * Paper nesting levels for automatic background adjustment\n * Higher levels get progressively lighter backgrounds\n */\nexport type PaperNestLevel = 0 | 1 | 2 | 3;\n\n/**\n * Paper spacing variants based on theme spacing tokens\n */\nexport type PaperSpacing = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'xxxl';\n\nexport interface PaperBaseProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'css'\n> {\n /**\n * Paper content - any React elements\n */\n children?: React.ReactNode;\n\n /**\n * Paper elevation level controlling shadow intensity\n * - `0`: No shadow (flat)\n * - `1`: Small shadow (subtle depth)\n * - `2`: Medium shadow (moderate depth)\n * - `3`: Large shadow (high depth)\n * @default 1\n */\n elevation?: PaperElevation;\n\n /**\n * Whether to show border around the paper\n * Uses theme border color with subtle opacity\n * @default false\n */\n bordered?: boolean;\n\n /**\n * Internal padding using theme spacing tokens\n * - `xs`: 2px padding\n * - `sm`: 4px padding\n * - `md`: 8px padding (default)\n * - `lg`: 12px padding\n * - `xl`: 16px padding\n * - `xxl`: 24px padding\n * - `xxxl`: 32px padding\n * @default \"md\"\n */\n padding?: PaperSpacing;\n\n /**\n * Nesting level for automatic background adjustment\n * Higher levels get progressively lighter backgrounds for better visual hierarchy\n * - `0`: Primary background (darkest)\n * - `1`: Secondary background\n * - `2`: Tertiary background\n * - `3`: Elevated background (lightest)\n * @default 0\n */\n nestLevel?: PaperNestLevel;\n\n /**\n * Whether the paper should expand to fill available space\n * Sets width and height to 100%\n * @default false\n */\n expand?: boolean;\n\n /**\n * Custom border radius override\n * Overrides default theme border radius if provided\n * @example \"8px\", \"50%\", \"0\"\n */\n customRadius?: string | number;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Props for the Paper component with prettified type for better IntelliSense\n */\nexport type PaperProps = Prettify<PaperBaseProps>;\n\n/**\n * A versatile paper component providing surface elevation and visual hierarchy.\n *\n * Perfect for creating cards, panels, modals, and any content that needs to stand out\n * from the background. Supports elevation shadows, automatic background adjustment\n * for nested components, and flexible spacing control.\n *\n * @example\n * ```tsx\n * // Basic paper with elevation\n * <Paper elevation={2} padding=\"lg\">\n * <h3>Card Title</h3>\n * <p>Card content goes here</p>\n * </Paper>\n *\n * // Nested papers with automatic background adjustment\n * <Paper nestLevel={0} padding=\"xl\">\n * <h2>Main Container</h2>\n * <Paper nestLevel={1} padding=\"lg\">\n * <h3>Nested Section</h3>\n * <Paper nestLevel={2} padding=\"md\">\n * <p>Deeply nested content</p>\n * </Paper>\n * </Paper>\n * </Paper>\n *\n * // Bordered paper without shadow\n * <Paper elevation={0} bordered padding=\"md\">\n * <p>Subtle outlined container</p>\n * </Paper>\n *\n * // Full-width expanded paper\n * <Paper expand elevation={1} padding=\"lg\">\n * <header>Full width header</header>\n * <main>Main content area</main>\n * </Paper>\n *\n * // Custom radius paper\n * <Paper elevation={2} customRadius=\"12px\" padding=\"lg\">\n * <p>Paper with custom border radius</p>\n * </Paper>\n *\n * // Compact paper for small UI elements\n * <Paper elevation={1} padding=\"xs\">\n * <Icon name=\"settings\" />\n * </Paper>\n * ```\n */\nexport const Paper = /*#__PURE__*/ React.memo<PaperProps>(\n ({\n children,\n elevation = 1,\n bordered = false,\n padding = 'md',\n nestLevel = 0,\n expand = false,\n customRadius,\n className,\n testId,\n style,\n ref,\n ...htmlProps\n }) => {\n const customRadiusStyle =\n customRadius !== undefined\n ? {\n borderRadius:\n typeof customRadius === 'number'\n ? `${customRadius}px`\n : customRadius,\n }\n : undefined;\n\n return (\n <div\n ref={ref}\n className={cx(\n paperRecipe({\n elevation,\n bordered: bordered || undefined,\n padding,\n nestLevel,\n expand: expand || undefined,\n }),\n className\n )}\n data-testid={testId}\n style={{ ...customRadiusStyle, ...style }}\n {...htmlProps}\n >\n {children}\n </div>\n );\n }\n);\n\nPaper.displayName = 'Paper';\n"],"names":[],"mappings":";;;;;;AAwGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CG;;AAgBC;AAEI;AACI;;AAGI;AACL;;;;;;;;;AAuBT;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.js","sources":["../../../../../../src/components/primitives/Popover/Popover.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAwBA;AAEA;;AAKE;;AAEE;;AAIF;AACF;AAEA;AAEA;;;;;;;;;;;;;;;;;;AAkBG;;AAcD;AACA;AACA;;AAGA;;AAGA;;;;AAKI;AACF;AAIF;;AAEA;AAEA;;;AAGI;;AAEJ;AAEA;;AAEI;;;AAEA;;;;;AAMF;AACA;AACA;AACA;AACA;AACD;;AAGD;AACA;AACE;AACA;AACD;AAED;;;AAGC;AAED;;AAGI;AACA;;;;;;;;AAQA;;AAEA;;AAEA;;;AAGD;;;;;;;;;;;;;;;AAgBA;AAGH;AAKF;AAEA;;"}
1
+ {"version":3,"file":"Popover.js","sources":["src/components/primitives/Popover/Popover.tsx"],"sourcesContent":["'use client';\n\nimport {\n useFloating,\n offset as offsetMiddleware,\n flip,\n shift,\n autoUpdate,\n useClick,\n useDismiss,\n useInteractions,\n} from '@floating-ui/react';\nimport React, {\n createContext,\n useCallback,\n useContext,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport type { PopoverContextValue, PopoverProps } from './Popover.types';\n\n// --- Context ---\n\nconst PopoverContext = /*#__PURE__*/ createContext<PopoverContextValue | null>(\n null\n);\n\nexport function usePopoverContext(): PopoverContextValue {\n const ctx = useContext(PopoverContext);\n if (!ctx) {\n throw new Error(\n 'Popover compound components must be used within <Popover>'\n );\n }\n return ctx;\n}\n\n// --- Component ---\n\n/**\n * Popover component — a floating content container for interactive content\n * anchored to a trigger element.\n *\n * Uses @floating-ui/react for robust positioning with collision detection,\n * flip/shift behavior, and scroll-aware auto-updating.\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger>\n * <Button>Open</Button>\n * </PopoverTrigger>\n * <PopoverContent>\n * <p>Popover content</p>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nexport const Popover: React.FC<PopoverProps> = ({\n open: openProp,\n defaultOpen = false,\n placement = 'bottom-start',\n offset = 8,\n closeOnClickOutside = true,\n closeOnEscape = true,\n returnFocus = true,\n portal = true,\n matchTriggerWidth = false,\n children,\n onOpenChange,\n}) => {\n const autoId = useId();\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = openProp !== undefined;\n const isOpen = isControlled ? openProp : internalOpen;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) {\n setInternalOpen(nextOpen);\n }\n onOpenChange?.(nextOpen);\n },\n [isControlled, onOpenChange]\n );\n\n const openPopover = useCallback(() => {\n handleOpenChange(true);\n }, [handleOpenChange]);\n\n const closePopover = useCallback(() => {\n handleOpenChange(false);\n if (returnFocus) {\n triggerRef.current?.focus();\n }\n }, [handleOpenChange, returnFocus]);\n\n const toggle = useCallback(() => {\n if (isOpen) {\n closePopover();\n } else {\n openPopover();\n }\n }, [isOpen, openPopover, closePopover]);\n\n // Floating UI setup\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: handleOpenChange,\n placement: placement,\n middleware: [offsetMiddleware(offset), flip(), shift({ padding: 8 })],\n whileElementsMounted: autoUpdate,\n });\n\n // Interactions\n const click = useClick(context);\n const dismiss = useDismiss(context, {\n outsidePress: closeOnClickOutside,\n escapeKey: closeOnEscape,\n });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n click,\n dismiss,\n ]);\n\n const contextValue: PopoverContextValue = useMemo(\n () => ({\n isOpen,\n open: openPopover,\n close: closePopover,\n toggle,\n triggerRef,\n contentRef,\n placement,\n offset,\n portal,\n matchTriggerWidth,\n popoverId: autoId,\n // Floating UI context\n floatingRefs: refs,\n floatingStyles,\n floatingContext: context,\n getReferenceProps,\n getFloatingProps,\n }),\n [\n isOpen,\n openPopover,\n closePopover,\n toggle,\n placement,\n offset,\n portal,\n matchTriggerWidth,\n autoId,\n refs,\n floatingStyles,\n context,\n getReferenceProps,\n getFloatingProps,\n ]\n );\n\n return (\n <PopoverContext.Provider value={contextValue}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\nPopover.displayName = 'Popover';\n"],"names":[],"mappings":";;;;;AAwBA;AAEA;;AAKE;;AAEE;;AAIF;AACF;AAEA;AAEA;;;;;;;;;;;;;;;;;;AAkBG;;AAcD;AACA;AACA;;AAGA;;AAGA;;;;AAKI;AACF;AAIF;;AAEA;AAEA;;;AAGI;;AAEJ;AAEA;;AAEI;;;AAEA;;;;;AAMF;AACA;AACA;AACA;AACA;AACD;;AAGD;AACA;AACE;AACA;AACD;AAED;;;AAGC;AAED;;AAGI;AACA;;;;;;;;AAQA;;AAEA;;AAEA;;;AAGD;;;;;;;;;;;;;;;AAgBA;AAGH;AAKF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"PopoverClose.js","sources":["../../../../../../src/components/primitives/Popover/PopoverClose.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AAYA;;AAUE;AAEA;;AAGI;AACF;;AAkBJ;AAEA;;"}
1
+ {"version":3,"file":"PopoverClose.js","sources":["src/components/primitives/Popover/PopoverClose.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { CloseIcon } from '@/components/Icons/CloseIcon';\nimport { cx } from '@/utils/cx';\n\nimport { usePopoverContext } from './Popover';\nimport { closeButtonStyle } from './Popover.css';\n\nimport type { PopoverCloseProps } from './Popover.types';\n\n// --- Component ---\n\nexport const PopoverClose: React.FC<PopoverCloseProps> = ({\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const { close } = usePopoverContext();\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n close();\n },\n [close]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-label=\"Close\"\n onClick={handleClick}\n className={cx(closeButtonStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children ?? <CloseIcon size=\"sm\" decorative />}\n </button>\n );\n};\n\nPopoverClose.displayName = 'PopoverClose';\n"],"names":[],"mappings":";;;;;;;;AAYA;;AAUE;AAEA;;AAGI;AACF;;AAkBJ;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"PopoverContent.js","sources":["../../../../../../src/components/primitives/Popover/PopoverContent.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAaA;AAEO;;;AAwBL;;AAGA;AAEI;AACA;AACA;;;AAEO;AACL;;;;;;;;AAWF;;;;;;;;AAOJ;;AAGE;;;;AAKA;AACE;AACA;;;AAKJ;;;AAIA;AACE;AACE;;AAEJ;AACE;AACE;AACF;;AAGF;;;AAWS;AAID;AACA;AACA;;;;;AAeR;AACF;AAEA;;"}
1
+ {"version":3,"file":"PopoverContent.js","sources":["src/components/primitives/Popover/PopoverContent.tsx"],"sourcesContent":["'use client';\n\nimport { FloatingFocusManager } from '@floating-ui/react';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { cx } from '@/utils/cx';\n\nimport { usePopoverContext } from './Popover';\nimport { contentPanelRecipe } from './Popover.css';\n\nimport type { PopoverContentProps } from './Popover.types';\n\n// --- Component ---\n\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n width,\n maxHeight,\n padding = 'md',\n className,\n style,\n testId,\n ref: externalRef,\n ...rest\n}) => {\n const {\n isOpen,\n contentRef,\n portal,\n matchTriggerWidth,\n popoverId,\n floatingRefs,\n floatingStyles,\n floatingContext,\n getFloatingProps,\n } = usePopoverContext();\n\n const [visible, setVisible] = useState(false);\n const contentId = `popover-${popoverId}-content`;\n\n // Set ref\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n contentRef.current = node;\n floatingRefs.setFloating(node);\n if (typeof externalRef === 'function') {\n externalRef(node);\n } else if (externalRef && typeof externalRef === 'object') {\n externalRef.current = node;\n }\n },\n [contentRef, floatingRefs, externalRef]\n );\n\n // Trigger enter animation on next frame after open\n useEffect(() => {\n if (isOpen) {\n requestAnimationFrame(() => {\n setVisible(true);\n });\n } else {\n // Reset enter-animation state on close; gated by the `isOpen` prop, so\n // this is a one-shot transition rather than continuous state sync.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setVisible(false);\n }\n }, [isOpen]);\n\n if (!isOpen) {\n return null;\n }\n\n // Get trigger width for matchTriggerWidth\n const triggerWidth = matchTriggerWidth\n ? floatingRefs.reference.current\n ? (floatingRefs.reference.current as HTMLElement).offsetWidth\n : undefined\n : undefined;\n\n const computedWidth = matchTriggerWidth ? triggerWidth : width;\n\n const floatingProps = getFloatingProps();\n\n // Build dimension styles\n const dimensionStyles: React.CSSProperties = {};\n if (computedWidth != null) {\n dimensionStyles.width =\n typeof computedWidth === 'number' ? `${computedWidth}px` : computedWidth;\n }\n if (maxHeight != null) {\n dimensionStyles.maxHeight =\n typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight;\n dimensionStyles.overflowY = 'auto';\n }\n\n const contentElement = (\n <FloatingFocusManager context={floatingContext} modal={false}>\n <div\n ref={setRef}\n role=\"dialog\"\n id={contentId}\n tabIndex={-1}\n className={cx(\n contentPanelRecipe({\n padding,\n visible: visible || undefined,\n }),\n className\n )}\n style={{\n ...floatingStyles,\n ...dimensionStyles,\n ...style,\n }}\n data-testid={testId}\n {...floatingProps}\n {...rest}\n >\n {children}\n </div>\n </FloatingFocusManager>\n );\n\n if (portal) {\n return createPortal(contentElement, document.body);\n }\n\n return contentElement;\n};\n\nPopoverContent.displayName = 'PopoverContent';\n"],"names":[],"mappings":";;;;;;;;;AAaA;AAEO;;;AAwBL;;AAGA;AAEI;AACA;AACA;;;AAEO;AACL;;;;;;;;AAWF;;;;;;;;AAOJ;;AAGE;;;;AAKA;AACE;AACA;;;AAKJ;;;AAIA;AACE;AACE;;AAEJ;AACE;AACE;AACF;;AAGF;;;AAWS;AAID;AACA;AACA;;;;;AAeR;AACF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"PopoverTrigger.js","sources":["../../../../../../src/components/primitives/Popover/PopoverTrigger.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;AAQA;;;AAGG;;AAED;AAQA;AAEA;;AAGI;AACF;AAIF;AAEI;AACA;AACF;;;AAMA;;;AAIA;AACD;AAED;AAGI;AACA;AACA;AACA;;AAED;AAEL;AAEA;;"}
1
+ {"version":3,"file":"PopoverTrigger.js","sources":["src/components/primitives/Popover/PopoverTrigger.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { usePopoverContext } from './Popover';\n\nimport type { PopoverTriggerProps } from './Popover.types';\n\n/**\n * Wraps the trigger element for a Popover.\n * Clicking the trigger toggles the popover open/closed.\n */\nexport const PopoverTrigger: React.FC<PopoverTriggerProps> = ({ children }) => {\n const {\n toggle,\n isOpen,\n triggerRef,\n popoverId,\n floatingRefs,\n getReferenceProps,\n } = usePopoverContext();\n const contentId = `popover-${popoverId}-content`;\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n toggle();\n },\n [toggle]\n );\n\n const setRef = useCallback(\n (node: HTMLElement | null) => {\n triggerRef.current = node;\n floatingRefs.setReference(node);\n },\n [triggerRef, floatingRefs]\n );\n\n // Clone the child element to add props\n if (!React.isValidElement(children)) {\n return null;\n }\n\n const referenceProps = getReferenceProps({\n onClick: handleClick,\n });\n\n return React.cloneElement(\n children as React.ReactElement<Record<string, unknown>>,\n {\n ref: setRef,\n ...referenceProps,\n 'aria-haspopup': 'dialog',\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? contentId : undefined,\n }\n );\n};\n\nPopoverTrigger.displayName = 'PopoverTrigger';\n"],"names":[],"mappings":";;;;AAQA;;;AAGG;;AAED;AAQA;AAEA;;AAGI;AACF;AAIF;AAEI;AACA;AACF;;;AAMA;;;AAIA;AACD;AAED;AAGI;AACA;AACA;AACA;;AAED;AAEL;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","sources":["../../../../../../src/components/primitives/Radio/Radio.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAsBA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAqBH;AACA;AACA;AACA;;AAGA;AACA;;AAGA;;;AAGE;AACF;AACA;AAEA;;AAEE;;;;;;;;AAOF;AAEI;;;AAGE;;;;;;AAQF;AACF;AAIF;AAEI;;AAEE;;;;;AAML;AAED;;;;AAMK;;;;;;;AAoCI;;AAQP;AACE;;AAMF;;AAGF;AAQF;AAGF;;"}
1
+ {"version":3,"file":"Radio.js","sources":["src/components/primitives/Radio/Radio.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useContext, useId, useState } from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { cx } from '@/utils/cx';\n\nimport {\n innerSizeVar,\n outerSizeVar,\n radioContainerStyle,\n radioDotRecipe,\n radioLabelRecipe,\n radioLabelTextStyle,\n radioOuterRecipe,\n visuallyHiddenInputStyle,\n} from './Radio.css';\nimport { RadioGroupContext } from './RadioGroup';\n\nimport type { RadioProps, RadioSize } from './Radio.types';\n\nconst OUTER_SIZES: Record<RadioSize, number> = {\n sm: 12,\n md: 14,\n lg: 16,\n};\n\nconst INNER_SIZES: Record<RadioSize, number> = {\n sm: 6,\n md: 6,\n lg: 8,\n};\n\n/**\n * Radio component for mutually exclusive selection in property panels,\n * settings, and form interfaces.\n *\n * Works standalone (controlled or uncontrolled) or as a child of `RadioGroup`,\n * which manages exclusive selection across siblings via context. When inside\n * a `RadioGroup`, the group's `value`, `name`, `size`, `disabled`, and `error`\n * override the corresponding props on individual radios.\n *\n * @example\n * ```tsx\n * <Radio value=\"local\" label=\"Local\" />\n *\n * <RadioGroup value={space} onChange={setSpace} label=\"Coordinate space\">\n * <Radio value=\"local\" label=\"Local\" />\n * <Radio value=\"world\" label=\"World\" />\n * <Radio value=\"parent\" label=\"Parent\" />\n * </RadioGroup>\n * ```\n */\nexport const Radio = /*#__PURE__*/ React.memo<RadioProps>(\n ({\n value,\n checked: checkedProp,\n defaultChecked = false,\n label,\n labelPosition = 'right',\n size: sizeProp,\n disabled: disabledProp,\n helperText,\n error: errorProp,\n errorMessage,\n name: nameProp,\n onChange,\n className,\n style,\n testId,\n ref,\n id: idProp,\n ...rest\n }) => {\n const groupContext = useContext(RadioGroupContext);\n const autoId = useId();\n const radioId = idProp ?? autoId;\n const helperId = `${radioId}-helper`;\n\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const isGrouped = groupContext !== null;\n\n // Group context overrides individual props when present\n const size: RadioSize = isGrouped ? groupContext.size : (sizeProp ?? 'md');\n const disabled = isGrouped\n ? groupContext.disabled\n : (disabledProp ?? false);\n const error = isGrouped ? groupContext.error : (errorProp ?? false);\n const name = isGrouped ? groupContext.name : nameProp;\n\n let resolvedChecked: boolean;\n if (isGrouped) {\n resolvedChecked = groupContext.value === value;\n } else if (isControlled) {\n resolvedChecked = checkedProp;\n } else {\n resolvedChecked = internalChecked;\n }\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n if (isGrouped) {\n groupContext.onChange(value, event);\n return;\n }\n\n if (!isControlled) {\n setInternalChecked(true);\n }\n\n onChange?.(value, event);\n },\n [disabled, isGrouped, groupContext, value, isControlled, onChange]\n );\n\n const showHelperText =\n !isGrouped && error && errorMessage\n ? errorMessage\n : !isGrouped\n ? helperText\n : undefined;\n\n const outerInlineVars = assignInlineVars({\n [outerSizeVar]: `${OUTER_SIZES[size]}px`,\n [innerSizeVar]: `${INNER_SIZES[size]}px`,\n });\n\n const labelNode = (\n <label\n className={radioLabelRecipe({\n labelPosition,\n size,\n disabled: disabled || undefined,\n })}\n >\n {/* aria-invalid surfaces the error state to assistive tech and is part\n of this component's documented/tested API; jsx-a11y's role support\n table for the implicit radio role is overly strict here. */}\n {/* eslint-disable-next-line jsx-a11y/role-supports-aria-props */}\n <input\n ref={ref}\n type=\"radio\"\n id={radioId}\n name={name}\n value={value}\n checked={resolvedChecked}\n disabled={disabled}\n aria-checked={resolvedChecked}\n aria-disabled={disabled || undefined}\n aria-invalid={error || undefined}\n aria-describedby={showHelperText ? helperId : undefined}\n onChange={handleChange}\n className={visuallyHiddenInputStyle}\n data-testid={testId}\n {...rest}\n />\n <span\n aria-hidden=\"true\"\n className={radioOuterRecipe({\n checked: resolvedChecked || undefined,\n disabled: disabled || undefined,\n error: error || undefined,\n })}\n style={outerInlineVars}\n >\n <span\n className={radioDotRecipe({\n checked: resolvedChecked || undefined,\n error: error || undefined,\n })}\n />\n </span>\n {label && <span className={radioLabelTextStyle}>{label}</span>}\n </label>\n );\n\n if (!showHelperText) {\n if (className || style) {\n return (\n <div className={cx(radioContainerStyle, className)} style={style}>\n {labelNode}\n </div>\n );\n }\n return labelNode;\n }\n\n return (\n <div className={cx(radioContainerStyle, className)} style={style}>\n {labelNode}\n <FormHelperText id={helperId} error={error}>\n {showHelperText}\n </FormHelperText>\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n"],"names":[],"mappings":";;;;;;;;;AAsBA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAqBH;AACA;AACA;AACA;;AAGA;AACA;;AAGA;;;AAGE;AACF;AACA;AAEA;;AAEE;;;;;;;;AAOF;AAEI;;;AAGE;;;;;;AAQF;AACF;AAIF;AAEI;;AAEE;;;;;AAML;AAED;;;;AAMK;;;;;;;AAoCI;;AAQP;AACE;;AAMF;;AAGF;AAQF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.js","sources":["../../../../../../src/components/primitives/Radio/RadioGroup.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;AA0BE;AAEF;;;;;;;;;;AAWA;;AACmC;;;;AAInC;AAEA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAuBH;AACA;AACA;AACA;;AAKA;;AAGA;;;;AAKI;AACF;AAIF;AAEI;;;;;AAKA;AACD;AAIH;AAEA;;;AA2BU;;AAaZ;AAGF;;"}
1
+ {"version":3,"file":"RadioGroup.js","sources":["src/components/primitives/Radio/RadioGroup.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, {\n createContext,\n useCallback,\n useId,\n useMemo,\n useState,\n} from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { FormLabel } from '@/components/form/FormLabel';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n groupContainerStyle,\n groupItemsStyle,\n groupOrientationVar,\n groupSpacingVar,\n} from './Radio.css';\n\nimport type { RadioGroupContextValue, RadioGroupProps } from './Radio.types';\n\nexport const RadioGroupContext =\n /*#__PURE__*/ createContext<RadioGroupContextValue | null>(null);\n\nconst SPACING_SCALE: readonly string[] = [\n '0',\n vars.spacing.xs,\n vars.spacing.sm,\n vars.spacing.md,\n vars.spacing.lg,\n vars.spacing.xl,\n vars.spacing.xxl,\n vars.spacing.xxxl,\n];\n\nconst resolveSpacing = (spacing: number | string): string => {\n if (typeof spacing === 'string') return spacing;\n const clamped = Math.max(0, Math.min(SPACING_SCALE.length - 1, spacing));\n const index = Math.floor(clamped);\n return SPACING_SCALE[index] ?? vars.spacing.sm;\n};\n\n/**\n * Groups multiple Radio components with shared, exclusive selection state.\n *\n * Manages a single `string` value, propagates `name`, `size`, `disabled`,\n * and `error` to children via React Context, and applies `aria-required`\n * for required fields. Supports controlled and uncontrolled modes.\n *\n * @example\n * ```tsx\n * <RadioGroup\n * label=\"Coordinate space\"\n * value={space}\n * onChange={setSpace}\n * >\n * <Radio value=\"local\" label=\"Local\" />\n * <Radio value=\"world\" label=\"World\" />\n * <Radio value=\"parent\" label=\"Parent\" />\n * </RadioGroup>\n * ```\n */\nexport const RadioGroup = /*#__PURE__*/ React.memo<RadioGroupProps>(\n ({\n value: valueProp,\n defaultValue,\n label,\n helperText,\n disabled = false,\n error = false,\n errorMessage,\n required = false,\n orientation = 'vertical',\n spacing = 2,\n name,\n size = 'md',\n onChange,\n children,\n className,\n style,\n testId,\n ref,\n id: idProp,\n ...rest\n }) => {\n const autoId = useId();\n const groupId = idProp ?? autoId;\n const labelId = `${groupId}-label`;\n const helperId = `${groupId}-helper`;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(\n defaultValue\n );\n const isControlled = valueProp !== undefined;\n const currentValue = isControlled ? valueProp : internalValue;\n\n const handleChange = useCallback(\n (nextValue: string) => {\n if (!isControlled) {\n setInternalValue(nextValue);\n }\n onChange?.(nextValue);\n },\n [isControlled, onChange]\n );\n\n const contextValue = useMemo<RadioGroupContextValue>(\n () => ({\n value: currentValue,\n name,\n size,\n disabled,\n error,\n onChange: handleChange,\n }),\n [currentValue, name, size, disabled, error, handleChange]\n );\n\n const showHelperText = error && errorMessage ? errorMessage : helperText;\n\n const flexDirection = orientation === 'horizontal' ? 'row' : 'column';\n\n return (\n <div\n ref={ref}\n role=\"radiogroup\"\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={showHelperText ? helperId : undefined}\n aria-required={required || undefined}\n aria-invalid={error || undefined}\n aria-disabled={disabled || undefined}\n aria-orientation={orientation}\n className={cx(groupContainerStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {label && (\n <FormLabel id={labelId} required={required} disabled={disabled}>\n {label}\n </FormLabel>\n )}\n <RadioGroupContext.Provider value={contextValue}>\n <div\n className={groupItemsStyle}\n style={assignInlineVars({\n [groupOrientationVar]: flexDirection,\n [groupSpacingVar]: resolveSpacing(spacing),\n })}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n {showHelperText && (\n <FormHelperText id={helperId} error={error}>\n {showHelperText}\n </FormHelperText>\n )}\n </div>\n );\n }\n);\n\nRadioGroup.displayName = 'RadioGroup';\n"],"names":[],"mappings":";;;;;;;;;;;AA0BE;AAEF;;;;;;;;;;AAWA;;AACmC;;;;AAInC;AAEA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAuBH;AACA;AACA;AACA;;AAKA;;AAGA;;;;AAKI;AACF;AAIF;AAEI;;;;;AAKA;AACD;AAIH;AAEA;;;AA2BU;;AAaZ;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","sources":["../../../../../../src/components/primitives/Switch/Switch.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AAkHA;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;AAYG;AACI;AAmBL;AACA;AACA;;AAGA;;AAGA;AACE;;AAEA;;;;AAMA;;AAGF;AAEA;AACA;;AAGE;AACA;AACD;;AAGC;AACA;AACD;;;;AAMD;;;;AAcK;;AAQE;AASP;AACE;;AAGF;;;;AAuBF;AAEA;;"}
1
+ {"version":3,"file":"Switch.js","sources":["src/components/primitives/Switch/Switch.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useId, useState } from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { cx } from '@/utils/cx';\n\nimport {\n switchContainerStyle,\n switchRowRecipe,\n trackRecipe,\n trackWidthVar,\n trackHeightVar,\n thumbRecipe,\n thumbDiameterVar,\n thumbTranslateVar,\n labelTextStyle,\n} from './Switch.css';\n\nimport type { Size } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\n\n// --- Types ---\n\nexport type SwitchSize = Size;\n\nexport interface SwitchBaseProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'onChange' | 'css'\n> {\n /**\n * Whether the switch is on (controlled)\n */\n checked?: boolean;\n\n /**\n * Default on/off state (uncontrolled)\n * @default false\n */\n defaultChecked?: boolean;\n\n /**\n * Switch label text\n */\n label?: string;\n\n /**\n * Position of the label relative to the switch\n * @default \"right\"\n */\n labelPosition?: 'left' | 'right';\n\n /**\n * Switch size\n * - `sm`: 28x14px track, compact toolbars\n * - `md`: 34x18px track, standard for panels\n * - `lg`: 42x22px track, prominent settings\n * @default \"md\"\n */\n size?: SwitchSize;\n\n /**\n * Whether the switch is disabled\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Helper text displayed below the switch\n */\n helperText?: string;\n\n /**\n * Error state\n * @default false\n */\n error?: boolean;\n\n /**\n * Error message displayed when error is true\n */\n errorMessage?: string;\n\n /**\n * Name attribute for form submission\n */\n name?: string;\n\n /**\n * Change event handler\n * @param checked - The new on/off state\n */\n onChange?: (checked: boolean) => void;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<HTMLButtonElement>;\n}\n\nexport type SwitchProps = Prettify<SwitchBaseProps>;\n\n// --- Size maps ---\n\ninterface SizeConfig {\n trackW: number;\n trackH: number;\n thumbDiameter: number;\n offset: number;\n}\n\nconst SIZE_MAP: Record<SwitchSize, SizeConfig> = {\n sm: { trackW: 28, trackH: 14, thumbDiameter: 10, offset: 2 },\n md: { trackW: 34, trackH: 18, thumbDiameter: 14, offset: 2 },\n lg: { trackW: 42, trackH: 22, thumbDiameter: 18, offset: 2 },\n};\n\n/**\n * Switch component for boolean on/off states in editor toolbars,\n * settings panels, and property inspectors.\n *\n * More space-efficient than Checkbox for toggle options like\n * \"Show Grid\", \"Snap to Grid\", \"Auto-Save\".\n *\n * @example\n * ```tsx\n * <Switch label=\"Show Grid\" />\n * <Switch checked={value} onChange={setValue} label=\"Auto-save\" />\n * ```\n */\nexport const Switch: React.FC<SwitchProps> = ({\n checked: checkedProp,\n defaultChecked = false,\n label,\n labelPosition = 'right',\n size = 'md',\n disabled = false,\n helperText,\n error = false,\n errorMessage,\n name,\n onChange,\n className,\n style,\n testId,\n ref,\n id: idProp,\n ...rest\n}) => {\n const autoId = useId();\n const switchId = idProp ?? autoId;\n const helperId = `${switchId}-helper`;\n\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const resolvedChecked = isControlled ? checkedProp : internalChecked;\n\n const handleClick = useCallback(() => {\n if (disabled) return;\n\n const newChecked = !resolvedChecked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, resolvedChecked, isControlled, onChange]);\n\n const showHelperText = error && errorMessage ? errorMessage : helperText;\n\n const config = SIZE_MAP[size];\n const translateX = config.trackW - config.thumbDiameter - config.offset * 2;\n\n const trackInlineVars = assignInlineVars({\n [trackWidthVar]: `${config.trackW}px`,\n [trackHeightVar]: `${config.trackH}px`,\n });\n\n const thumbInlineVars = assignInlineVars({\n [thumbDiameterVar]: `${config.thumbDiameter}px`,\n [thumbTranslateVar]: `${translateX}px`,\n });\n\n const thumbStyle: React.CSSProperties = !resolvedChecked\n ? { transform: `translateX(${config.offset}px)` }\n : {};\n\n const track = (\n <button\n ref={ref}\n type=\"button\"\n role=\"switch\"\n aria-checked={resolvedChecked}\n aria-disabled={disabled || undefined}\n aria-describedby={showHelperText ? helperId : undefined}\n disabled={disabled}\n onClick={handleClick}\n className={trackRecipe({\n checked: resolvedChecked || undefined,\n disabled: disabled || undefined,\n error: error || undefined,\n })}\n style={trackInlineVars}\n data-testid={testId}\n {...rest}\n >\n <span\n className={thumbRecipe({\n checked: resolvedChecked || undefined,\n })}\n style={{ ...thumbInlineVars, ...thumbStyle }}\n />\n {name && (\n <input type=\"hidden\" name={name} value={resolvedChecked ? 'on' : ''} />\n )}\n </button>\n );\n\n if (!label && !showHelperText) {\n return track;\n }\n\n return (\n <div className={cx(switchContainerStyle, className)} style={style}>\n <label\n className={switchRowRecipe({\n size,\n disabled: disabled || undefined,\n })}\n >\n {labelPosition === 'left' && label && (\n <span className={labelTextStyle}>{label}</span>\n )}\n {track}\n {labelPosition === 'right' && label && (\n <span className={labelTextStyle}>{label}</span>\n )}\n </label>\n {showHelperText && (\n <FormHelperText id={helperId} error={error}>\n {showHelperText}\n </FormHelperText>\n )}\n </div>\n );\n};\n\nSwitch.displayName = 'Switch';\n"],"names":[],"mappings":";;;;;;;;AAkHA;AACE;AACA;AACA;;AAGF;;;;;;;;;;;;AAYG;AACI;AAmBL;AACA;AACA;;AAGA;;AAGA;AACE;;AAEA;;;;AAMA;;AAGF;AAEA;AACA;;AAGE;AACA;AACD;;AAGC;AACA;AACD;;;;AAMD;;;;AAcK;;AAQE;AASP;AACE;;AAGF;;;;AAuBF;AAEA;;"}