@agentaily/design-system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/DESIGN.md +112 -0
  2. package/README.md +81 -0
  3. package/dist/assets/logo/agentaily-mark-black.svg +5 -0
  4. package/dist/assets/logo/agentaily-mark-white.svg +5 -0
  5. package/dist/components/ai/Attachments.d.ts +23 -0
  6. package/dist/components/ai/Attachments.js +96 -0
  7. package/dist/components/ai/Attachments.js.map +1 -0
  8. package/dist/components/ai/Checkpoint.d.ts +3 -0
  9. package/dist/components/ai/Checkpoint.js +38 -0
  10. package/dist/components/ai/Checkpoint.js.map +1 -0
  11. package/dist/components/ai/Confirmation.d.ts +3 -0
  12. package/dist/components/ai/Confirmation.js +54 -0
  13. package/dist/components/ai/Confirmation.js.map +1 -0
  14. package/dist/components/ai/Context.d.ts +3 -0
  15. package/dist/components/ai/Context.js +63 -0
  16. package/dist/components/ai/Context.js.map +1 -0
  17. package/dist/components/ai/Conversation.d.ts +3 -0
  18. package/dist/components/ai/Conversation.js +53 -0
  19. package/dist/components/ai/Conversation.js.map +1 -0
  20. package/dist/components/ai/ModelSelector.d.ts +19 -0
  21. package/dist/components/ai/ModelSelector.js +92 -0
  22. package/dist/components/ai/ModelSelector.js.map +1 -0
  23. package/dist/components/ai/Plan.d.ts +4 -0
  24. package/dist/components/ai/Plan.js +49 -0
  25. package/dist/components/ai/Plan.js.map +1 -0
  26. package/dist/components/ai/Queue.d.ts +4 -0
  27. package/dist/components/ai/Queue.js +45 -0
  28. package/dist/components/ai/Queue.js.map +1 -0
  29. package/dist/components/ai/Reasoning.d.ts +17 -0
  30. package/dist/components/ai/Reasoning.js +60 -0
  31. package/dist/components/ai/Reasoning.js.map +1 -0
  32. package/dist/components/ai/Shimmer.d.ts +10 -0
  33. package/dist/components/ai/Shimmer.js +28 -0
  34. package/dist/components/ai/Shimmer.js.map +1 -0
  35. package/dist/components/ai/Sources.d.ts +23 -0
  36. package/dist/components/ai/Sources.js +65 -0
  37. package/dist/components/ai/Sources.js.map +1 -0
  38. package/dist/components/ai/Suggestion.d.ts +19 -0
  39. package/dist/components/ai/Suggestion.js +40 -0
  40. package/dist/components/ai/Suggestion.js.map +1 -0
  41. package/dist/components/ai/Task.d.ts +4 -0
  42. package/dist/components/ai/Task.js +48 -0
  43. package/dist/components/ai/Task.js.map +1 -0
  44. package/dist/components/ai/ToolCall.d.ts +16 -0
  45. package/dist/components/ai/ToolCall.js +70 -0
  46. package/dist/components/ai/ToolCall.js.map +1 -0
  47. package/dist/components/buttons/Button.d.ts +17 -0
  48. package/dist/components/buttons/Button.js +60 -0
  49. package/dist/components/buttons/Button.js.map +1 -0
  50. package/dist/components/buttons/ButtonGroup.d.ts +3 -0
  51. package/dist/components/buttons/ButtonGroup.js +27 -0
  52. package/dist/components/buttons/ButtonGroup.js.map +1 -0
  53. package/dist/components/buttons/IconButton.d.ts +16 -0
  54. package/dist/components/buttons/IconButton.js +49 -0
  55. package/dist/components/buttons/IconButton.js.map +1 -0
  56. package/dist/components/chat/CodeBlock.d.ts +9 -0
  57. package/dist/components/chat/CodeBlock.js +62 -0
  58. package/dist/components/chat/CodeBlock.js.map +1 -0
  59. package/dist/components/chat/Composer.d.ts +17 -0
  60. package/dist/components/chat/Composer.js +123 -0
  61. package/dist/components/chat/Composer.js.map +1 -0
  62. package/dist/components/chat/Message.d.ts +16 -0
  63. package/dist/components/chat/Message.js +63 -0
  64. package/dist/components/chat/Message.js.map +1 -0
  65. package/dist/components/code/Agent.d.ts +3 -0
  66. package/dist/components/code/Agent.js +44 -0
  67. package/dist/components/code/Agent.js.map +1 -0
  68. package/dist/components/code/Artifact.d.ts +3 -0
  69. package/dist/components/code/Artifact.js +50 -0
  70. package/dist/components/code/Artifact.js.map +1 -0
  71. package/dist/components/code/Commit.d.ts +3 -0
  72. package/dist/components/code/Commit.js +55 -0
  73. package/dist/components/code/Commit.js.map +1 -0
  74. package/dist/components/code/EnvironmentVariables.d.ts +4 -0
  75. package/dist/components/code/EnvironmentVariables.js +49 -0
  76. package/dist/components/code/EnvironmentVariables.js.map +1 -0
  77. package/dist/components/code/FileTree.d.ts +4 -0
  78. package/dist/components/code/FileTree.js +59 -0
  79. package/dist/components/code/FileTree.js.map +1 -0
  80. package/dist/components/code/JSXPreview.d.ts +3 -0
  81. package/dist/components/code/JSXPreview.js +35 -0
  82. package/dist/components/code/JSXPreview.js.map +1 -0
  83. package/dist/components/code/PackageInfo.d.ts +3 -0
  84. package/dist/components/code/PackageInfo.js +47 -0
  85. package/dist/components/code/PackageInfo.js.map +1 -0
  86. package/dist/components/code/Sandbox.d.ts +3 -0
  87. package/dist/components/code/Sandbox.js +43 -0
  88. package/dist/components/code/Sandbox.js.map +1 -0
  89. package/dist/components/code/SchemaDisplay.d.ts +4 -0
  90. package/dist/components/code/SchemaDisplay.js +43 -0
  91. package/dist/components/code/SchemaDisplay.js.map +1 -0
  92. package/dist/components/code/Snippet.d.ts +3 -0
  93. package/dist/components/code/Snippet.js +36 -0
  94. package/dist/components/code/Snippet.js.map +1 -0
  95. package/dist/components/code/StackTrace.d.ts +4 -0
  96. package/dist/components/code/StackTrace.js +46 -0
  97. package/dist/components/code/StackTrace.js.map +1 -0
  98. package/dist/components/code/Terminal.d.ts +4 -0
  99. package/dist/components/code/Terminal.js +73 -0
  100. package/dist/components/code/Terminal.js.map +1 -0
  101. package/dist/components/code/TestResults.d.ts +4 -0
  102. package/dist/components/code/TestResults.js +61 -0
  103. package/dist/components/code/TestResults.js.map +1 -0
  104. package/dist/components/code/WebPreview.d.ts +3 -0
  105. package/dist/components/code/WebPreview.js +48 -0
  106. package/dist/components/code/WebPreview.js.map +1 -0
  107. package/dist/components/display/Accordion.d.ts +12 -0
  108. package/dist/components/display/Accordion.js +60 -0
  109. package/dist/components/display/Accordion.js.map +1 -0
  110. package/dist/components/display/Avatar.d.ts +14 -0
  111. package/dist/components/display/Avatar.js +41 -0
  112. package/dist/components/display/Avatar.js.map +1 -0
  113. package/dist/components/display/Badge.d.ts +11 -0
  114. package/dist/components/display/Badge.js +40 -0
  115. package/dist/components/display/Badge.js.map +1 -0
  116. package/dist/components/display/Breadcrumb.d.ts +11 -0
  117. package/dist/components/display/Breadcrumb.js +32 -0
  118. package/dist/components/display/Breadcrumb.js.map +1 -0
  119. package/dist/components/display/Card.d.ts +14 -0
  120. package/dist/components/display/Card.js +61 -0
  121. package/dist/components/display/Card.js.map +1 -0
  122. package/dist/components/display/Carousel.d.ts +3 -0
  123. package/dist/components/display/Carousel.js +40 -0
  124. package/dist/components/display/Carousel.js.map +1 -0
  125. package/dist/components/display/Chart.d.ts +7 -0
  126. package/dist/components/display/Chart.js +68 -0
  127. package/dist/components/display/Chart.js.map +1 -0
  128. package/dist/components/display/Collapsible.d.ts +3 -0
  129. package/dist/components/display/Collapsible.js +36 -0
  130. package/dist/components/display/Collapsible.js.map +1 -0
  131. package/dist/components/display/DataTable.d.ts +4 -0
  132. package/dist/components/display/DataTable.js +72 -0
  133. package/dist/components/display/DataTable.js.map +1 -0
  134. package/dist/components/display/Empty.d.ts +14 -0
  135. package/dist/components/display/Empty.js +36 -0
  136. package/dist/components/display/Empty.js.map +1 -0
  137. package/dist/components/display/Item.d.ts +3 -0
  138. package/dist/components/display/Item.js +36 -0
  139. package/dist/components/display/Item.js.map +1 -0
  140. package/dist/components/display/Kbd.d.ts +7 -0
  141. package/dist/components/display/Kbd.js +27 -0
  142. package/dist/components/display/Kbd.js.map +1 -0
  143. package/dist/components/display/Pagination.d.ts +11 -0
  144. package/dist/components/display/Pagination.js +55 -0
  145. package/dist/components/display/Pagination.js.map +1 -0
  146. package/dist/components/display/Progress.d.ts +14 -0
  147. package/dist/components/display/Progress.js +43 -0
  148. package/dist/components/display/Progress.js.map +1 -0
  149. package/dist/components/display/Separator.d.ts +10 -0
  150. package/dist/components/display/Separator.js +33 -0
  151. package/dist/components/display/Separator.js.map +1 -0
  152. package/dist/components/display/Skeleton.d.ts +12 -0
  153. package/dist/components/display/Skeleton.js +43 -0
  154. package/dist/components/display/Skeleton.js.map +1 -0
  155. package/dist/components/display/Table.d.ts +20 -0
  156. package/dist/components/display/Table.js +42 -0
  157. package/dist/components/display/Table.js.map +1 -0
  158. package/dist/components/display/Tabs.d.ts +11 -0
  159. package/dist/components/display/Tabs.js +47 -0
  160. package/dist/components/display/Tabs.js.map +1 -0
  161. package/dist/components/display/Typography.d.ts +5 -0
  162. package/dist/components/display/Typography.js +45 -0
  163. package/dist/components/display/Typography.js.map +1 -0
  164. package/dist/components/feedback/Alert.d.ts +12 -0
  165. package/dist/components/feedback/Alert.js +41 -0
  166. package/dist/components/feedback/Alert.js.map +1 -0
  167. package/dist/components/feedback/Dialog.d.ts +17 -0
  168. package/dist/components/feedback/Dialog.js +90 -0
  169. package/dist/components/feedback/Dialog.js.map +1 -0
  170. package/dist/components/feedback/Spinner.d.ts +8 -0
  171. package/dist/components/feedback/Spinner.js +39 -0
  172. package/dist/components/feedback/Spinner.js.map +1 -0
  173. package/dist/components/feedback/Toast.d.ts +12 -0
  174. package/dist/components/feedback/Toast.js +50 -0
  175. package/dist/components/feedback/Toast.js.map +1 -0
  176. package/dist/components/feedback/Tooltip.d.ts +11 -0
  177. package/dist/components/feedback/Tooltip.js +34 -0
  178. package/dist/components/feedback/Tooltip.js.map +1 -0
  179. package/dist/components/inputs/Calendar.d.ts +3 -0
  180. package/dist/components/inputs/Calendar.js +81 -0
  181. package/dist/components/inputs/Calendar.js.map +1 -0
  182. package/dist/components/inputs/Checkbox.d.ts +10 -0
  183. package/dist/components/inputs/Checkbox.js +42 -0
  184. package/dist/components/inputs/Checkbox.js.map +1 -0
  185. package/dist/components/inputs/Combobox.d.ts +3 -0
  186. package/dist/components/inputs/Combobox.js +94 -0
  187. package/dist/components/inputs/Combobox.js.map +1 -0
  188. package/dist/components/inputs/DatePicker.d.ts +3 -0
  189. package/dist/components/inputs/DatePicker.js +56 -0
  190. package/dist/components/inputs/DatePicker.js.map +1 -0
  191. package/dist/components/inputs/Field.d.ts +5 -0
  192. package/dist/components/inputs/Field.js +44 -0
  193. package/dist/components/inputs/Field.js.map +1 -0
  194. package/dist/components/inputs/Input.d.ts +19 -0
  195. package/dist/components/inputs/Input.js +72 -0
  196. package/dist/components/inputs/Input.js.map +1 -0
  197. package/dist/components/inputs/InputGroup.d.ts +3 -0
  198. package/dist/components/inputs/InputGroup.js +32 -0
  199. package/dist/components/inputs/InputGroup.js.map +1 -0
  200. package/dist/components/inputs/InputOTP.d.ts +3 -0
  201. package/dist/components/inputs/InputOTP.js +49 -0
  202. package/dist/components/inputs/InputOTP.js.map +1 -0
  203. package/dist/components/inputs/Label.d.ts +13 -0
  204. package/dist/components/inputs/Label.js +33 -0
  205. package/dist/components/inputs/Label.js.map +1 -0
  206. package/dist/components/inputs/RadioGroup.d.ts +15 -0
  207. package/dist/components/inputs/RadioGroup.js +58 -0
  208. package/dist/components/inputs/RadioGroup.js.map +1 -0
  209. package/dist/components/inputs/Select.d.ts +12 -0
  210. package/dist/components/inputs/Select.js +49 -0
  211. package/dist/components/inputs/Select.js.map +1 -0
  212. package/dist/components/inputs/Slider.d.ts +16 -0
  213. package/dist/components/inputs/Slider.js +62 -0
  214. package/dist/components/inputs/Slider.js.map +1 -0
  215. package/dist/components/inputs/Switch.d.ts +11 -0
  216. package/dist/components/inputs/Switch.js +39 -0
  217. package/dist/components/inputs/Switch.js.map +1 -0
  218. package/dist/components/inputs/Textarea.d.ts +13 -0
  219. package/dist/components/inputs/Textarea.js +41 -0
  220. package/dist/components/inputs/Textarea.js.map +1 -0
  221. package/dist/components/inputs/Toggle.d.ts +19 -0
  222. package/dist/components/inputs/Toggle.js +57 -0
  223. package/dist/components/inputs/Toggle.js.map +1 -0
  224. package/dist/components/layout/AspectRatio.d.ts +3 -0
  225. package/dist/components/layout/AspectRatio.js +20 -0
  226. package/dist/components/layout/AspectRatio.js.map +1 -0
  227. package/dist/components/layout/Resizable.d.ts +3 -0
  228. package/dist/components/layout/Resizable.js +58 -0
  229. package/dist/components/layout/Resizable.js.map +1 -0
  230. package/dist/components/layout/ScrollArea.d.ts +3 -0
  231. package/dist/components/layout/ScrollArea.js +24 -0
  232. package/dist/components/layout/ScrollArea.js.map +1 -0
  233. package/dist/components/layout/Sidebar.d.ts +5 -0
  234. package/dist/components/layout/Sidebar.js +55 -0
  235. package/dist/components/layout/Sidebar.js.map +1 -0
  236. package/dist/components/overlay/AlertDialog.d.ts +3 -0
  237. package/dist/components/overlay/AlertDialog.js +51 -0
  238. package/dist/components/overlay/AlertDialog.js.map +1 -0
  239. package/dist/components/overlay/Command.d.ts +22 -0
  240. package/dist/components/overlay/Command.js +123 -0
  241. package/dist/components/overlay/Command.js.map +1 -0
  242. package/dist/components/overlay/ContextMenu.d.ts +4 -0
  243. package/dist/components/overlay/ContextMenu.js +66 -0
  244. package/dist/components/overlay/ContextMenu.js.map +1 -0
  245. package/dist/components/overlay/DropdownMenu.d.ts +20 -0
  246. package/dist/components/overlay/DropdownMenu.js +86 -0
  247. package/dist/components/overlay/DropdownMenu.js.map +1 -0
  248. package/dist/components/overlay/HoverCard.d.ts +3 -0
  249. package/dist/components/overlay/HoverCard.js +53 -0
  250. package/dist/components/overlay/HoverCard.js.map +1 -0
  251. package/dist/components/overlay/Menubar.d.ts +4 -0
  252. package/dist/components/overlay/Menubar.js +55 -0
  253. package/dist/components/overlay/Menubar.js.map +1 -0
  254. package/dist/components/overlay/NavigationMenu.d.ts +5 -0
  255. package/dist/components/overlay/NavigationMenu.js +42 -0
  256. package/dist/components/overlay/NavigationMenu.js.map +1 -0
  257. package/dist/components/overlay/Popover.d.ts +16 -0
  258. package/dist/components/overlay/Popover.js +53 -0
  259. package/dist/components/overlay/Popover.js.map +1 -0
  260. package/dist/components/overlay/Sheet.d.ts +13 -0
  261. package/dist/components/overlay/Sheet.js +49 -0
  262. package/dist/components/overlay/Sheet.js.map +1 -0
  263. package/dist/components/utilities/Image.d.ts +3 -0
  264. package/dist/components/utilities/Image.js +32 -0
  265. package/dist/components/utilities/Image.js.map +1 -0
  266. package/dist/components/utilities/OpenInChat.d.ts +3 -0
  267. package/dist/components/utilities/OpenInChat.js +26 -0
  268. package/dist/components/utilities/OpenInChat.js.map +1 -0
  269. package/dist/components/voice/AudioPlayer.d.ts +3 -0
  270. package/dist/components/voice/AudioPlayer.js +42 -0
  271. package/dist/components/voice/AudioPlayer.js.map +1 -0
  272. package/dist/components/voice/MicSelector.d.ts +3 -0
  273. package/dist/components/voice/MicSelector.js +36 -0
  274. package/dist/components/voice/MicSelector.js.map +1 -0
  275. package/dist/components/voice/Persona.d.ts +3 -0
  276. package/dist/components/voice/Persona.js +41 -0
  277. package/dist/components/voice/Persona.js.map +1 -0
  278. package/dist/components/voice/SpeechInput.d.ts +3 -0
  279. package/dist/components/voice/SpeechInput.js +42 -0
  280. package/dist/components/voice/SpeechInput.js.map +1 -0
  281. package/dist/components/voice/Transcription.d.ts +4 -0
  282. package/dist/components/voice/Transcription.js +48 -0
  283. package/dist/components/voice/Transcription.js.map +1 -0
  284. package/dist/components/voice/VoiceSelector.d.ts +3 -0
  285. package/dist/components/voice/VoiceSelector.js +58 -0
  286. package/dist/components/voice/VoiceSelector.js.map +1 -0
  287. package/dist/components/workflow/Flow.d.ts +20 -0
  288. package/dist/components/workflow/Flow.js +96 -0
  289. package/dist/components/workflow/Flow.js.map +1 -0
  290. package/dist/index.d.ts +120 -0
  291. package/dist/index.js +208 -0
  292. package/dist/index.js.map +1 -0
  293. package/dist/styles.css +217 -0
  294. package/package.json +77 -0
@@ -0,0 +1,55 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ const AX_SIDEBAR_CSS = `
4
+ .ax-sidebar { display: flex; flex-direction: column; width: var(--sidebar-w); flex: none; height: 100%; background: var(--surface-panel); border-right: 1px solid var(--border-default); transition: width var(--dur-2) var(--ease-out); overflow: hidden; }
5
+ .ax-sidebar--collapsed { width: 56px; }
6
+ .ax-sidebar__header { padding: 16px; display: flex; align-items: center; gap: 10px; min-height: 56px; }
7
+ .ax-sidebar__content { flex: 1; overflow-y: auto; padding: 8px; }
8
+ .ax-sidebar__footer { padding: 12px 16px; border-top: 1px solid var(--border-default); }
9
+ .ax-sidebar__group { margin-bottom: 16px; }
10
+ .ax-sidebar__group-label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 6px 10px; white-space: nowrap; }
11
+ .ax-sidebar--collapsed .ax-sidebar__group-label { opacity: 0; }
12
+ .ax-sidebar__item { display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none; text-align: left; cursor: pointer; padding: 8px 10px; border-radius: var(--radius-2); color: var(--text-muted); font-family: var(--font-body); font-size: var(--text-sm); position: relative; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); white-space: nowrap; }
13
+ .ax-sidebar__item:hover { background: var(--surface-raised); color: var(--text-body); }
14
+ .ax-sidebar__item--active { background: var(--surface-raised); color: var(--text-body); }
15
+ .ax-sidebar__item--active::before { content: ""; position: absolute; left: 0; top: 7px; bottom: 7px; width: 2px; border-radius: 1px; background: var(--accent); }
16
+ .ax-sidebar__item-icon { width: 18px; height: 18px; flex: none; display: inline-flex; align-items: center; justify-content: center; }
17
+ .ax-sidebar__item-icon svg { width: 16px; height: 16px; }
18
+ .ax-sidebar__item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
19
+ .ax-sidebar--collapsed .ax-sidebar__item-label { opacity: 0; }
20
+ .ax-sidebar__item-badge { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }
21
+ .ax-sidebar--collapsed .ax-sidebar__item-badge { display: none; }
22
+ `;
23
+ if (typeof document !== "undefined" && !document.getElementById("ax-sidebar-css")) {
24
+ const s = document.createElement("style");
25
+ s.id = "ax-sidebar-css";
26
+ s.textContent = AX_SIDEBAR_CSS;
27
+ document.head.appendChild(s);
28
+ }
29
+ function Sidebar({ groups = [], activeId, onSelect, header, footer, collapsed = false, className = "", ...rest }) {
30
+ return /* @__PURE__ */ jsxs("aside", { className: ["ax-sidebar", collapsed ? "ax-sidebar--collapsed" : "", className].filter(Boolean).join(" "), ...rest, children: [
31
+ header ? /* @__PURE__ */ jsx("div", { className: "ax-sidebar__header", children: header }) : null,
32
+ /* @__PURE__ */ jsx("nav", { className: "ax-sidebar__content", children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { className: "ax-sidebar__group", children: [
33
+ g.label ? /* @__PURE__ */ jsx("div", { className: "ax-sidebar__group-label", children: g.label }) : null,
34
+ g.items.map((it) => /* @__PURE__ */ jsxs(
35
+ "button",
36
+ {
37
+ className: "ax-sidebar__item" + (it.id === activeId ? " ax-sidebar__item--active" : ""),
38
+ onClick: () => onSelect && onSelect(it.id),
39
+ title: collapsed ? it.label : void 0,
40
+ children: [
41
+ it.icon ? /* @__PURE__ */ jsx("span", { className: "ax-sidebar__item-icon", children: it.icon }) : null,
42
+ /* @__PURE__ */ jsx("span", { className: "ax-sidebar__item-label", children: it.label }),
43
+ it.badge != null ? /* @__PURE__ */ jsx("span", { className: "ax-sidebar__item-badge", children: it.badge }) : null
44
+ ]
45
+ },
46
+ it.id
47
+ ))
48
+ ] }, gi)) }),
49
+ footer ? /* @__PURE__ */ jsx("div", { className: "ax-sidebar__footer", children: footer }) : null
50
+ ] });
51
+ }
52
+ export {
53
+ Sidebar
54
+ };
55
+ //# sourceMappingURL=Sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.js","sources":["../../../src/components/layout/Sidebar.jsx"],"sourcesContent":["import React, { createContext, useContext, useState } from \"react\";\n\nconst AX_SIDEBAR_CSS = `\n.ax-sidebar { display: flex; flex-direction: column; width: var(--sidebar-w); flex: none; height: 100%; background: var(--surface-panel); border-right: 1px solid var(--border-default); transition: width var(--dur-2) var(--ease-out); overflow: hidden; }\n.ax-sidebar--collapsed { width: 56px; }\n.ax-sidebar__header { padding: 16px; display: flex; align-items: center; gap: 10px; min-height: 56px; }\n.ax-sidebar__content { flex: 1; overflow-y: auto; padding: 8px; }\n.ax-sidebar__footer { padding: 12px 16px; border-top: 1px solid var(--border-default); }\n.ax-sidebar__group { margin-bottom: 16px; }\n.ax-sidebar__group-label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 6px 10px; white-space: nowrap; }\n.ax-sidebar--collapsed .ax-sidebar__group-label { opacity: 0; }\n.ax-sidebar__item { display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none; text-align: left; cursor: pointer; padding: 8px 10px; border-radius: var(--radius-2); color: var(--text-muted); font-family: var(--font-body); font-size: var(--text-sm); position: relative; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); white-space: nowrap; }\n.ax-sidebar__item:hover { background: var(--surface-raised); color: var(--text-body); }\n.ax-sidebar__item--active { background: var(--surface-raised); color: var(--text-body); }\n.ax-sidebar__item--active::before { content: \"\"; position: absolute; left: 0; top: 7px; bottom: 7px; width: 2px; border-radius: 1px; background: var(--accent); }\n.ax-sidebar__item-icon { width: 18px; height: 18px; flex: none; display: inline-flex; align-items: center; justify-content: center; }\n.ax-sidebar__item-icon svg { width: 16px; height: 16px; }\n.ax-sidebar__item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n.ax-sidebar--collapsed .ax-sidebar__item-label { opacity: 0; }\n.ax-sidebar__item-badge { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }\n.ax-sidebar--collapsed .ax-sidebar__item-badge { display: none; }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-sidebar-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-sidebar-css\";\n s.textContent = AX_SIDEBAR_CSS;\n document.head.appendChild(s);\n}\n\nexport function Sidebar({ groups = [], activeId, onSelect, header, footer, collapsed = false, className = \"\", ...rest }) {\n return (\n <aside className={[\"ax-sidebar\", collapsed ? \"ax-sidebar--collapsed\" : \"\", className].filter(Boolean).join(\" \")} {...rest}>\n {header ? <div className=\"ax-sidebar__header\">{header}</div> : null}\n <nav className=\"ax-sidebar__content\">\n {groups.map((g, gi) => (\n <div className=\"ax-sidebar__group\" key={gi}>\n {g.label ? <div className=\"ax-sidebar__group-label\">{g.label}</div> : null}\n {g.items.map((it) => (\n <button\n key={it.id}\n className={\"ax-sidebar__item\" + (it.id === activeId ? \" ax-sidebar__item--active\" : \"\")}\n onClick={() => onSelect && onSelect(it.id)}\n title={collapsed ? it.label : undefined}\n >\n {it.icon ? <span className=\"ax-sidebar__item-icon\">{it.icon}</span> : null}\n <span className=\"ax-sidebar__item-label\">{it.label}</span>\n {it.badge != null ? <span className=\"ax-sidebar__item-badge\">{it.badge}</span> : null}\n </button>\n ))}\n </div>\n ))}\n </nav>\n {footer ? <div className=\"ax-sidebar__footer\">{footer}</div> : null}\n </aside>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBvB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,gBAAgB,GAAG;AACjF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,QAAQ,EAAE,SAAS,CAAA,GAAI,UAAU,UAAU,QAAQ,QAAQ,YAAY,OAAO,YAAY,IAAI,GAAG,QAAQ;AACvH,8BACG,SAAA,EAAM,WAAW,CAAC,cAAc,YAAY,0BAA0B,IAAI,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,MAClH,UAAA;AAAA,IAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,sBAAsB,kBAAO,IAAS;AAAA,IAC/D,oBAAC,OAAA,EAAI,WAAU,uBACZ,UAAA,OAAO,IAAI,CAAC,GAAG,OACd,qBAAC,OAAA,EAAI,WAAU,qBACZ,UAAA;AAAA,MAAA,EAAE,QAAQ,oBAAC,OAAA,EAAI,WAAU,2BAA2B,UAAA,EAAE,OAAM,IAAS;AAAA,MACrE,EAAE,MAAM,IAAI,CAAC,OACZ;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAW,sBAAsB,GAAG,OAAO,WAAW,8BAA8B;AAAA,UACpF,SAAS,MAAM,YAAY,SAAS,GAAG,EAAE;AAAA,UACzC,OAAO,YAAY,GAAG,QAAQ;AAAA,UAE7B,UAAA;AAAA,YAAA,GAAG,OAAO,oBAAC,QAAA,EAAK,WAAU,yBAAyB,UAAA,GAAG,MAAK,IAAU;AAAA,YACtE,oBAAC,QAAA,EAAK,WAAU,0BAA0B,aAAG,OAAM;AAAA,YAClD,GAAG,SAAS,OAAO,oBAAC,UAAK,WAAU,0BAA0B,UAAA,GAAG,MAAA,CAAM,IAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAP5E,GAAG;AAAA,MAAA,CASX;AAAA,IAAA,KAbqC,EAcxC,CACD,GACH;AAAA,IACC,SAAS,oBAAC,OAAA,EAAI,WAAU,sBAAsB,kBAAO,IAAS;AAAA,EAAA,GACjE;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Confirmation modal with a tone icon and cancel/confirm actions. */
2
+ export interface AlertDialogProps { open?: boolean; inline?: boolean; tone?: "danger" | "warn"; title?: React.ReactNode; description?: React.ReactNode; cancelLabel?: string; confirmLabel?: string; onCancel?: () => void; onConfirm?: () => void; }
3
+ export declare function AlertDialog(props: AlertDialogProps): JSX.Element;
@@ -0,0 +1,51 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ const AX_ALERTDIALOG_CSS = `
4
+ .ax-alertdialog-overlay { position: fixed; inset: 0; z-index: 110; display: flex; align-items: center; justify-content: center; background: var(--bg-overlay); backdrop-filter: blur(var(--blur-overlay)); -webkit-backdrop-filter: blur(var(--blur-overlay)); animation: ax-ad-fade var(--dur-2) var(--ease-out); }
5
+ .ax-alertdialog { width: min(420px, calc(100vw - 48px)); background: var(--surface-panel); border: 1px solid var(--border-strong); border-radius: var(--radius-3); box-shadow: var(--shadow-3); padding: var(--space-6); animation: ax-ad-rise var(--dur-3) var(--ease-out); }
6
+ .ax-alertdialog--inline { position: relative; animation: none; box-shadow: none; }
7
+ .ax-alertdialog__icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-2); margin-bottom: var(--space-4); }
8
+ .ax-alertdialog__icon--danger { background: var(--danger-dim); color: var(--danger); }
9
+ .ax-alertdialog__icon--warn { background: var(--warn-dim); color: var(--warn); }
10
+ .ax-alertdialog__title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-medium); letter-spacing: var(--tracking-tight); color: var(--text-body); margin: 0 0 8px; }
11
+ .ax-alertdialog__desc { font-size: var(--text-sm); color: var(--text-muted); margin: 0 0 var(--space-6); line-height: var(--leading-body); }
12
+ .ax-alertdialog__actions { display: flex; justify-content: flex-end; gap: var(--space-2); }
13
+ .ax-alertdialog__btn { display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; cursor: pointer; border-radius: var(--radius-2); font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium); border: 1px solid transparent; transition: background var(--dur-1) var(--ease-out); }
14
+ .ax-alertdialog__btn--cancel { background: transparent; color: var(--text-muted); border-color: var(--border-strong); }
15
+ .ax-alertdialog__btn--cancel:hover { background: var(--surface-raised); color: var(--text-body); }
16
+ .ax-alertdialog__btn--confirm { background: var(--accent); color: var(--accent-fg); }
17
+ .ax-alertdialog__btn--confirm:hover { background: var(--accent-hover); }
18
+ .ax-alertdialog__btn--danger { background: var(--danger); color: #fff; }
19
+ .ax-alertdialog__btn--danger:hover { filter: brightness(1.1); }
20
+ @keyframes ax-ad-fade { from { opacity: 0; } }
21
+ @keyframes ax-ad-rise { from { opacity: 0; transform: translateY(8px); } }
22
+ @media (prefers-reduced-motion: reduce) { .ax-alertdialog-overlay, .ax-alertdialog { animation: none; } }
23
+ `;
24
+ if (typeof document !== "undefined" && !document.getElementById("ax-alertdialog-css")) {
25
+ const s = document.createElement("style");
26
+ s.id = "ax-alertdialog-css";
27
+ s.textContent = AX_ALERTDIALOG_CSS;
28
+ document.head.appendChild(s);
29
+ }
30
+ const Warn = /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
31
+ /* @__PURE__ */ jsx("path", { d: "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z" }),
32
+ /* @__PURE__ */ jsx("path", { d: "M12 9v4M12 17h.01" })
33
+ ] });
34
+ function AlertDialog({ open = true, inline = false, tone = "danger", title, description, cancelLabel = "Cancel", confirmLabel = "Confirm", onCancel, onConfirm, className = "", ...rest }) {
35
+ if (!open) return null;
36
+ const panel = /* @__PURE__ */ jsxs("div", { className: ["ax-alertdialog", inline ? "ax-alertdialog--inline" : "", className].filter(Boolean).join(" "), role: "alertdialog", "aria-modal": !inline, onClick: (e) => e.stopPropagation(), ...rest, children: [
37
+ /* @__PURE__ */ jsx("div", { className: "ax-alertdialog__icon ax-alertdialog__icon--" + (tone === "warn" ? "warn" : "danger"), children: Warn }),
38
+ /* @__PURE__ */ jsx("h2", { className: "ax-alertdialog__title", children: title }),
39
+ description ? /* @__PURE__ */ jsx("p", { className: "ax-alertdialog__desc", children: description }) : null,
40
+ /* @__PURE__ */ jsxs("div", { className: "ax-alertdialog__actions", children: [
41
+ /* @__PURE__ */ jsx("button", { className: "ax-alertdialog__btn ax-alertdialog__btn--cancel", onClick: onCancel, children: cancelLabel }),
42
+ /* @__PURE__ */ jsx("button", { className: "ax-alertdialog__btn " + (tone === "danger" ? "ax-alertdialog__btn--danger" : "ax-alertdialog__btn--confirm"), onClick: onConfirm, children: confirmLabel })
43
+ ] })
44
+ ] });
45
+ if (inline) return panel;
46
+ return /* @__PURE__ */ jsx("div", { className: "ax-alertdialog-overlay", onClick: onCancel, children: panel });
47
+ }
48
+ export {
49
+ AlertDialog
50
+ };
51
+ //# sourceMappingURL=AlertDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlertDialog.js","sources":["../../../src/components/overlay/AlertDialog.jsx"],"sourcesContent":["import React from \"react\";\n\nconst AX_ALERTDIALOG_CSS = `\n.ax-alertdialog-overlay { position: fixed; inset: 0; z-index: 110; display: flex; align-items: center; justify-content: center; background: var(--bg-overlay); backdrop-filter: blur(var(--blur-overlay)); -webkit-backdrop-filter: blur(var(--blur-overlay)); animation: ax-ad-fade var(--dur-2) var(--ease-out); }\n.ax-alertdialog { width: min(420px, calc(100vw - 48px)); background: var(--surface-panel); border: 1px solid var(--border-strong); border-radius: var(--radius-3); box-shadow: var(--shadow-3); padding: var(--space-6); animation: ax-ad-rise var(--dur-3) var(--ease-out); }\n.ax-alertdialog--inline { position: relative; animation: none; box-shadow: none; }\n.ax-alertdialog__icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-2); margin-bottom: var(--space-4); }\n.ax-alertdialog__icon--danger { background: var(--danger-dim); color: var(--danger); }\n.ax-alertdialog__icon--warn { background: var(--warn-dim); color: var(--warn); }\n.ax-alertdialog__title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-medium); letter-spacing: var(--tracking-tight); color: var(--text-body); margin: 0 0 8px; }\n.ax-alertdialog__desc { font-size: var(--text-sm); color: var(--text-muted); margin: 0 0 var(--space-6); line-height: var(--leading-body); }\n.ax-alertdialog__actions { display: flex; justify-content: flex-end; gap: var(--space-2); }\n.ax-alertdialog__btn { display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; cursor: pointer; border-radius: var(--radius-2); font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium); border: 1px solid transparent; transition: background var(--dur-1) var(--ease-out); }\n.ax-alertdialog__btn--cancel { background: transparent; color: var(--text-muted); border-color: var(--border-strong); }\n.ax-alertdialog__btn--cancel:hover { background: var(--surface-raised); color: var(--text-body); }\n.ax-alertdialog__btn--confirm { background: var(--accent); color: var(--accent-fg); }\n.ax-alertdialog__btn--confirm:hover { background: var(--accent-hover); }\n.ax-alertdialog__btn--danger { background: var(--danger); color: #fff; }\n.ax-alertdialog__btn--danger:hover { filter: brightness(1.1); }\n@keyframes ax-ad-fade { from { opacity: 0; } }\n@keyframes ax-ad-rise { from { opacity: 0; transform: translateY(8px); } }\n@media (prefers-reduced-motion: reduce) { .ax-alertdialog-overlay, .ax-alertdialog { animation: none; } }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-alertdialog-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-alertdialog-css\";\n s.textContent = AX_ALERTDIALOG_CSS;\n document.head.appendChild(s);\n}\n\nconst Warn = <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z\"></path><path d=\"M12 9v4M12 17h.01\"></path></svg>;\n\nexport function AlertDialog({ open = true, inline = false, tone = \"danger\", title, description, cancelLabel = \"Cancel\", confirmLabel = \"Confirm\", onCancel, onConfirm, className = \"\", ...rest }) {\n if (!open) return null;\n const panel = (\n <div className={[\"ax-alertdialog\", inline ? \"ax-alertdialog--inline\" : \"\", className].filter(Boolean).join(\" \")} role=\"alertdialog\" aria-modal={!inline} onClick={(e) => e.stopPropagation()} {...rest}>\n <div className={\"ax-alertdialog__icon ax-alertdialog__icon--\" + (tone === \"warn\" ? \"warn\" : \"danger\")}>{Warn}</div>\n <h2 className=\"ax-alertdialog__title\">{title}</h2>\n {description ? <p className=\"ax-alertdialog__desc\">{description}</p> : null}\n <div className=\"ax-alertdialog__actions\">\n <button className=\"ax-alertdialog__btn ax-alertdialog__btn--cancel\" onClick={onCancel}>{cancelLabel}</button>\n <button className={\"ax-alertdialog__btn \" + (tone === \"danger\" ? \"ax-alertdialog__btn--danger\" : \"ax-alertdialog__btn--confirm\")} onClick={onConfirm}>{confirmLabel}</button>\n </div>\n </div>\n );\n if (inline) return panel;\n return <div className=\"ax-alertdialog-overlay\" onClick={onCancel}>{panel}</div>;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsB3B,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,oBAAoB,GAAG;AACrF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEA,MAAM,OAAO,qBAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,gFAAA,CAAgF;AAAA,EAAO,oBAAC,QAAA,EAAK,GAAE,oBAAA,CAAoB;AAAA,GAAO;AAEvR,SAAS,YAAY,EAAE,OAAO,MAAM,SAAS,OAAO,OAAO,UAAU,OAAO,aAAa,cAAc,UAAU,eAAe,WAAW,UAAU,WAAW,YAAY,IAAI,GAAG,QAAQ;AAChM,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QACJ,qBAAC,OAAA,EAAI,WAAW,CAAC,kBAAkB,SAAS,2BAA2B,IAAI,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAG,MAAK,eAAc,cAAY,CAAC,QAAQ,SAAS,CAAC,MAAM,EAAE,gBAAA,GAAoB,GAAG,MAChM,UAAA;AAAA,IAAA,oBAAC,SAAI,WAAW,iDAAiD,SAAS,SAAS,SAAS,WAAY,UAAA,KAAA,CAAK;AAAA,IAC7G,oBAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,OAAM;AAAA,IAC5C,cAAc,oBAAC,KAAA,EAAE,WAAU,wBAAwB,uBAAY,IAAO;AAAA,IACvE,qBAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAA,oBAAC,UAAA,EAAO,WAAU,mDAAkD,SAAS,UAAW,UAAA,aAAY;AAAA,MACpG,oBAAC,UAAA,EAAO,WAAW,0BAA0B,SAAS,WAAW,gCAAgC,iCAAiC,SAAS,WAAY,UAAA,aAAA,CAAa;AAAA,IAAA,EAAA,CACtK;AAAA,EAAA,GACF;AAEF,MAAI,OAAQ,QAAO;AACnB,6BAAQ,OAAA,EAAI,WAAU,0BAAyB,SAAS,UAAW,UAAA,OAAM;AAC3E;"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @startingPoint section="Overlay" subtitle="⌘K command palette — search + keyboard nav" viewport="600x420"
3
+ * Command palette: fuzzy filter, ↑/↓/↵ keyboard nav, grouped results.
4
+ */
5
+ export interface CommandItem {
6
+ id?: string;
7
+ label: string;
8
+ icon?: React.ReactNode;
9
+ shortcut?: string;
10
+ }
11
+ export interface CommandProps {
12
+ /** @default true */
13
+ open?: boolean;
14
+ /** Render without the fixed overlay (docs/specimens). @default false */
15
+ inline?: boolean;
16
+ /** Grouped commands: { label, items }. */
17
+ groups: Array<{ label?: string; items: CommandItem[] }>;
18
+ placeholder?: string;
19
+ onClose?: () => void;
20
+ onSelect?: (item: CommandItem) => void;
21
+ }
22
+ export declare function Command(props: CommandProps): JSX.Element;
@@ -0,0 +1,123 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useMemo, useEffect } from "react";
3
+ const AX_COMMAND_CSS = `
4
+ .ax-cmd-overlay {
5
+ position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-start; justify-content: center;
6
+ padding-top: 14vh; background: var(--bg-overlay);
7
+ backdrop-filter: blur(var(--blur-overlay)); -webkit-backdrop-filter: blur(var(--blur-overlay));
8
+ animation: ax-cmd-fade var(--dur-2) var(--ease-out);
9
+ }
10
+ .ax-cmd {
11
+ width: min(560px, calc(100vw - 48px)); max-height: 60vh; display: flex; flex-direction: column;
12
+ background: var(--surface-panel); border: 1px solid var(--border-strong);
13
+ border-radius: var(--radius-3); box-shadow: var(--shadow-3); overflow: hidden;
14
+ animation: ax-cmd-rise var(--dur-3) var(--ease-out);
15
+ }
16
+ .ax-cmd--inline { position: relative; animation: none; max-height: 340px; }
17
+ .ax-cmd__head { display: flex; align-items: center; gap: 10px; padding: 0 14px; border-bottom: 1px solid var(--border-default); }
18
+ .ax-cmd__icon { color: var(--text-faint); flex: none; }
19
+ .ax-cmd__input { flex: 1; height: 48px; background: none; border: none; outline: none; color: var(--text-body); font-family: var(--font-body); font-size: var(--text-md); }
20
+ .ax-cmd__input::placeholder { color: var(--text-faint); }
21
+ .ax-cmd__esc { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); border: 1px solid var(--border-default); border-radius: var(--radius-1); padding: 2px 5px; }
22
+ .ax-cmd__list { overflow-y: auto; padding: var(--space-1); }
23
+ .ax-cmd__group-label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }
24
+ .ax-cmd__item {
25
+ display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none;
26
+ text-align: left; cursor: pointer; padding: 9px 10px; border-radius: var(--radius-2);
27
+ color: var(--text-body); font-family: var(--font-body); font-size: var(--text-sm);
28
+ }
29
+ .ax-cmd__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }
30
+ .ax-cmd__item--active { background: var(--surface-raised); }
31
+ .ax-cmd__item-shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
32
+ .ax-cmd__empty { padding: 28px; text-align: center; color: var(--text-faint); font-size: var(--text-sm); }
33
+ @keyframes ax-cmd-fade { from { opacity: 0; } }
34
+ @keyframes ax-cmd-rise { from { opacity: 0; transform: translateY(-8px); } }
35
+ @media (prefers-reduced-motion: reduce) { .ax-cmd-overlay, .ax-cmd { animation: none; } }
36
+ `;
37
+ if (typeof document !== "undefined" && !document.getElementById("ax-command-css")) {
38
+ const s = document.createElement("style");
39
+ s.id = "ax-command-css";
40
+ s.textContent = AX_COMMAND_CSS;
41
+ document.head.appendChild(s);
42
+ }
43
+ function Command({ open = true, inline = false, groups = [], placeholder = "Type a command or search…", onClose, onSelect, className = "", ...rest }) {
44
+ const [query, setQuery] = useState("");
45
+ const [active, setActive] = useState(0);
46
+ const inputRef = useRef(null);
47
+ const flat = useMemo(() => {
48
+ const q = query.trim().toLowerCase();
49
+ const out = [];
50
+ for (const g of groups) {
51
+ const matched = g.items.filter((it) => !q || it.label.toLowerCase().includes(q));
52
+ if (matched.length) out.push({ label: g.label, items: matched });
53
+ }
54
+ return out;
55
+ }, [groups, query]);
56
+ const flatItems = useMemo(() => flat.flatMap((g) => g.items), [flat]);
57
+ useEffect(() => {
58
+ setActive(0);
59
+ }, [query]);
60
+ useEffect(() => {
61
+ if (open && inputRef.current) inputRef.current.focus();
62
+ }, [open]);
63
+ if (!open) return null;
64
+ const choose = (it) => {
65
+ onSelect && onSelect(it);
66
+ onClose && onClose();
67
+ };
68
+ const onKey = (e) => {
69
+ if (e.key === "ArrowDown") {
70
+ e.preventDefault();
71
+ setActive((a) => Math.min(a + 1, flatItems.length - 1));
72
+ } else if (e.key === "ArrowUp") {
73
+ e.preventDefault();
74
+ setActive((a) => Math.max(a - 1, 0));
75
+ } else if (e.key === "Enter") {
76
+ e.preventDefault();
77
+ if (flatItems[active]) choose(flatItems[active]);
78
+ } else if (e.key === "Escape") {
79
+ onClose && onClose();
80
+ }
81
+ };
82
+ let idx = -1;
83
+ const panel = /* @__PURE__ */ jsxs("div", { className: ["ax-cmd", inline ? "ax-cmd--inline" : "", className].filter(Boolean).join(" "), onClick: (e) => e.stopPropagation(), ...rest, children: [
84
+ /* @__PURE__ */ jsxs("div", { className: "ax-cmd__head", children: [
85
+ /* @__PURE__ */ jsxs("svg", { className: "ax-cmd__icon", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
86
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
87
+ /* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
88
+ ] }),
89
+ /* @__PURE__ */ jsx("input", { ref: inputRef, className: "ax-cmd__input", placeholder, value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: onKey }),
90
+ /* @__PURE__ */ jsx("span", { className: "ax-cmd__esc", children: "ESC" })
91
+ ] }),
92
+ /* @__PURE__ */ jsxs("div", { className: "ax-cmd__list", children: [
93
+ flatItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ax-cmd__empty", children: "No results." }) : null,
94
+ flat.map((g) => /* @__PURE__ */ jsxs("div", { children: [
95
+ g.label ? /* @__PURE__ */ jsx("div", { className: "ax-cmd__group-label", children: g.label }) : null,
96
+ g.items.map((it) => {
97
+ idx++;
98
+ const myIdx = idx;
99
+ return /* @__PURE__ */ jsxs(
100
+ "button",
101
+ {
102
+ className: "ax-cmd__item" + (myIdx === active ? " ax-cmd__item--active" : ""),
103
+ onMouseEnter: () => setActive(myIdx),
104
+ onClick: () => choose(it),
105
+ children: [
106
+ it.icon,
107
+ /* @__PURE__ */ jsx("span", { children: it.label }),
108
+ it.shortcut ? /* @__PURE__ */ jsx("span", { className: "ax-cmd__item-shortcut", children: it.shortcut }) : null
109
+ ]
110
+ },
111
+ it.id || it.label
112
+ );
113
+ })
114
+ ] }, g.label))
115
+ ] })
116
+ ] });
117
+ if (inline) return panel;
118
+ return /* @__PURE__ */ jsx("div", { className: "ax-cmd-overlay", onClick: onClose, children: panel });
119
+ }
120
+ export {
121
+ Command
122
+ };
123
+ //# sourceMappingURL=Command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Command.js","sources":["../../../src/components/overlay/Command.jsx"],"sourcesContent":["import React, { useState, useMemo, useEffect, useRef } from \"react\";\n\nconst AX_COMMAND_CSS = `\n.ax-cmd-overlay {\n position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-start; justify-content: center;\n padding-top: 14vh; background: var(--bg-overlay);\n backdrop-filter: blur(var(--blur-overlay)); -webkit-backdrop-filter: blur(var(--blur-overlay));\n animation: ax-cmd-fade var(--dur-2) var(--ease-out);\n}\n.ax-cmd {\n width: min(560px, calc(100vw - 48px)); max-height: 60vh; display: flex; flex-direction: column;\n background: var(--surface-panel); border: 1px solid var(--border-strong);\n border-radius: var(--radius-3); box-shadow: var(--shadow-3); overflow: hidden;\n animation: ax-cmd-rise var(--dur-3) var(--ease-out);\n}\n.ax-cmd--inline { position: relative; animation: none; max-height: 340px; }\n.ax-cmd__head { display: flex; align-items: center; gap: 10px; padding: 0 14px; border-bottom: 1px solid var(--border-default); }\n.ax-cmd__icon { color: var(--text-faint); flex: none; }\n.ax-cmd__input { flex: 1; height: 48px; background: none; border: none; outline: none; color: var(--text-body); font-family: var(--font-body); font-size: var(--text-md); }\n.ax-cmd__input::placeholder { color: var(--text-faint); }\n.ax-cmd__esc { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); border: 1px solid var(--border-default); border-radius: var(--radius-1); padding: 2px 5px; }\n.ax-cmd__list { overflow-y: auto; padding: var(--space-1); }\n.ax-cmd__group-label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }\n.ax-cmd__item {\n display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none;\n text-align: left; cursor: pointer; padding: 9px 10px; border-radius: var(--radius-2);\n color: var(--text-body); font-family: var(--font-body); font-size: var(--text-sm);\n}\n.ax-cmd__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }\n.ax-cmd__item--active { background: var(--surface-raised); }\n.ax-cmd__item-shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }\n.ax-cmd__empty { padding: 28px; text-align: center; color: var(--text-faint); font-size: var(--text-sm); }\n@keyframes ax-cmd-fade { from { opacity: 0; } }\n@keyframes ax-cmd-rise { from { opacity: 0; transform: translateY(-8px); } }\n@media (prefers-reduced-motion: reduce) { .ax-cmd-overlay, .ax-cmd { animation: none; } }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-command-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-command-css\";\n s.textContent = AX_COMMAND_CSS;\n document.head.appendChild(s);\n}\n\nexport function Command({ open = true, inline = false, groups = [], placeholder = \"Type a command or search…\", onClose, onSelect, className = \"\", ...rest }) {\n const [query, setQuery] = useState(\"\");\n const [active, setActive] = useState(0);\n const inputRef = useRef(null);\n\n const flat = useMemo(() => {\n const q = query.trim().toLowerCase();\n const out = [];\n for (const g of groups) {\n const matched = g.items.filter((it) => !q || it.label.toLowerCase().includes(q));\n if (matched.length) out.push({ label: g.label, items: matched });\n }\n return out;\n }, [groups, query]);\n\n const flatItems = useMemo(() => flat.flatMap((g) => g.items), [flat]);\n\n useEffect(() => { setActive(0); }, [query]);\n useEffect(() => { if (open && inputRef.current) inputRef.current.focus(); }, [open]);\n\n if (!open) return null;\n\n const choose = (it) => { onSelect && onSelect(it); onClose && onClose(); };\n\n const onKey = (e) => {\n if (e.key === \"ArrowDown\") { e.preventDefault(); setActive((a) => Math.min(a + 1, flatItems.length - 1)); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); setActive((a) => Math.max(a - 1, 0)); }\n else if (e.key === \"Enter\") { e.preventDefault(); if (flatItems[active]) choose(flatItems[active]); }\n else if (e.key === \"Escape\") { onClose && onClose(); }\n };\n\n let idx = -1;\n const panel = (\n <div className={[\"ax-cmd\", inline ? \"ax-cmd--inline\" : \"\", className].filter(Boolean).join(\" \")} onClick={(e) => e.stopPropagation()} {...rest}>\n <div className=\"ax-cmd__head\">\n <svg className=\"ax-cmd__icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"></circle><path d=\"m21 21-4.3-4.3\"></path></svg>\n <input ref={inputRef} className=\"ax-cmd__input\" placeholder={placeholder} value={query} onChange={(e) => setQuery(e.target.value)} onKeyDown={onKey} />\n <span className=\"ax-cmd__esc\">ESC</span>\n </div>\n <div className=\"ax-cmd__list\">\n {flatItems.length === 0 ? <div className=\"ax-cmd__empty\">No results.</div> : null}\n {flat.map((g) => (\n <div key={g.label}>\n {g.label ? <div className=\"ax-cmd__group-label\">{g.label}</div> : null}\n {g.items.map((it) => {\n idx++;\n const myIdx = idx;\n return (\n <button\n key={it.id || it.label}\n className={\"ax-cmd__item\" + (myIdx === active ? \" ax-cmd__item--active\" : \"\")}\n onMouseEnter={() => setActive(myIdx)}\n onClick={() => choose(it)}\n >\n {it.icon}\n <span>{it.label}</span>\n {it.shortcut ? <span className=\"ax-cmd__item-shortcut\">{it.shortcut}</span> : null}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n </div>\n );\n\n if (inline) return panel;\n return <div className=\"ax-cmd-overlay\" onClick={onClose}>{panel}</div>;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCvB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,gBAAgB,GAAG;AACjF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,QAAQ,EAAE,OAAO,MAAM,SAAS,OAAO,SAAS,CAAA,GAAI,cAAc,6BAA6B,SAAS,UAAU,YAAY,IAAI,GAAG,QAAQ;AAC3J,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,WAAW,OAAO,IAAI;AAE5B,QAAM,OAAO,QAAQ,MAAM;AACzB,UAAM,IAAI,MAAM,KAAA,EAAO,YAAA;AACvB,UAAM,MAAM,CAAA;AACZ,eAAW,KAAK,QAAQ;AACtB,YAAM,UAAU,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,MAAM,YAAA,EAAc,SAAS,CAAC,CAAC;AAC/E,UAAI,QAAQ,OAAQ,KAAI,KAAK,EAAE,OAAO,EAAE,OAAO,OAAO,SAAS;AAAA,IACjE;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,KAAK,CAAC;AAElB,QAAM,YAAY,QAAQ,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC;AAEpE,YAAU,MAAM;AAAE,cAAU,CAAC;AAAA,EAAG,GAAG,CAAC,KAAK,CAAC;AAC1C,YAAU,MAAM;AAAE,QAAI,QAAQ,SAAS,QAAS,UAAS,QAAQ,MAAA;AAAA,EAAS,GAAG,CAAC,IAAI,CAAC;AAEnF,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,SAAS,CAAC,OAAO;AAAE,gBAAY,SAAS,EAAE;AAAG,eAAW,QAAA;AAAA,EAAW;AAEzE,QAAM,QAAQ,CAAC,MAAM;AACnB,QAAI,EAAE,QAAQ,aAAa;AAAE,QAAE,eAAA;AAAkB,gBAAU,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,UAAU,SAAS,CAAC,CAAC;AAAA,IAAG,WACjG,EAAE,QAAQ,WAAW;AAAE,QAAE,eAAA;AAAkB,gBAAU,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC;AAAA,IAAG,WACjF,EAAE,QAAQ,SAAS;AAAE,QAAE,eAAA;AAAkB,UAAI,UAAU,MAAM,EAAG,QAAO,UAAU,MAAM,CAAC;AAAA,IAAG,WAC3F,EAAE,QAAQ,UAAU;AAAE,iBAAW,QAAA;AAAA,IAAW;AAAA,EACvD;AAEA,MAAI,MAAM;AACV,QAAM,QACJ,qBAAC,OAAA,EAAI,WAAW,CAAC,UAAU,SAAS,mBAAmB,IAAI,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,gBAAA,GAAoB,GAAG,MACxI,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,MAAA,qBAAC,SAAI,WAAU,gBAAe,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,UAAA;AAAA,QAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,QAAS,oBAAC,QAAA,EAAK,GAAE,iBAAA,CAAiB;AAAA,MAAA,GAAO;AAAA,0BACvN,SAAA,EAAM,KAAK,UAAU,WAAU,iBAAgB,aAA0B,OAAO,OAAO,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK,GAAG,WAAW,OAAO;AAAA,MACrJ,oBAAC,QAAA,EAAK,WAAU,eAAc,UAAA,MAAA,CAAG;AAAA,IAAA,GACnC;AAAA,IACA,qBAAC,OAAA,EAAI,WAAU,gBACZ,UAAA;AAAA,MAAA,UAAU,WAAW,IAAI,oBAAC,SAAI,WAAU,iBAAgB,yBAAW,IAAS;AAAA,MAC5E,KAAK,IAAI,CAAC,2BACR,OAAA,EACE,UAAA;AAAA,QAAA,EAAE,QAAQ,oBAAC,OAAA,EAAI,WAAU,uBAAuB,UAAA,EAAE,OAAM,IAAS;AAAA,QACjE,EAAE,MAAM,IAAI,CAAC,OAAO;AACnB;AACA,gBAAM,QAAQ;AACd,iBACE;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,WAAW,kBAAkB,UAAU,SAAS,0BAA0B;AAAA,cAC1E,cAAc,MAAM,UAAU,KAAK;AAAA,cACnC,SAAS,MAAM,OAAO,EAAE;AAAA,cAEvB,UAAA;AAAA,gBAAA,GAAG;AAAA,gBACJ,oBAAC,QAAA,EAAM,UAAA,GAAG,MAAA,CAAM;AAAA,gBACf,GAAG,WAAW,oBAAC,QAAA,EAAK,WAAU,yBAAyB,UAAA,GAAG,UAAS,IAAU;AAAA,cAAA;AAAA,YAAA;AAAA,YAPzE,GAAG,MAAM,GAAG;AAAA,UAAA;AAAA,QAUvB,CAAC;AAAA,MAAA,EAAA,GAjBO,EAAE,KAkBZ,CACD;AAAA,IAAA,EAAA,CACH;AAAA,EAAA,GACF;AAGF,MAAI,OAAQ,QAAO;AACnB,6BAAQ,OAAA,EAAI,WAAU,kBAAiB,SAAS,SAAU,UAAA,OAAM;AAClE;"}
@@ -0,0 +1,4 @@
1
+ /** Right-click context menu; items support icons, shortcuts, danger, separators, labels. */
2
+ export interface ContextMenuItem { label?: React.ReactNode; icon?: React.ReactNode; shortcut?: string; danger?: boolean; onSelect?: () => void; type?: "separator" | "label"; }
3
+ export interface ContextMenuProps { items: ContextMenuItem[]; children?: React.ReactNode; }
4
+ export declare function ContextMenu(props: ContextMenuProps): JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import React, { useState, useRef, useCallback, useEffect } from "react";
3
+ const AX_CTXMENU_CSS = `
4
+ .ax-ctxmenu-trigger { display: contents; }
5
+ .ax-ctxmenu { position: fixed; z-index: 80; min-width: 190px; background: var(--surface-panel); border: 1px solid var(--border-strong); border-radius: var(--radius-3); box-shadow: var(--shadow-2); padding: var(--space-1); animation: ax-ctxmenu-in var(--dur-1) var(--ease-out); }
6
+ .ax-ctxmenu__item { display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none; text-align: left; cursor: pointer; padding: 7px 10px; border-radius: var(--radius-2); color: var(--text-body); font-family: var(--font-body); font-size: var(--text-sm); }
7
+ .ax-ctxmenu__item:hover { background: var(--surface-raised); }
8
+ .ax-ctxmenu__item--danger { color: var(--danger); }
9
+ .ax-ctxmenu__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }
10
+ .ax-ctxmenu__item--danger svg { color: var(--danger); }
11
+ .ax-ctxmenu__shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
12
+ .ax-ctxmenu__sep { height: 1px; background: var(--border-default); margin: var(--space-1) 0; }
13
+ .ax-ctxmenu__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }
14
+ @keyframes ax-ctxmenu-in { from { opacity: 0; transform: scale(0.97); } }
15
+ @media (prefers-reduced-motion: reduce) { .ax-ctxmenu { animation: none; } }
16
+ `;
17
+ if (typeof document !== "undefined" && !document.getElementById("ax-ctxmenu-css")) {
18
+ const s = document.createElement("style");
19
+ s.id = "ax-ctxmenu-css";
20
+ s.textContent = AX_CTXMENU_CSS;
21
+ document.head.appendChild(s);
22
+ }
23
+ function ContextMenu({ items = [], children, className = "", ...rest }) {
24
+ const [menu, setMenu] = useState(null);
25
+ const ref = useRef(null);
26
+ const onContext = (e) => {
27
+ e.preventDefault();
28
+ setMenu({ x: e.clientX, y: e.clientY });
29
+ };
30
+ const close = useCallback(() => setMenu(null), []);
31
+ useEffect(() => {
32
+ if (menu) {
33
+ const onDoc = () => close();
34
+ const onKey = (e) => {
35
+ if (e.key === "Escape") close();
36
+ };
37
+ document.addEventListener("mousedown", onDoc);
38
+ document.addEventListener("keydown", onKey);
39
+ document.addEventListener("scroll", onDoc, true);
40
+ return () => {
41
+ document.removeEventListener("mousedown", onDoc);
42
+ document.removeEventListener("keydown", onKey);
43
+ document.removeEventListener("scroll", onDoc, true);
44
+ };
45
+ }
46
+ }, [menu, close]);
47
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
48
+ /* @__PURE__ */ jsx("div", { className: "ax-ctxmenu-trigger", onContextMenu: onContext, ref, ...rest, children }),
49
+ menu ? /* @__PURE__ */ jsx("div", { className: ["ax-ctxmenu", className].filter(Boolean).join(" "), style: { left: menu.x, top: menu.y }, onClick: (e) => e.stopPropagation(), children: items.map((it, i) => {
50
+ if (it.type === "separator") return /* @__PURE__ */ jsx("div", { className: "ax-ctxmenu__sep" }, i);
51
+ if (it.type === "label") return /* @__PURE__ */ jsx("div", { className: "ax-ctxmenu__label", children: it.label }, i);
52
+ return /* @__PURE__ */ jsxs("button", { className: "ax-ctxmenu__item" + (it.danger ? " ax-ctxmenu__item--danger" : ""), onClick: () => {
53
+ close();
54
+ it.onSelect && it.onSelect();
55
+ }, children: [
56
+ it.icon,
57
+ /* @__PURE__ */ jsx("span", { children: it.label }),
58
+ it.shortcut ? /* @__PURE__ */ jsx("span", { className: "ax-ctxmenu__shortcut", children: it.shortcut }) : null
59
+ ] }, i);
60
+ }) }) : null
61
+ ] });
62
+ }
63
+ export {
64
+ ContextMenu
65
+ };
66
+ //# sourceMappingURL=ContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextMenu.js","sources":["../../../src/components/overlay/ContextMenu.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\n\nconst AX_CTXMENU_CSS = `\n.ax-ctxmenu-trigger { display: contents; }\n.ax-ctxmenu { position: fixed; z-index: 80; min-width: 190px; background: var(--surface-panel); border: 1px solid var(--border-strong); border-radius: var(--radius-3); box-shadow: var(--shadow-2); padding: var(--space-1); animation: ax-ctxmenu-in var(--dur-1) var(--ease-out); }\n.ax-ctxmenu__item { display: flex; align-items: center; gap: 10px; width: 100%; appearance: none; background: none; border: none; text-align: left; cursor: pointer; padding: 7px 10px; border-radius: var(--radius-2); color: var(--text-body); font-family: var(--font-body); font-size: var(--text-sm); }\n.ax-ctxmenu__item:hover { background: var(--surface-raised); }\n.ax-ctxmenu__item--danger { color: var(--danger); }\n.ax-ctxmenu__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }\n.ax-ctxmenu__item--danger svg { color: var(--danger); }\n.ax-ctxmenu__shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }\n.ax-ctxmenu__sep { height: 1px; background: var(--border-default); margin: var(--space-1) 0; }\n.ax-ctxmenu__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }\n@keyframes ax-ctxmenu-in { from { opacity: 0; transform: scale(0.97); } }\n@media (prefers-reduced-motion: reduce) { .ax-ctxmenu { animation: none; } }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-ctxmenu-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-ctxmenu-css\";\n s.textContent = AX_CTXMENU_CSS;\n document.head.appendChild(s);\n}\n\nexport function ContextMenu({ items = [], children, className = \"\", ...rest }) {\n const [menu, setMenu] = useState(null); // {x,y}\n const ref = useRef(null);\n\n const onContext = (e) => { e.preventDefault(); setMenu({ x: e.clientX, y: e.clientY }); };\n const close = useCallback(() => setMenu(null), []);\n useEffect(() => {\n if (menu) {\n const onDoc = () => close();\n const onKey = (e) => { if (e.key === \"Escape\") close(); };\n document.addEventListener(\"mousedown\", onDoc);\n document.addEventListener(\"keydown\", onKey);\n document.addEventListener(\"scroll\", onDoc, true);\n return () => { document.removeEventListener(\"mousedown\", onDoc); document.removeEventListener(\"keydown\", onKey); document.removeEventListener(\"scroll\", onDoc, true); };\n }\n }, [menu, close]);\n\n return (\n <React.Fragment>\n <div className=\"ax-ctxmenu-trigger\" onContextMenu={onContext} ref={ref} {...rest}>{children}</div>\n {menu ? (\n <div className={[\"ax-ctxmenu\", className].filter(Boolean).join(\" \")} style={{ left: menu.x, top: menu.y }} onClick={(e) => e.stopPropagation()}>\n {items.map((it, i) => {\n if (it.type === \"separator\") return <div key={i} className=\"ax-ctxmenu__sep\"></div>;\n if (it.type === \"label\") return <div key={i} className=\"ax-ctxmenu__label\">{it.label}</div>;\n return (\n <button key={i} className={\"ax-ctxmenu__item\" + (it.danger ? \" ax-ctxmenu__item--danger\" : \"\")} onClick={() => { close(); it.onSelect && it.onSelect(); }}>\n {it.icon}<span>{it.label}</span>{it.shortcut ? <span className=\"ax-ctxmenu__shortcut\">{it.shortcut}</span> : null}\n </button>\n );\n })}\n </div>\n ) : null}\n </React.Fragment>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAevB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,gBAAgB,GAAG;AACjF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,YAAY,EAAE,QAAQ,IAAI,UAAU,YAAY,IAAI,GAAG,QAAQ;AAC7E,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,IAAI;AACrC,QAAM,MAAM,OAAO,IAAI;AAEvB,QAAM,YAAY,CAAC,MAAM;AAAE,MAAE,eAAA;AAAkB,YAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,SAAS;AAAA,EAAG;AACxF,QAAM,QAAQ,YAAY,MAAM,QAAQ,IAAI,GAAG,CAAA,CAAE;AACjD,YAAU,MAAM;AACd,QAAI,MAAM;AACR,YAAM,QAAQ,MAAM,MAAA;AACpB,YAAM,QAAQ,CAAC,MAAM;AAAE,YAAI,EAAE,QAAQ,SAAU,OAAA;AAAA,MAAS;AACxD,eAAS,iBAAiB,aAAa,KAAK;AAC5C,eAAS,iBAAiB,WAAW,KAAK;AAC1C,eAAS,iBAAiB,UAAU,OAAO,IAAI;AAC/C,aAAO,MAAM;AAAE,iBAAS,oBAAoB,aAAa,KAAK;AAAG,iBAAS,oBAAoB,WAAW,KAAK;AAAG,iBAAS,oBAAoB,UAAU,OAAO,IAAI;AAAA,MAAG;AAAA,IACxK;AAAA,EACF,GAAG,CAAC,MAAM,KAAK,CAAC;AAEhB,SACE,qBAAC,MAAM,UAAN,EACC,UAAA;AAAA,IAAA,oBAAC,OAAA,EAAI,WAAU,sBAAqB,eAAe,WAAW,KAAW,GAAG,MAAO,UAAS;AAAA,IAC3F,OACC,oBAAC,OAAA,EAAI,WAAW,CAAC,cAAc,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAG,OAAO,EAAE,MAAM,KAAK,GAAG,KAAK,KAAK,EAAA,GAAK,SAAS,CAAC,MAAM,EAAE,mBAC1H,UAAA,MAAM,IAAI,CAAC,IAAI,MAAM;AACpB,UAAI,GAAG,SAAS,YAAa,4BAAQ,OAAA,EAAY,WAAU,qBAAb,CAA+B;AAC7E,UAAI,GAAG,SAAS,QAAS,QAAO,oBAAC,SAAY,WAAU,qBAAqB,UAAA,GAAG,MAAA,GAArC,CAA2C;AACrF,aACE,qBAAC,YAAe,WAAW,sBAAsB,GAAG,SAAS,8BAA8B,KAAK,SAAS,MAAM;AAAE,cAAA;AAAS,WAAG,YAAY,GAAG,SAAA;AAAA,MAAY,GACrJ,UAAA;AAAA,QAAA,GAAG;AAAA,QAAK,oBAAC,QAAA,EAAM,UAAA,GAAG,MAAA,CAAM;AAAA,QAAQ,GAAG,WAAW,oBAAC,QAAA,EAAK,WAAU,wBAAwB,UAAA,GAAG,UAAS,IAAU;AAAA,MAAA,EAAA,GADlG,CAEb;AAAA,IAEJ,CAAC,GACH,IACE;AAAA,EAAA,GACN;AAEJ;"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Action menu. Items support icons, shortcuts, danger styling, separators and labels.
3
+ */
4
+ export interface MenuItem {
5
+ label?: React.ReactNode;
6
+ icon?: React.ReactNode;
7
+ shortcut?: string;
8
+ danger?: boolean;
9
+ disabled?: boolean;
10
+ onSelect?: () => void;
11
+ /** "separator" | "label" for structural rows. */
12
+ type?: "separator" | "label";
13
+ }
14
+ export interface DropdownMenuProps {
15
+ trigger: React.ReactNode;
16
+ items: MenuItem[];
17
+ /** @default "start" */
18
+ align?: "start" | "end";
19
+ }
20
+ export declare function DropdownMenu(props: DropdownMenuProps): JSX.Element;
@@ -0,0 +1,86 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
+ const AX_MENU_CSS = `
4
+ .ax-menu { position: relative; display: inline-flex; }
5
+ .ax-menu__panel {
6
+ position: absolute; z-index: 60; min-width: 200px; top: calc(100% + 6px);
7
+ background: var(--surface-panel); border: 1px solid var(--border-strong);
8
+ border-radius: var(--radius-3); box-shadow: var(--shadow-2); padding: var(--space-1);
9
+ animation: ax-menu-in var(--dur-2) var(--ease-out);
10
+ }
11
+ .ax-menu__panel--end { right: 0; }
12
+ .ax-menu__panel--start { left: 0; }
13
+ .ax-menu__item {
14
+ display: flex; align-items: center; gap: 10px; width: 100%;
15
+ appearance: none; background: none; border: none; text-align: left; cursor: pointer;
16
+ padding: 7px 10px; border-radius: var(--radius-2); color: var(--text-body);
17
+ font-family: var(--font-body); font-size: var(--text-sm);
18
+ transition: background var(--dur-1) var(--ease-out);
19
+ }
20
+ .ax-menu__item:hover { background: var(--surface-raised); }
21
+ .ax-menu__item:focus-visible { outline: none; background: var(--surface-raised); }
22
+ .ax-menu__item--danger { color: var(--danger); }
23
+ .ax-menu__item:disabled { opacity: 0.4; cursor: not-allowed; }
24
+ .ax-menu__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }
25
+ .ax-menu__item--danger svg { color: var(--danger); }
26
+ .ax-menu__shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); letter-spacing: 0.04em; }
27
+ .ax-menu__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }
28
+ .ax-menu__sep { height: 1px; background: var(--border-default); margin: var(--space-1) 0; }
29
+ @keyframes ax-menu-in { from { opacity: 0; transform: translateY(-4px); } }
30
+ @media (prefers-reduced-motion: reduce) { .ax-menu__panel { animation: none; } }
31
+ `;
32
+ if (typeof document !== "undefined" && !document.getElementById("ax-menu-css")) {
33
+ const s = document.createElement("style");
34
+ s.id = "ax-menu-css";
35
+ s.textContent = AX_MENU_CSS;
36
+ document.head.appendChild(s);
37
+ }
38
+ function DropdownMenu({ trigger, items = [], align = "start", className = "", ...rest }) {
39
+ const [open, setOpen] = useState(false);
40
+ const ref = useRef(null);
41
+ const onDoc = useCallback((e) => {
42
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
43
+ }, []);
44
+ useEffect(() => {
45
+ if (open) {
46
+ document.addEventListener("mousedown", onDoc);
47
+ const onKey = (e) => {
48
+ if (e.key === "Escape") setOpen(false);
49
+ };
50
+ document.addEventListener("keydown", onKey);
51
+ return () => {
52
+ document.removeEventListener("mousedown", onDoc);
53
+ document.removeEventListener("keydown", onKey);
54
+ };
55
+ }
56
+ }, [open, onDoc]);
57
+ return /* @__PURE__ */ jsxs("span", { className: ["ax-menu", className].filter(Boolean).join(" "), ref, ...rest, children: [
58
+ /* @__PURE__ */ jsx("span", { onClick: () => setOpen((o) => !o), children: trigger }),
59
+ open ? /* @__PURE__ */ jsx("div", { className: "ax-menu__panel ax-menu__panel--" + align, role: "menu", children: items.map((it, i) => {
60
+ if (it.type === "separator") return /* @__PURE__ */ jsx("div", { className: "ax-menu__sep" }, i);
61
+ if (it.type === "label") return /* @__PURE__ */ jsx("div", { className: "ax-menu__label", children: it.label }, i);
62
+ return /* @__PURE__ */ jsxs(
63
+ "button",
64
+ {
65
+ role: "menuitem",
66
+ disabled: it.disabled,
67
+ className: "ax-menu__item" + (it.danger ? " ax-menu__item--danger" : ""),
68
+ onClick: () => {
69
+ setOpen(false);
70
+ it.onSelect && it.onSelect();
71
+ },
72
+ children: [
73
+ it.icon,
74
+ /* @__PURE__ */ jsx("span", { children: it.label }),
75
+ it.shortcut ? /* @__PURE__ */ jsx("span", { className: "ax-menu__shortcut", children: it.shortcut }) : null
76
+ ]
77
+ },
78
+ i
79
+ );
80
+ }) }) : null
81
+ ] });
82
+ }
83
+ export {
84
+ DropdownMenu
85
+ };
86
+ //# sourceMappingURL=DropdownMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropdownMenu.js","sources":["../../../src/components/overlay/DropdownMenu.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\n\nconst AX_MENU_CSS = `\n.ax-menu { position: relative; display: inline-flex; }\n.ax-menu__panel {\n position: absolute; z-index: 60; min-width: 200px; top: calc(100% + 6px);\n background: var(--surface-panel); border: 1px solid var(--border-strong);\n border-radius: var(--radius-3); box-shadow: var(--shadow-2); padding: var(--space-1);\n animation: ax-menu-in var(--dur-2) var(--ease-out);\n}\n.ax-menu__panel--end { right: 0; }\n.ax-menu__panel--start { left: 0; }\n.ax-menu__item {\n display: flex; align-items: center; gap: 10px; width: 100%;\n appearance: none; background: none; border: none; text-align: left; cursor: pointer;\n padding: 7px 10px; border-radius: var(--radius-2); color: var(--text-body);\n font-family: var(--font-body); font-size: var(--text-sm);\n transition: background var(--dur-1) var(--ease-out);\n}\n.ax-menu__item:hover { background: var(--surface-raised); }\n.ax-menu__item:focus-visible { outline: none; background: var(--surface-raised); }\n.ax-menu__item--danger { color: var(--danger); }\n.ax-menu__item:disabled { opacity: 0.4; cursor: not-allowed; }\n.ax-menu__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }\n.ax-menu__item--danger svg { color: var(--danger); }\n.ax-menu__shortcut { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); letter-spacing: 0.04em; }\n.ax-menu__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }\n.ax-menu__sep { height: 1px; background: var(--border-default); margin: var(--space-1) 0; }\n@keyframes ax-menu-in { from { opacity: 0; transform: translateY(-4px); } }\n@media (prefers-reduced-motion: reduce) { .ax-menu__panel { animation: none; } }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-menu-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-menu-css\";\n s.textContent = AX_MENU_CSS;\n document.head.appendChild(s);\n}\n\nexport function DropdownMenu({ trigger, items = [], align = \"start\", className = \"\", ...rest }) {\n const [open, setOpen] = useState(false);\n const ref = useRef(null);\n\n const onDoc = useCallback((e) => {\n if (ref.current && !ref.current.contains(e.target)) setOpen(false);\n }, []);\n\n useEffect(() => {\n if (open) {\n document.addEventListener(\"mousedown\", onDoc);\n const onKey = (e) => { if (e.key === \"Escape\") setOpen(false); };\n document.addEventListener(\"keydown\", onKey);\n return () => { document.removeEventListener(\"mousedown\", onDoc); document.removeEventListener(\"keydown\", onKey); };\n }\n }, [open, onDoc]);\n\n return (\n <span className={[\"ax-menu\", className].filter(Boolean).join(\" \")} ref={ref} {...rest}>\n <span onClick={() => setOpen((o) => !o)}>{trigger}</span>\n {open ? (\n <div className={\"ax-menu__panel ax-menu__panel--\" + align} role=\"menu\">\n {items.map((it, i) => {\n if (it.type === \"separator\") return <div key={i} className=\"ax-menu__sep\"></div>;\n if (it.type === \"label\") return <div key={i} className=\"ax-menu__label\">{it.label}</div>;\n return (\n <button\n key={i}\n role=\"menuitem\"\n disabled={it.disabled}\n className={\"ax-menu__item\" + (it.danger ? \" ax-menu__item--danger\" : \"\")}\n onClick={() => { setOpen(false); it.onSelect && it.onSelect(); }}\n >\n {it.icon}\n <span>{it.label}</span>\n {it.shortcut ? <span className=\"ax-menu__shortcut\">{it.shortcut}</span> : null}\n </button>\n );\n })}\n </div>\n ) : null}\n </span>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BpB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,aAAa,GAAG;AAC9E,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,aAAa,EAAE,SAAS,QAAQ,IAAI,QAAQ,SAAS,YAAY,IAAI,GAAG,QAAQ;AAC9F,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,MAAM,OAAO,IAAI;AAEvB,QAAM,QAAQ,YAAY,CAAC,MAAM;AAC/B,QAAI,IAAI,WAAW,CAAC,IAAI,QAAQ,SAAS,EAAE,MAAM,EAAG,SAAQ,KAAK;AAAA,EACnE,GAAG,CAAA,CAAE;AAEL,YAAU,MAAM;AACd,QAAI,MAAM;AACR,eAAS,iBAAiB,aAAa,KAAK;AAC5C,YAAM,QAAQ,CAAC,MAAM;AAAE,YAAI,EAAE,QAAQ,SAAU,SAAQ,KAAK;AAAA,MAAG;AAC/D,eAAS,iBAAiB,WAAW,KAAK;AAC1C,aAAO,MAAM;AAAE,iBAAS,oBAAoB,aAAa,KAAK;AAAG,iBAAS,oBAAoB,WAAW,KAAK;AAAA,MAAG;AAAA,IACnH;AAAA,EACF,GAAG,CAAC,MAAM,KAAK,CAAC;AAEhB,SACE,qBAAC,QAAA,EAAK,WAAW,CAAC,WAAW,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAG,KAAW,GAAG,MAC/E,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,SAAS,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAI,UAAA,QAAA,CAAQ;AAAA,IACjD,OACC,oBAAC,OAAA,EAAI,WAAW,oCAAoC,OAAO,MAAK,QAC7D,UAAA,MAAM,IAAI,CAAC,IAAI,MAAM;AACpB,UAAI,GAAG,SAAS,YAAa,4BAAQ,OAAA,EAAY,WAAU,kBAAb,CAA4B;AAC1E,UAAI,GAAG,SAAS,QAAS,QAAO,oBAAC,SAAY,WAAU,kBAAkB,UAAA,GAAG,MAAA,GAAlC,CAAwC;AAClF,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,UAAU,GAAG;AAAA,UACb,WAAW,mBAAmB,GAAG,SAAS,2BAA2B;AAAA,UACrE,SAAS,MAAM;AAAE,oBAAQ,KAAK;AAAG,eAAG,YAAY,GAAG,SAAA;AAAA,UAAY;AAAA,UAE9D,UAAA;AAAA,YAAA,GAAG;AAAA,YACJ,oBAAC,QAAA,EAAM,UAAA,GAAG,MAAA,CAAM;AAAA,YACf,GAAG,WAAW,oBAAC,QAAA,EAAK,WAAU,qBAAqB,UAAA,GAAG,UAAS,IAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QARrE;AAAA,MAAA;AAAA,IAWX,CAAC,GACH,IACE;AAAA,EAAA,GACN;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Rich hover preview card (open/close delays). For non-essential supplementary info. */
2
+ export interface HoverCardProps { trigger: React.ReactNode; side?: "top" | "bottom"; openDelay?: number; closeDelay?: number; children?: React.ReactNode; }
3
+ export declare function HoverCard(props: HoverCardProps): JSX.Element;
@@ -0,0 +1,53 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ const AX_HOVERCARD_CSS = `
4
+ .ax-hovercard { position: relative; display: inline-flex; }
5
+ .ax-hovercard__trigger { border-bottom: 1px dashed var(--border-strong); cursor: help; }
6
+ .ax-hovercard__panel {
7
+ position: absolute; z-index: 60; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
8
+ width: 280px; padding: var(--space-4); pointer-events: none;
9
+ background: var(--surface-panel); border: 1px solid var(--border-strong);
10
+ border-radius: var(--radius-3); box-shadow: var(--shadow-2);
11
+ opacity: 0; transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
12
+ }
13
+ .ax-hovercard__panel--bottom { bottom: auto; top: calc(100% + 8px); }
14
+ .ax-hovercard--open .ax-hovercard__panel { opacity: 1; pointer-events: auto; }
15
+ `;
16
+ if (typeof document !== "undefined" && !document.getElementById("ax-hovercard-css")) {
17
+ const s = document.createElement("style");
18
+ s.id = "ax-hovercard-css";
19
+ s.textContent = AX_HOVERCARD_CSS;
20
+ document.head.appendChild(s);
21
+ }
22
+ function HoverCard({ trigger, children, side = "top", openDelay = 200, closeDelay = 120, className = "", ...rest }) {
23
+ const [open, setOpen] = useState(false);
24
+ const timer = useRef(null);
25
+ const enter = () => {
26
+ clearTimeout(timer.current);
27
+ timer.current = setTimeout(() => setOpen(true), openDelay);
28
+ };
29
+ const leave = () => {
30
+ clearTimeout(timer.current);
31
+ timer.current = setTimeout(() => setOpen(false), closeDelay);
32
+ };
33
+ useEffect(() => () => clearTimeout(timer.current), []);
34
+ return /* @__PURE__ */ jsxs(
35
+ "span",
36
+ {
37
+ className: ["ax-hovercard", open ? "ax-hovercard--open" : "", className].filter(Boolean).join(" "),
38
+ onMouseEnter: enter,
39
+ onMouseLeave: leave,
40
+ onFocus: enter,
41
+ onBlur: leave,
42
+ ...rest,
43
+ children: [
44
+ /* @__PURE__ */ jsx("span", { className: "ax-hovercard__trigger", children: trigger }),
45
+ /* @__PURE__ */ jsx("span", { className: "ax-hovercard__panel" + (side === "bottom" ? " ax-hovercard__panel--bottom" : ""), children })
46
+ ]
47
+ }
48
+ );
49
+ }
50
+ export {
51
+ HoverCard
52
+ };
53
+ //# sourceMappingURL=HoverCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoverCard.js","sources":["../../../src/components/overlay/HoverCard.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\n\nconst AX_HOVERCARD_CSS = `\n.ax-hovercard { position: relative; display: inline-flex; }\n.ax-hovercard__trigger { border-bottom: 1px dashed var(--border-strong); cursor: help; }\n.ax-hovercard__panel {\n position: absolute; z-index: 60; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);\n width: 280px; padding: var(--space-4); pointer-events: none;\n background: var(--surface-panel); border: 1px solid var(--border-strong);\n border-radius: var(--radius-3); box-shadow: var(--shadow-2);\n opacity: 0; transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);\n}\n.ax-hovercard__panel--bottom { bottom: auto; top: calc(100% + 8px); }\n.ax-hovercard--open .ax-hovercard__panel { opacity: 1; pointer-events: auto; }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-hovercard-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-hovercard-css\";\n s.textContent = AX_HOVERCARD_CSS;\n document.head.appendChild(s);\n}\n\nexport function HoverCard({ trigger, children, side = \"top\", openDelay = 200, closeDelay = 120, className = \"\", ...rest }) {\n const [open, setOpen] = useState(false);\n const timer = useRef(null);\n const enter = () => { clearTimeout(timer.current); timer.current = setTimeout(() => setOpen(true), openDelay); };\n const leave = () => { clearTimeout(timer.current); timer.current = setTimeout(() => setOpen(false), closeDelay); };\n useEffect(() => () => clearTimeout(timer.current), []);\n return (\n <span\n className={[\"ax-hovercard\", open ? \"ax-hovercard--open\" : \"\", className].filter(Boolean).join(\" \")}\n onMouseEnter={enter} onMouseLeave={leave} onFocus={enter} onBlur={leave}\n {...rest}\n >\n <span className=\"ax-hovercard__trigger\">{trigger}</span>\n <span className={\"ax-hovercard__panel\" + (side === \"bottom\" ? \" ax-hovercard__panel--bottom\" : \"\")}>{children}</span>\n </span>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAczB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,kBAAkB,GAAG;AACnF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,UAAU,EAAE,SAAS,UAAU,OAAO,OAAO,YAAY,KAAK,aAAa,KAAK,YAAY,IAAI,GAAG,QAAQ;AACzH,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,QAAQ,OAAO,IAAI;AACzB,QAAM,QAAQ,MAAM;AAAE,iBAAa,MAAM,OAAO;AAAG,UAAM,UAAU,WAAW,MAAM,QAAQ,IAAI,GAAG,SAAS;AAAA,EAAG;AAC/G,QAAM,QAAQ,MAAM;AAAE,iBAAa,MAAM,OAAO;AAAG,UAAM,UAAU,WAAW,MAAM,QAAQ,KAAK,GAAG,UAAU;AAAA,EAAG;AACjH,YAAU,MAAM,MAAM,aAAa,MAAM,OAAO,GAAG,CAAA,CAAE;AACrD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,CAAC,gBAAgB,OAAO,uBAAuB,IAAI,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACjG,cAAc;AAAA,MAAO,cAAc;AAAA,MAAO,SAAS;AAAA,MAAO,QAAQ;AAAA,MACjE,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,yBAAyB,UAAA,SAAQ;AAAA,QACjD,oBAAC,UAAK,WAAW,yBAAyB,SAAS,WAAW,iCAAiC,KAAM,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGpH;"}
@@ -0,0 +1,4 @@
1
+ /** Desktop-style menubar; hover to move between open menus. */
2
+ export interface MenubarMenu { label: string; items: Array<{ label?: React.ReactNode; shortcut?: string; onSelect?: () => void; type?: "separator" }>; }
3
+ export interface MenubarProps { menus: MenubarMenu[]; }
4
+ export declare function Menubar(props: MenubarProps): JSX.Element;