@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
package/DESIGN.md ADDED
@@ -0,0 +1,112 @@
1
+ # Agentaily Design System
2
+
3
+ **Agentaily** is an AI chatbot. The brand brief, verbatim: **极客风格,简约,大气,科技感** — geek-flavored, minimal, expansive, technological. Agentaily answers in plain language first, then shows its work: conclusion → derivation, no hype, no mascots.
4
+
5
+ This is a **greenfield system** — no codebase, Figma, or existing assets were provided. Everything here (name, mark, palette, type, components, screens) was originated in this project on 2026-06-10 and is the source of truth. The only inputs were the one-line brief and these choices from the kickoff questionnaire: dual theme (dark default), **monochrome accent**, everything else delegated.
6
+
7
+ Two product surfaces are represented as full UI kits:
8
+ - **Chat app** (`ui_kits/chat/`) — the core product: sidebar + thread + composer.
9
+ - **Marketing website** (`ui_kits/website/`) — the landing page.
10
+ - **Documentation site** (`ui_kits/docs/`) — three-pane developer docs (nav + article + TOC).
11
+
12
+ The component library is **deliberately exhaustive** — 116 exports across 11 categories, covering the full shadcn/ui primitive set plus AI-native surfaces (reasoning, tool calls, agents, voice, workflow graphs). See the INDEX below.
13
+
14
+ ---
15
+
16
+ ## CONTENT FUNDAMENTALS
17
+
18
+ **Tone:** plain, precise, slightly dry. Confidence through restraint — Agentaily never sells, it states. The voice of a good senior engineer: short declaratives, concrete numbers, zero filler.
19
+
20
+ **Language:** bilingual by design. Display/English carries the tech identity ("Reasoning, distilled"), body copy is natural Chinese("先给结论,再给推导——不废话,不卖萌"). Mixing is intentional, but within one element pick one language.
21
+
22
+ **Casing:**
23
+ - Product copy and buttons: sentence case — "New chat", "Start free", "Read the docs".
24
+ - The label motif: mono ALL-CAPS with letter-spacing — `CONVERSATIONS`, `AGENTAILY MAY MAKE MISTAKES`.
25
+ - The wordmark is always lowercase: **agentaily**.
26
+
27
+ **Person:** address the user as 你/you; Agentaily refers to itself as Agentaily, never "I'm excited to…". System text is impersonal: "This cannot be undone."
28
+
29
+ **Emoji: never.** Status is carried by square dots and color tokens. Keyboard glyphs (⌘ ⌥ ⇧ ⏎) and geometric unicode (▣ ▍) are typed as text and ARE part of the vocabulary.
30
+
31
+ **Numbers are copy.** "0.4s", "128k", "Retry in 18s" — specific figures replace adjectives.
32
+
33
+ Examples — ✓ "Rate limited. Retry in 18s." ✗ "Oops! Something went wrong 😅" · ✓ "有什么要解决的?" ✗ "✨ 开启你的奇妙旅程!"
34
+
35
+ ---
36
+
37
+ ## VISUAL FOUNDATIONS
38
+
39
+ **Color.** Monochrome-first. Two scales: **ink** (dark, the default on `:root`) and **paper** (light, scoped under `[data-theme="light"]`). The accent is **inversion, not hue** — the primary button is white-on-black in dark, black-on-white in light. Semantic green/amber/red exist (`--ok/--warn/--danger`) but appear only as status; never decorative. There are no gradients anywhere except the dot-grid mask fade.
40
+
41
+ **Type.** Space Grotesk (display + UI) and JetBrains Mono (code, timestamps, labels). CJK falls back to system sans (PingFang SC / Microsoft YaHei). Display sizes use tight tracking (−0.02em) and medium weight — never bold-black. The mono ALL-CAPS label (12px, +0.08em) is the system's signature. Body is 15px/1.6, max ~76ch.
42
+
43
+ **Spacing.** 4px grid. Outer space is generous (sections 72–96px) — 大气; inner rhythm is tight (8–16px) — 极客. Chat thread column maxes at 760px; marketing container 1120px; sidebar fixed 272px.
44
+
45
+ **Backgrounds.** Flat solids from the scale. No photography, no illustration. The only textures permitted: the **dot grid** (24px, for heroes/empty states, usually mask-faded) and hairline rules. Marketing hero art is the product window itself.
46
+
47
+ **Corners.** Hard-edged: 2px chips, 4px buttons/inputs, 8px cards/dialogs. Full-round only for rare avatar cases; default avatars are **square** (4px).
48
+
49
+ **Borders & shadows.** Hierarchy comes from 1px hairlines (`--line-1` resting, `--line-2` hover/strong), not shadows. Shadows exist only for floating layers (menus `--shadow-2`, dialogs/marketing window `--shadow-3`). No inner shadows except the Kbd's 2px bottom border.
50
+
51
+ **Hover:** background fill (`--bg-3`) or border step-up (`--line-1`→`--line-2`) — never opacity fades on text. **Press:** translateY(1px) — mechanical, no scale. **Focus:** keyboard focus uses the double ring (`--ring`); inputs use border-color swap.
52
+
53
+ **Motion.** One ease (`cubic-bezier(0.2,0,0,1)`), three durations (120/200/320ms). Decisive and damped — no bounce, no parallax. Mechanical exceptions that define the brand: the cursor blinks in `steps(1)`, the spinner rotates in `steps(8)`. Respect `prefers-reduced-motion`.
54
+
55
+ **Transparency & blur:** only on overlay layers — dialog scrim (`--bg-overlay` + 12px blur) and the sticky marketing nav. Never on content.
56
+
57
+ **Cards:** flat `--bg-2`, 1px `--line-1`, 8px radius, no shadow. Featured cards may carry the **corner-tick** motif (two L-shaped ticks on opposite corners).
58
+
59
+ **Motifs (use 1, max 2 per view):** block cursor ▍ (liveness) · dot grid (potential space) · corner ticks (selection/precision) · mono ALL-CAPS labels.
60
+
61
+ **Chat anatomy:** user turns are right-aligned hairline cards (max 78%); assistant turns are full-width prose under a mono `AGENTAILY` label — no bubble. Streaming = blinking block cursor.
62
+
63
+ ---
64
+
65
+ ## ICONOGRAPHY
66
+
67
+ - **System: [Lucide](https://lucide.dev)** — 24px grid, stroke 2, round caps, `currentColor`, rendered at 14–20px. Chosen as the open-source set matching the hairline aesthetic. No brand icon font existed (greenfield); this substitution is flagged in CAVEATS.
68
+ - **In static HTML:** load the UMD build from CDN (`https://unpkg.com/lucide@latest/dist/umd/lucide.js`) and call `lucide.createIcons()` on `<i data-lucide="plus">` elements — see `guidelines/iconography.card.html`.
69
+ - **In React kits:** use `ChatIcon` from `ui_kits/chat/ChatIcons.jsx` — inline copies of Lucide path geometry (plus, search, settings, sun, moon, pen, trash, copy, refresh, chevron-down, x, paperclip, panel-left, arrow-up, message, share). Add icons by copying paths from Lucide, never by drawing freehand.
70
+ - **Never:** filled icons, duotone, emoji-as-icon, mixed stroke weights.
71
+ - **Unicode as UI:** ⌘ ⌥ ⇧ ⏎ in `Kbd`; ▣ as model-chip glyph; ✕ for dismiss; ✓ in copy-confirmation. These are text, set in mono.
72
+ - **Logo:** `assets/logo/agentaily-mark-{white,black}.svg` — cursor-block-in-corner-ticks mark. Wordmark is typed, not drawn: lowercase mono `agentaily` + optional blinking cursor.
73
+
74
+ ---
75
+
76
+ ## INDEX
77
+
78
+ | Path | What |
79
+ |---|---|
80
+ | `styles.css` | Global entry — `@import`s everything below. Link this one file. |
81
+ | `tokens/colors.css` | Ink + paper scales, accent, semantic, aliases |
82
+ | `tokens/typography.css` | Families, scale (12–68px), weights, tracking |
83
+ | `tokens/spacing.css` | 4px scale + layout constants |
84
+ | `tokens/effects.css` | Radii, shadows, motion, focus ring, blur |
85
+ | `tokens/base.css` | Body defaults + motif utilities (`.ax-label`, `.ax-cursor`, `.ax-dotgrid`, `.ax-ticks`) |
86
+ | `tokens/fonts.css` | Google Fonts imports (substitution — see CAVEATS) |
87
+ | `assets/logo/` | Mark SVGs (white/black) |
88
+ | `guidelines/` | 17 specimen cards (Colors ×4, Type ×4, Spacing ×5, Brand ×4) |
89
+ | `states/` | 5 interaction-state matrices (buttons, form controls, selection/nav, loading/streaming, status/feedback) — force-rendered hover/focus/active/disabled |
90
+ | `components/buttons/` | Button, IconButton, **ButtonGroup** |
91
+ | `components/inputs/` | Input, Textarea, Select, Switch, Checkbox, Label, RadioGroup, Slider, Toggle, ToggleGroup, **Field, FieldGroup, InputGroup, InputOTP, Combobox, Calendar, DatePicker** |
92
+ | `components/display/` | Card, Badge, Avatar, Tabs, Kbd, Separator, Skeleton, Progress, Accordion, Breadcrumb, Table, Pagination, Empty, **Collapsible, Item, Carousel, Chart (BarChart/LineChart), DataTable, Typography (Prose/Text)** |
93
+ | `components/feedback/` | Spinner, Toast, Tooltip, Dialog, Alert |
94
+ | `components/overlay/` | Popover, DropdownMenu, Command, Sheet, **HoverCard, ContextMenu, Menubar, NavigationMenu, AlertDialog** |
95
+ | `components/layout/` | **AspectRatio, ScrollArea, Resizable, Sidebar** |
96
+ | `components/chat/` | Message, Composer, CodeBlock |
97
+ | `components/ai/` | Reasoning, ToolCall, Sources + Citation, Suggestion/Suggestions, ModelSelector, Attachments, Shimmer, **Conversation, Task, Plan, Context, Confirmation, Checkpoint, Queue** |
98
+ | `components/code/` | **Terminal, FileTree, Snippet, StackTrace, TestResults, Artifact, WebPreview, Agent, Commit, EnvironmentVariables, PackageInfo, Sandbox, SchemaDisplay, JSXPreview** |
99
+ | `components/voice/` | **AudioPlayer, MicSelector, VoiceSelector, SpeechInput, Transcription, Persona** |
100
+ | `components/workflow/` | **Flow (Canvas), Canvas, Node, Edge, Connection, Controls, Panel, Toolbar** |
101
+ | `components/utilities/` | **Image, OpenInChat** |
102
+ | `ui_kits/chat/` | Chat app (interactive) |
103
+ | `ui_kits/website/` | Marketing landing page |
104
+ | `ui_kits/docs/` | Documentation site (interactive) |
105
+ | `SKILL.md` | Agent-skill entry point |
106
+
107
+ Every component ships `<Name>.jsx` + `<Name>.d.ts` (props) + `<Name>.prompt.md` (usage) — **116 component exports across 11 categories** (buttons, inputs, display, feedback, overlay, layout, chat, ai, code, voice, workflow, utilities). This is a deliberately exhaustive set covering shadcn/ui primitives + AI-native surfaces (reasoning, tools, agents, voice, workflow graphs). Consume via the compiled bundle: `window.AxiomDesignSystem_7fc962`. Read each component's `.prompt.md` for copy-paste usage.
108
+
109
+ ## CAVEATS
110
+ - **Fonts are CDN substitutions:** Space Grotesk + JetBrains Mono via Google Fonts `@import` (no binaries shipped). Replace `tokens/fonts.css` with real `@font-face` + files for offline/production use.
111
+ - **Icons are Lucide** (CDN / copied paths), not a bespoke set.
112
+ - All product copy, stats and names in the kits are invented placeholders.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # agentaily design system
2
+
3
+ Agentaily(AI chatbot)设计系统:116 个 React 组件 + Storybook,单色暗色优先。品牌一句话:**极客风格,简约,大气,科技感**。
4
+
5
+ 📖 **在线 Storybook:** https://agentaily.github.io/design-system/
6
+
7
+ 设计规范全文见 [DESIGN.md](./DESIGN.md)(来自 claude.ai/design 的 handoff);运维与发布操作见 [OPERATIONS.md](./OPERATIONS.md)。
8
+
9
+ ## 开发
10
+
11
+ ```bash
12
+ npm install
13
+ npm run storybook # 开发服务器 http://localhost:6006
14
+ npm run build-storybook # 静态构建到 storybook-static/
15
+ ```
16
+
17
+ ## 分发(三条渠道)
18
+
19
+ ### ① npm 组件库
20
+
21
+ 作为 React 组件库被其他项目消费。ESM-only,每个组件一个模块(`preserveModules`),消费方可 tree-shake 未用到的组件;`react` / `react-dom` 为 peer dependency。
22
+
23
+ ```bash
24
+ npm run build:lib # 产出 dist/:每组件一个 .js + index.d.ts + styles.css + assets/
25
+ ```
26
+
27
+ 产物结构:
28
+
29
+ | 路径 | 内容 |
30
+ | ----------------------------------------------- | ----------------------------------------- |
31
+ | `dist/index.js` | ESM 入口,re-export 全部 110 个组件符号 |
32
+ | `dist/components/**/*.js` | 每个组件独立模块(含运行时 CSS 注入) |
33
+ | `dist/index.d.ts` + `dist/components/**/*.d.ts` | TypeScript 类型契约 |
34
+ | `dist/styles.css` | 内联好的 tokens + 字体,消费方 import 一次 |
35
+ | `dist/assets/logo/*.svg` | 品牌 mark |
36
+
37
+ 消费方用法:
38
+
39
+ ```jsx
40
+ import "@agentaily/design-system/styles.css"; // 一次,加载 tokens
41
+ import { Button, Composer, Reasoning } from "@agentaily/design-system";
42
+ ```
43
+
44
+ **版本与发布走 [Changesets](https://github.com/changesets/changesets)**:
45
+
46
+ - 改动值得发版时,跑 `npm run changeset` 选 patch/minor/major 并写一行摘要,把生成的 `.changeset/*.md` 跟代码一起提交。
47
+ - `.github/workflows/release.yml` 在 push 到 `main` 时,要么开一个「Version Packages」PR(消费 changeset、bump 版本、写 `CHANGELOG.md`),要么在该 PR 合并后**发布到 npm**(OIDC trusted publishing + provenance,仓库零 token)并创建 GitHub Release。
48
+ - **首发为引导步骤**:scoped 包要先存在才能配可信发布者,所以 v0.1.0 先本地手动 `npm publish` 一次;之后到 npmjs.com 给该包加 Trusted Publisher(org `agentaily` / repo `design-system` / workflow `release.yml`),后续全自动。
49
+
50
+ 注:`package.json` 的 `license` 暂为 `UNLICENSED`,公开发布前请确认授权条款。
51
+
52
+ ### ② 托管 Storybook(活文档)
53
+
54
+ `.github/workflows/storybook.yml` 在推送到 `main` 时自动 `build-storybook` 并部署到 GitHub Pages —— 已上线:**https://agentaily.github.io/design-system/**。
55
+
56
+ ### ③ Agent Skill
57
+
58
+ 仓库根目录的 `SKILL.md` 让整个目录可作为 Claude Code / Agent Skill 分发,供 AI 按 Agentaily 品牌产出设计稿或生产代码。
59
+
60
+ ## 结构
61
+
62
+ ```
63
+ .storybook/ Storybook 配置(深色默认 + 工具栏 ink/paper 双主题切换)
64
+ src/styles.css 全局入口,@import 所有 token
65
+ src/tokens/ 颜色 / 字体 / 间距 / 效果 / 基础母题 CSS 变量
66
+ src/assets/logo/ 品牌 mark SVG(白/黑)
67
+ src/foundations/ Foundations stories(Intro / Colors / Typography / Spacing / Effects / Motifs)
68
+ src/components/ 11 个类别的组件源码 + stories
69
+ <cat>/<Name>.jsx 组件(自包含,注入自身 CSS,只消费 token 变量)
70
+ <cat>/<Name>.d.ts props 契约
71
+ <cat>/<Name>.prompt.md 用法说明
72
+ <cat>/<Name>.stories.jsx
73
+ ```
74
+
75
+ ## 约定
76
+
77
+ - 暗色 ink 是默认主题(`:root`);亮色 paper 走 `[data-theme="light"]`,用 Storybook 工具栏切换。
78
+ - 单色反相 accent,无渐变;语义色(--ok/--warn/--danger)只作状态。
79
+ - 圆角 2/4/8px;层级靠 1px hairline 边框;阴影只给浮层。
80
+ - 文案:平实精确,无 emoji,具体数字即文案("0.4s"、"128k")。
81
+ - 字体经 Google Fonts CDN 引入(Space Grotesk + JetBrains Mono),生产环境请替换 `src/tokens/fonts.css` 为自托管 @font-face。
@@ -0,0 +1,5 @@
1
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2 10 V2 H10" stroke="#111113" stroke-width="2"></path>
3
+ <path d="M22 30 H30 V22" stroke="#111113" stroke-width="2"></path>
4
+ <rect x="12" y="9" width="8" height="14" fill="#111113"></rect>
5
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2 10 V2 H10" stroke="#F4F4F5" stroke-width="2"></path>
3
+ <path d="M22 30 H30 V22" stroke="#F4F4F5" stroke-width="2"></path>
4
+ <rect x="12" y="9" width="8" height="14" fill="#F4F4F5"></rect>
5
+ </svg>
@@ -0,0 +1,23 @@
1
+ /**
2
+ * File attachment display in three layouts: grid thumbnails, inline badges, list rows.
3
+ */
4
+ export interface AttachmentFile {
5
+ id?: string | number;
6
+ name: string;
7
+ /** MIME type — drives the auto icon + list metadata. */
8
+ type?: string;
9
+ /** Human size, e.g. "2.4 MB" (list variant). */
10
+ size?: string;
11
+ /** Image src for grid thumbnails. */
12
+ src?: string;
13
+ /** Override auto media category. */
14
+ category?: "image" | "video" | "audio" | "document";
15
+ }
16
+ export interface AttachmentsProps {
17
+ files: AttachmentFile[];
18
+ /** @default "list" */
19
+ variant?: "grid" | "inline" | "list";
20
+ /** Renders a ✕ per item when provided; receives the file id (or index). */
21
+ onRemove?: (id: string | number) => void;
22
+ }
23
+ export declare function Attachments(props: AttachmentsProps): JSX.Element;
@@ -0,0 +1,96 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "react";
3
+ const AX_ATTACH_CSS = `
4
+ .ax-attachments { display: flex; gap: 8px; }
5
+ .ax-attachments--grid { flex-wrap: wrap; }
6
+ .ax-attachments--inline { flex-wrap: wrap; }
7
+ .ax-attachments--list { flex-direction: column; }
8
+
9
+ .ax-attach {
10
+ position: relative; display: flex; align-items: center; gap: 8px;
11
+ border: 1px solid var(--border-default); border-radius: var(--radius-2);
12
+ background: var(--surface-card); transition: border-color var(--dur-1) var(--ease-out);
13
+ }
14
+ .ax-attach:hover { border-color: var(--border-strong); }
15
+
16
+ /* grid: thumbnail tile */
17
+ .ax-attachments--grid .ax-attach { width: 96px; height: 96px; padding: 0; overflow: hidden; flex-direction: column; gap: 0; }
18
+ .ax-attachments--grid .ax-attach__thumb { width: 100%; flex: 1; display: flex; align-items: center; justify-content: center; color: var(--text-faint); background: var(--surface-raised); }
19
+ .ax-attachments--grid .ax-attach__thumb img { width: 100%; height: 100%; object-fit: cover; }
20
+ .ax-attachments--grid .ax-attach__name { font-size: 10px; padding: 4px 6px; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-muted); border-top: 1px solid var(--border-default); }
21
+
22
+ /* inline: compact badge */
23
+ .ax-attachments--inline .ax-attach { padding: 4px 8px 4px 8px; border-radius: var(--radius-1); }
24
+ .ax-attachments--inline .ax-attach__name { font-size: var(--text-xs); }
25
+
26
+ /* list: full row */
27
+ .ax-attachments--list .ax-attach { padding: 10px 12px; }
28
+ .ax-attachments--list .ax-attach__body { flex: 1; min-width: 0; }
29
+ .ax-attachments--list .ax-attach__meta { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); margin-top: 1px; }
30
+
31
+ .ax-attach__icon { flex: none; color: var(--text-faint); display: inline-flex; }
32
+ .ax-attach__icon svg { width: 15px; height: 15px; }
33
+ .ax-attach__name { color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); }
34
+ .ax-attach__remove {
35
+ appearance: none; background: none; border: none; cursor: pointer; flex: none;
36
+ color: var(--text-faint); font-family: var(--font-mono); font-size: 11px; line-height: 1;
37
+ padding: 3px; border-radius: var(--radius-1);
38
+ }
39
+ .ax-attach__remove:hover { color: var(--danger); background: var(--danger-dim); }
40
+ .ax-attachments--grid .ax-attach__remove { position: absolute; top: 4px; right: 4px; background: var(--bg-overlay); }
41
+ `;
42
+ if (typeof document !== "undefined" && !document.getElementById("ax-attach-css")) {
43
+ const s = document.createElement("style");
44
+ s.id = "ax-attach-css";
45
+ s.textContent = AX_ATTACH_CSS;
46
+ document.head.appendChild(s);
47
+ }
48
+ const ICONS = {
49
+ image: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
50
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
51
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
52
+ /* @__PURE__ */ jsx("path", { d: "m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21" })
53
+ ] }),
54
+ video: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
55
+ /* @__PURE__ */ jsx("path", { d: "m22 8-6 4 6 4V8Z" }),
56
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" })
57
+ ] }),
58
+ audio: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
59
+ /* @__PURE__ */ jsx("path", { d: "M9 18V5l12-2v13" }),
60
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "18", r: "3" }),
61
+ /* @__PURE__ */ jsx("circle", { cx: "18", cy: "16", r: "3" })
62
+ ] }),
63
+ document: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
64
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
65
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" })
66
+ ] })
67
+ };
68
+ function category(file) {
69
+ if (file.category) return file.category;
70
+ const t = file.type || "";
71
+ if (t.startsWith("image")) return "image";
72
+ if (t.startsWith("video")) return "video";
73
+ if (t.startsWith("audio")) return "audio";
74
+ return "document";
75
+ }
76
+ function Attachments({ files = [], variant = "list", onRemove, className = "", ...rest }) {
77
+ return /* @__PURE__ */ jsx("div", { className: ["ax-attachments", "ax-attachments--" + variant, className].filter(Boolean).join(" "), ...rest, children: files.map((file, i) => {
78
+ const cat = category(file);
79
+ const icon = ICONS[cat] || ICONS.document;
80
+ return /* @__PURE__ */ jsxs("div", { className: "ax-attach", children: [
81
+ variant === "grid" ? /* @__PURE__ */ jsx("span", { className: "ax-attach__thumb", children: file.src ? /* @__PURE__ */ jsx("img", { src: file.src, alt: file.name }) : /* @__PURE__ */ jsx("span", { className: "ax-attach__icon", children: icon }) }) : /* @__PURE__ */ jsx("span", { className: "ax-attach__icon", children: icon }),
82
+ variant === "list" ? /* @__PURE__ */ jsxs("span", { className: "ax-attach__body", children: [
83
+ /* @__PURE__ */ jsx("span", { className: "ax-attach__name", children: file.name }),
84
+ file.type ? /* @__PURE__ */ jsxs("span", { className: "ax-attach__meta", children: [
85
+ file.type,
86
+ file.size ? " · " + file.size : ""
87
+ ] }) : null
88
+ ] }) : /* @__PURE__ */ jsx("span", { className: "ax-attach__name", children: file.name }),
89
+ onRemove ? /* @__PURE__ */ jsx("button", { className: "ax-attach__remove", "aria-label": "Remove " + file.name, onClick: () => onRemove(file.id ?? i), children: "✕" }) : null
90
+ ] }, file.id || i);
91
+ }) });
92
+ }
93
+ export {
94
+ Attachments
95
+ };
96
+ //# sourceMappingURL=Attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Attachments.js","sources":["../../../src/components/ai/Attachments.jsx"],"sourcesContent":["import React from \"react\";\n\nconst AX_ATTACH_CSS = `\n.ax-attachments { display: flex; gap: 8px; }\n.ax-attachments--grid { flex-wrap: wrap; }\n.ax-attachments--inline { flex-wrap: wrap; }\n.ax-attachments--list { flex-direction: column; }\n\n.ax-attach {\n position: relative; display: flex; align-items: center; gap: 8px;\n border: 1px solid var(--border-default); border-radius: var(--radius-2);\n background: var(--surface-card); transition: border-color var(--dur-1) var(--ease-out);\n}\n.ax-attach:hover { border-color: var(--border-strong); }\n\n/* grid: thumbnail tile */\n.ax-attachments--grid .ax-attach { width: 96px; height: 96px; padding: 0; overflow: hidden; flex-direction: column; gap: 0; }\n.ax-attachments--grid .ax-attach__thumb { width: 100%; flex: 1; display: flex; align-items: center; justify-content: center; color: var(--text-faint); background: var(--surface-raised); }\n.ax-attachments--grid .ax-attach__thumb img { width: 100%; height: 100%; object-fit: cover; }\n.ax-attachments--grid .ax-attach__name { font-size: 10px; padding: 4px 6px; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-muted); border-top: 1px solid var(--border-default); }\n\n/* inline: compact badge */\n.ax-attachments--inline .ax-attach { padding: 4px 8px 4px 8px; border-radius: var(--radius-1); }\n.ax-attachments--inline .ax-attach__name { font-size: var(--text-xs); }\n\n/* list: full row */\n.ax-attachments--list .ax-attach { padding: 10px 12px; }\n.ax-attachments--list .ax-attach__body { flex: 1; min-width: 0; }\n.ax-attachments--list .ax-attach__meta { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); margin-top: 1px; }\n\n.ax-attach__icon { flex: none; color: var(--text-faint); display: inline-flex; }\n.ax-attach__icon svg { width: 15px; height: 15px; }\n.ax-attach__name { color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); }\n.ax-attach__remove {\n appearance: none; background: none; border: none; cursor: pointer; flex: none;\n color: var(--text-faint); font-family: var(--font-mono); font-size: 11px; line-height: 1;\n padding: 3px; border-radius: var(--radius-1);\n}\n.ax-attach__remove:hover { color: var(--danger); background: var(--danger-dim); }\n.ax-attachments--grid .ax-attach__remove { position: absolute; top: 4px; right: 4px; background: var(--bg-overlay); }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-attach-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-attach-css\";\n s.textContent = AX_ATTACH_CSS;\n document.head.appendChild(s);\n}\n\nconst ICONS = {\n image: <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"></rect><circle cx=\"9\" cy=\"9\" r=\"2\"></circle><path d=\"m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21\"></path></svg>,\n video: <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"m22 8-6 4 6 4V8Z\"></path><rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\"></rect></svg>,\n audio: <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M9 18V5l12-2v13\"></path><circle cx=\"6\" cy=\"18\" r=\"3\"></circle><circle cx=\"18\" cy=\"16\" r=\"3\"></circle></svg>,\n document: <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z\"></path><path d=\"M14 2v6h6\"></path></svg>,\n};\n\nfunction category(file) {\n if (file.category) return file.category;\n const t = file.type || \"\";\n if (t.startsWith(\"image\")) return \"image\";\n if (t.startsWith(\"video\")) return \"video\";\n if (t.startsWith(\"audio\")) return \"audio\";\n return \"document\";\n}\n\nexport function Attachments({ files = [], variant = \"list\", onRemove, className = \"\", ...rest }) {\n return (\n <div className={[\"ax-attachments\", \"ax-attachments--\" + variant, className].filter(Boolean).join(\" \")} {...rest}>\n {files.map((file, i) => {\n const cat = category(file);\n const icon = ICONS[cat] || ICONS.document;\n return (\n <div className=\"ax-attach\" key={file.id || i}>\n {variant === \"grid\" ? (\n <span className=\"ax-attach__thumb\">{file.src ? <img src={file.src} alt={file.name} /> : <span className=\"ax-attach__icon\">{icon}</span>}</span>\n ) : (\n <span className=\"ax-attach__icon\">{icon}</span>\n )}\n {variant === \"list\" ? (\n <span className=\"ax-attach__body\">\n <span className=\"ax-attach__name\">{file.name}</span>\n {file.type ? <span className=\"ax-attach__meta\">{file.type}{file.size ? \" · \" + file.size : \"\"}</span> : null}\n </span>\n ) : (\n <span className=\"ax-attach__name\">{file.name}</span>\n )}\n {onRemove ? <button className=\"ax-attach__remove\" aria-label={\"Remove \" + file.name} onClick={() => onRemove(file.id ?? i)}>✕</button> : null}\n </div>\n );\n })}\n </div>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,gBAAgB;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAwCtB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,eAAe,GAAG;AAChF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEA,MAAM,QAAQ;AAAA,EACZ,OAAO,qBAAC,OAAA,EAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,wBAAQ,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI;AAAA,IAAS,oBAAC,QAAA,EAAK,GAAE,sCAAA,CAAsC;AAAA,EAAA,GAAO;AAAA,EAChR,OAAO,qBAAC,OAAA,EAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,mBAAA,CAAmB;AAAA,IAAO,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EAAA,GAAO;AAAA,EACxN,OAAO,qBAAC,OAAA,EAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,kBAAA,CAAkB;AAAA,wBAAQ,UAAA,EAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI;AAAA,wBAAU,UAAA,EAAO,IAAG,MAAK,IAAG,MAAK,GAAE,IAAA,CAAI;AAAA,EAAA,GAAS;AAAA,EAC7O,UAAU,qBAAC,OAAA,EAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,6DAAA,CAA6D;AAAA,IAAO,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EAAA,EAAA,CAAO;AAC3O;AAEA,SAAS,SAAS,MAAM;AACtB,MAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,QAAM,IAAI,KAAK,QAAQ;AACvB,MAAI,EAAE,WAAW,OAAO,EAAG,QAAO;AAClC,MAAI,EAAE,WAAW,OAAO,EAAG,QAAO;AAClC,MAAI,EAAE,WAAW,OAAO,EAAG,QAAO;AAClC,SAAO;AACT;AAEO,SAAS,YAAY,EAAE,QAAQ,CAAA,GAAI,UAAU,QAAQ,UAAU,YAAY,IAAI,GAAG,QAAQ;AAC/F,SACE,oBAAC,SAAI,WAAW,CAAC,kBAAkB,qBAAqB,SAAS,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,MACxG,UAAA,MAAM,IAAI,CAAC,MAAM,MAAM;AACtB,UAAM,MAAM,SAAS,IAAI;AACzB,UAAM,OAAO,MAAM,GAAG,KAAK,MAAM;AACjC,WACE,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,MAAA,YAAY,SACX,oBAAC,QAAA,EAAK,WAAU,oBAAoB,UAAA,KAAK,MAAM,oBAAC,OAAA,EAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAA,CAAM,IAAK,oBAAC,QAAA,EAAK,WAAU,mBAAmB,UAAA,KAAA,CAAK,EAAA,CAAQ,IAExI,oBAAC,QAAA,EAAK,WAAU,mBAAmB,UAAA,MAAK;AAAA,MAEzC,YAAY,SACX,qBAAC,QAAA,EAAK,WAAU,mBACd,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,mBAAmB,UAAA,KAAK,MAAK;AAAA,QAC5C,KAAK,OAAO,qBAAC,QAAA,EAAK,WAAU,mBAAmB,UAAA;AAAA,UAAA,KAAK;AAAA,UAAM,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,QAAA,EAAA,CAAG,IAAU;AAAA,MAAA,GAC1G,IAEA,oBAAC,QAAA,EAAK,WAAU,mBAAmB,eAAK,MAAK;AAAA,MAE9C,WAAW,oBAAC,UAAA,EAAO,WAAU,qBAAoB,cAAY,YAAY,KAAK,MAAM,SAAS,MAAM,SAAS,KAAK,MAAM,CAAC,GAAG,eAAC,IAAY;AAAA,IAAA,KAd3G,KAAK,MAAM,CAe3C;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Inline conversation checkpoint divider with optional restore action. */
2
+ export interface CheckpointProps { label?: string; time?: string; onRestore?: () => void; }
3
+ export declare function Checkpoint(props: CheckpointProps): JSX.Element;
@@ -0,0 +1,38 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ const AX_CHECKPOINT_CSS = `
4
+ .ax-checkpoint { display: flex; align-items: center; gap: 12px; padding: 6px 0; }
5
+ .ax-checkpoint__line { flex: 1; height: 1px; background: var(--border-default); }
6
+ .ax-checkpoint__chip { display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px; border: 1px solid var(--border-default); border-radius: var(--radius-full); background: var(--surface-card); white-space: nowrap; }
7
+ .ax-checkpoint__icon { width: 13px; height: 13px; color: var(--text-faint); }
8
+ .ax-checkpoint__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-muted); }
9
+ .ax-checkpoint__time { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }
10
+ .ax-checkpoint__restore { appearance: none; background: none; border: none; cursor: pointer; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); padding: 0; transition: color var(--dur-1) var(--ease-out); }
11
+ .ax-checkpoint__restore:hover { color: var(--text-body); }
12
+ `;
13
+ if (typeof document !== "undefined" && !document.getElementById("ax-checkpoint-css")) {
14
+ const s = document.createElement("style");
15
+ s.id = "ax-checkpoint-css";
16
+ s.textContent = AX_CHECKPOINT_CSS;
17
+ document.head.appendChild(s);
18
+ }
19
+ const Flag = /* @__PURE__ */ jsxs("svg", { className: "ax-checkpoint__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
20
+ /* @__PURE__ */ jsx("path", { d: "M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" }),
21
+ /* @__PURE__ */ jsx("path", { d: "M4 22v-7" })
22
+ ] });
23
+ function Checkpoint({ label = "Checkpoint", time, onRestore, className = "", ...rest }) {
24
+ return /* @__PURE__ */ jsxs("div", { className: ["ax-checkpoint", className].filter(Boolean).join(" "), ...rest, children: [
25
+ /* @__PURE__ */ jsx("span", { className: "ax-checkpoint__line" }),
26
+ /* @__PURE__ */ jsxs("span", { className: "ax-checkpoint__chip", children: [
27
+ Flag,
28
+ /* @__PURE__ */ jsx("span", { className: "ax-checkpoint__label", children: label }),
29
+ time ? /* @__PURE__ */ jsx("span", { className: "ax-checkpoint__time", children: time }) : null,
30
+ onRestore ? /* @__PURE__ */ jsx("button", { className: "ax-checkpoint__restore", onClick: onRestore, children: "↺ Restore" }) : null
31
+ ] }),
32
+ /* @__PURE__ */ jsx("span", { className: "ax-checkpoint__line" })
33
+ ] });
34
+ }
35
+ export {
36
+ Checkpoint
37
+ };
38
+ //# sourceMappingURL=Checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Checkpoint.js","sources":["../../../src/components/ai/Checkpoint.jsx"],"sourcesContent":["import React from \"react\";\n\nconst AX_CHECKPOINT_CSS = `\n.ax-checkpoint { display: flex; align-items: center; gap: 12px; padding: 6px 0; }\n.ax-checkpoint__line { flex: 1; height: 1px; background: var(--border-default); }\n.ax-checkpoint__chip { display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px; border: 1px solid var(--border-default); border-radius: var(--radius-full); background: var(--surface-card); white-space: nowrap; }\n.ax-checkpoint__icon { width: 13px; height: 13px; color: var(--text-faint); }\n.ax-checkpoint__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-muted); }\n.ax-checkpoint__time { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }\n.ax-checkpoint__restore { appearance: none; background: none; border: none; cursor: pointer; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); padding: 0; transition: color var(--dur-1) var(--ease-out); }\n.ax-checkpoint__restore:hover { color: var(--text-body); }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-checkpoint-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-checkpoint-css\";\n s.textContent = AX_CHECKPOINT_CSS;\n document.head.appendChild(s);\n}\n\nconst Flag = <svg className=\"ax-checkpoint__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\"></path><path d=\"M4 22v-7\"></path></svg>;\n\nexport function Checkpoint({ label = \"Checkpoint\", time, onRestore, className = \"\", ...rest }) {\n return (\n <div className={[\"ax-checkpoint\", className].filter(Boolean).join(\" \")} {...rest}>\n <span className=\"ax-checkpoint__line\"></span>\n <span className=\"ax-checkpoint__chip\">\n {Flag}\n <span className=\"ax-checkpoint__label\">{label}</span>\n {time ? <span className=\"ax-checkpoint__time\">{time}</span> : null}\n {onRestore ? <button className=\"ax-checkpoint__restore\" onClick={onRestore}>↺ Restore</button> : null}\n </span>\n <span className=\"ax-checkpoint__line\"></span>\n </div>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAW1B,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,mBAAmB,GAAG;AACpF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEA,MAAM,OAAO,qBAAC,OAAA,EAAI,WAAU,uBAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,4DAAA,CAA4D;AAAA,EAAO,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,GAAO;AAEnQ,SAAS,WAAW,EAAE,QAAQ,cAAc,MAAM,WAAW,YAAY,IAAI,GAAG,QAAQ;AAC7F,SACE,qBAAC,OAAA,EAAI,WAAW,CAAC,iBAAiB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,MAC1E,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,WAAU,sBAAA,CAAsB;AAAA,IACtC,qBAAC,QAAA,EAAK,WAAU,uBACb,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAA,EAAK,WAAU,wBAAwB,UAAA,OAAM;AAAA,MAC7C,OAAO,oBAAC,QAAA,EAAK,WAAU,uBAAuB,gBAAK,IAAU;AAAA,MAC7D,gCAAa,UAAA,EAAO,WAAU,0BAAyB,SAAS,WAAW,uBAAS,IAAY;AAAA,IAAA,GACnG;AAAA,IACA,oBAAC,QAAA,EAAK,WAAU,sBAAA,CAAsB;AAAA,EAAA,GACxC;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Tool-permission prompt: Allow / Deny with optional detail; shows a verdict once resolved. */
2
+ export interface ConfirmationProps { title?: string; description?: React.ReactNode; detail?: React.ReactNode; allowLabel?: string; denyLabel?: string; resolved?: "allowed" | "denied"; onAllow?: () => void; onDeny?: () => void; }
3
+ export declare function Confirmation(props: ConfirmationProps): JSX.Element;
@@ -0,0 +1,54 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ const AX_CONFIRM_CSS = `
4
+ .ax-confirm { border: 1px solid var(--border-strong); border-radius: var(--radius-3); background: var(--surface-card); overflow: hidden; }
5
+ .ax-confirm__head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; }
6
+ .ax-confirm__icon { width: 16px; height: 16px; flex: none; color: var(--warn); }
7
+ .ax-confirm__title { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-body); flex: 1; }
8
+ .ax-confirm__body { padding: 0 14px 12px 40px; }
9
+ .ax-confirm__desc { font-size: var(--text-sm); color: var(--text-muted); margin: 0; line-height: var(--leading-body); }
10
+ .ax-confirm__detail { margin-top: 10px; padding: 8px 10px; background: var(--bg-0); border: 1px solid var(--border-default); border-radius: var(--radius-2); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body); white-space: pre-wrap; word-break: break-word; }
11
+ [data-theme="light"] .ax-confirm__detail { background: var(--bg-1); }
12
+ .ax-confirm__actions { display: flex; gap: 8px; padding: 12px 14px; border-top: 1px solid var(--border-default); background: var(--surface-panel); }
13
+ .ax-confirm__spacer { flex: 1; }
14
+ .ax-confirm__btn { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 0 14px; 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); }
15
+ .ax-confirm__btn--deny { background: transparent; color: var(--text-muted); border-color: var(--border-strong); }
16
+ .ax-confirm__btn--deny:hover { background: var(--surface-raised); color: var(--text-body); }
17
+ .ax-confirm__btn--allow { background: var(--accent); color: var(--accent-fg); }
18
+ .ax-confirm__btn--allow:hover { background: var(--accent-hover); }
19
+ .ax-confirm--resolved { opacity: 0.6; }
20
+ .ax-confirm__verdict { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; padding: 12px 14px; border-top: 1px solid var(--border-default); }
21
+ .ax-confirm__verdict--allowed { color: var(--ok); }
22
+ .ax-confirm__verdict--denied { color: var(--danger); }
23
+ `;
24
+ if (typeof document !== "undefined" && !document.getElementById("ax-confirm-css")) {
25
+ const s = document.createElement("style");
26
+ s.id = "ax-confirm-css";
27
+ s.textContent = AX_CONFIRM_CSS;
28
+ document.head.appendChild(s);
29
+ }
30
+ const Warn = /* @__PURE__ */ jsxs("svg", { className: "ax-confirm__icon", 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 Confirmation({ title = "Confirm action", description, detail, allowLabel = "Allow", denyLabel = "Deny", resolved, onAllow, onDeny, className = "", ...rest }) {
35
+ return /* @__PURE__ */ jsxs("div", { className: ["ax-confirm", resolved ? "ax-confirm--resolved" : "", className].filter(Boolean).join(" "), ...rest, children: [
36
+ /* @__PURE__ */ jsxs("div", { className: "ax-confirm__head", children: [
37
+ Warn,
38
+ /* @__PURE__ */ jsx("span", { className: "ax-confirm__title", children: title })
39
+ ] }),
40
+ description || detail ? /* @__PURE__ */ jsxs("div", { className: "ax-confirm__body", children: [
41
+ description ? /* @__PURE__ */ jsx("p", { className: "ax-confirm__desc", children: description }) : null,
42
+ detail ? /* @__PURE__ */ jsx("div", { className: "ax-confirm__detail", children: detail }) : null
43
+ ] }) : null,
44
+ resolved ? /* @__PURE__ */ jsx("div", { className: "ax-confirm__verdict ax-confirm__verdict--" + (resolved === "allowed" ? "allowed" : "denied"), children: resolved === "allowed" ? "✓ Allowed" : "✕ Denied" }) : /* @__PURE__ */ jsxs("div", { className: "ax-confirm__actions", children: [
45
+ /* @__PURE__ */ jsx("span", { className: "ax-confirm__spacer" }),
46
+ /* @__PURE__ */ jsx("button", { className: "ax-confirm__btn ax-confirm__btn--deny", onClick: onDeny, children: denyLabel }),
47
+ /* @__PURE__ */ jsx("button", { className: "ax-confirm__btn ax-confirm__btn--allow", onClick: onAllow, children: allowLabel })
48
+ ] })
49
+ ] });
50
+ }
51
+ export {
52
+ Confirmation
53
+ };
54
+ //# sourceMappingURL=Confirmation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Confirmation.js","sources":["../../../src/components/ai/Confirmation.jsx"],"sourcesContent":["import React from \"react\";\n\nconst AX_CONFIRM_CSS = `\n.ax-confirm { border: 1px solid var(--border-strong); border-radius: var(--radius-3); background: var(--surface-card); overflow: hidden; }\n.ax-confirm__head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; }\n.ax-confirm__icon { width: 16px; height: 16px; flex: none; color: var(--warn); }\n.ax-confirm__title { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-body); flex: 1; }\n.ax-confirm__body { padding: 0 14px 12px 40px; }\n.ax-confirm__desc { font-size: var(--text-sm); color: var(--text-muted); margin: 0; line-height: var(--leading-body); }\n.ax-confirm__detail { margin-top: 10px; padding: 8px 10px; background: var(--bg-0); border: 1px solid var(--border-default); border-radius: var(--radius-2); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body); white-space: pre-wrap; word-break: break-word; }\n[data-theme=\"light\"] .ax-confirm__detail { background: var(--bg-1); }\n.ax-confirm__actions { display: flex; gap: 8px; padding: 12px 14px; border-top: 1px solid var(--border-default); background: var(--surface-panel); }\n.ax-confirm__spacer { flex: 1; }\n.ax-confirm__btn { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 0 14px; 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-confirm__btn--deny { background: transparent; color: var(--text-muted); border-color: var(--border-strong); }\n.ax-confirm__btn--deny:hover { background: var(--surface-raised); color: var(--text-body); }\n.ax-confirm__btn--allow { background: var(--accent); color: var(--accent-fg); }\n.ax-confirm__btn--allow:hover { background: var(--accent-hover); }\n.ax-confirm--resolved { opacity: 0.6; }\n.ax-confirm__verdict { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; padding: 12px 14px; border-top: 1px solid var(--border-default); }\n.ax-confirm__verdict--allowed { color: var(--ok); }\n.ax-confirm__verdict--denied { color: var(--danger); }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-confirm-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-confirm-css\";\n s.textContent = AX_CONFIRM_CSS;\n document.head.appendChild(s);\n}\n\nconst Warn = <svg className=\"ax-confirm__icon\" 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 Confirmation({ title = \"Confirm action\", description, detail, allowLabel = \"Allow\", denyLabel = \"Deny\", resolved, onAllow, onDeny, className = \"\", ...rest }) {\n return (\n <div className={[\"ax-confirm\", resolved ? \"ax-confirm--resolved\" : \"\", className].filter(Boolean).join(\" \")} {...rest}>\n <div className=\"ax-confirm__head\">\n {Warn}\n <span className=\"ax-confirm__title\">{title}</span>\n </div>\n {(description || detail) ? (\n <div className=\"ax-confirm__body\">\n {description ? <p className=\"ax-confirm__desc\">{description}</p> : null}\n {detail ? <div className=\"ax-confirm__detail\">{detail}</div> : null}\n </div>\n ) : null}\n {resolved ? (\n <div className={\"ax-confirm__verdict ax-confirm__verdict--\" + (resolved === \"allowed\" ? \"allowed\" : \"denied\")}>\n {resolved === \"allowed\" ? \"✓ Allowed\" : \"✕ Denied\"}\n </div>\n ) : (\n <div className=\"ax-confirm__actions\">\n <span className=\"ax-confirm__spacer\"></span>\n <button className=\"ax-confirm__btn ax-confirm__btn--deny\" onClick={onDeny}>{denyLabel}</button>\n <button className=\"ax-confirm__btn ax-confirm__btn--allow\" onClick={onAllow}>{allowLabel}</button>\n </div>\n )}\n </div>\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;AAAA;AAsBvB,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;AAEA,MAAM,OAAO,qBAAC,OAAA,EAAI,WAAU,oBAAmB,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;AAE7R,SAAS,aAAa,EAAE,QAAQ,kBAAkB,aAAa,QAAQ,aAAa,SAAS,YAAY,QAAQ,UAAU,SAAS,QAAQ,YAAY,IAAI,GAAG,QAAQ;AAC5K,8BACG,OAAA,EAAI,WAAW,CAAC,cAAc,WAAW,yBAAyB,IAAI,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,MAC/G,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,oBACZ,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAA,EAAK,WAAU,qBAAqB,UAAA,MAAA,CAAM;AAAA,IAAA,GAC7C;AAAA,IACE,eAAe,SACf,qBAAC,OAAA,EAAI,WAAU,oBACZ,UAAA;AAAA,MAAA,cAAc,oBAAC,KAAA,EAAE,WAAU,oBAAoB,uBAAY,IAAO;AAAA,MAClE,SAAS,oBAAC,OAAA,EAAI,WAAU,sBAAsB,kBAAO,IAAS;AAAA,IAAA,EAAA,CACjE,IACE;AAAA,IACH,WACC,oBAAC,OAAA,EAAI,WAAW,+CAA+C,aAAa,YAAY,YAAY,WACjG,UAAA,aAAa,YAAY,cAAc,YAC1C,IAEA,qBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,qBAAA,CAAqB;AAAA,0BACpC,UAAA,EAAO,WAAU,yCAAwC,SAAS,QAAS,UAAA,WAAU;AAAA,0BACrF,UAAA,EAAO,WAAU,0CAAyC,SAAS,SAAU,UAAA,WAAA,CAAW;AAAA,IAAA,EAAA,CAC3F;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Context-window usage meter (tokens). Optionally splits input vs output; warns near the cap. */
2
+ export interface ContextProps { used?: number; max?: number; input?: number; output?: number; label?: string; }
3
+ export declare function Context(props: ContextProps): JSX.Element;
@@ -0,0 +1,63 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ const AX_CONTEXT_CSS = `
4
+ .ax-context { display: flex; flex-direction: column; gap: 6px; min-width: 180px; }
5
+ .ax-context__top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
6
+ .ax-context__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); }
7
+ .ax-context__val { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); }
8
+ .ax-context__val b { color: var(--text-body); font-weight: var(--weight-medium); }
9
+ .ax-context__track { display: flex; height: 6px; border: 1px solid var(--border-default); border-radius: var(--radius-1); overflow: hidden; background: var(--surface-raised); }
10
+ .ax-context__seg { height: 100%; }
11
+ .ax-context__seg--in { background: var(--text-body); }
12
+ .ax-context__seg--out { background: var(--text-faint); }
13
+ .ax-context__seg--warn { background: var(--warn); }
14
+ .ax-context__legend { display: flex; gap: 14px; }
15
+ .ax-context__key { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }
16
+ .ax-context__dot { width: 7px; height: 7px; border-radius: 1px; }
17
+ `;
18
+ if (typeof document !== "undefined" && !document.getElementById("ax-context-css")) {
19
+ const s = document.createElement("style");
20
+ s.id = "ax-context-css";
21
+ s.textContent = AX_CONTEXT_CSS;
22
+ document.head.appendChild(s);
23
+ }
24
+ function fmt(n) {
25
+ if (n >= 1e3) return (n / 1e3).toFixed(n % 1e3 === 0 ? 0 : 1) + "k";
26
+ return String(n);
27
+ }
28
+ function Context({ used = 0, max = 128e3, input, output, label = "Context", className = "", ...rest }) {
29
+ const pct = Math.min(100, used / max * 100);
30
+ const near = pct >= 85;
31
+ const inPct = input != null ? input / max * 100 : pct;
32
+ const outPct = output != null ? output / max * 100 : 0;
33
+ return /* @__PURE__ */ jsxs("div", { className: ["ax-context", className].filter(Boolean).join(" "), ...rest, children: [
34
+ /* @__PURE__ */ jsxs("div", { className: "ax-context__top", children: [
35
+ /* @__PURE__ */ jsx("span", { className: "ax-context__label", children: label }),
36
+ /* @__PURE__ */ jsxs("span", { className: "ax-context__val", children: [
37
+ /* @__PURE__ */ jsx("b", { children: fmt(used) }),
38
+ " / ",
39
+ fmt(max)
40
+ ] })
41
+ ] }),
42
+ /* @__PURE__ */ jsx("div", { className: "ax-context__track", children: input != null ? /* @__PURE__ */ jsxs(React.Fragment, { children: [
43
+ /* @__PURE__ */ jsx("span", { className: "ax-context__seg " + (near ? "ax-context__seg--warn" : "ax-context__seg--in"), style: { width: inPct + "%" } }),
44
+ /* @__PURE__ */ jsx("span", { className: "ax-context__seg ax-context__seg--out", style: { width: outPct + "%" } })
45
+ ] }) : /* @__PURE__ */ jsx("span", { className: "ax-context__seg " + (near ? "ax-context__seg--warn" : "ax-context__seg--in"), style: { width: pct + "%" } }) }),
46
+ input != null ? /* @__PURE__ */ jsxs("div", { className: "ax-context__legend", children: [
47
+ /* @__PURE__ */ jsxs("span", { className: "ax-context__key", children: [
48
+ /* @__PURE__ */ jsx("span", { className: "ax-context__dot", style: { background: near ? "var(--warn)" : "var(--text-body)" } }),
49
+ "Input ",
50
+ fmt(input)
51
+ ] }),
52
+ /* @__PURE__ */ jsxs("span", { className: "ax-context__key", children: [
53
+ /* @__PURE__ */ jsx("span", { className: "ax-context__dot", style: { background: "var(--text-faint)" } }),
54
+ "Output ",
55
+ fmt(output || 0)
56
+ ] })
57
+ ] }) : null
58
+ ] });
59
+ }
60
+ export {
61
+ Context
62
+ };
63
+ //# sourceMappingURL=Context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Context.js","sources":["../../../src/components/ai/Context.jsx"],"sourcesContent":["import React from \"react\";\n\nconst AX_CONTEXT_CSS = `\n.ax-context { display: flex; flex-direction: column; gap: 6px; min-width: 180px; }\n.ax-context__top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }\n.ax-context__label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint); }\n.ax-context__val { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); }\n.ax-context__val b { color: var(--text-body); font-weight: var(--weight-medium); }\n.ax-context__track { display: flex; height: 6px; border: 1px solid var(--border-default); border-radius: var(--radius-1); overflow: hidden; background: var(--surface-raised); }\n.ax-context__seg { height: 100%; }\n.ax-context__seg--in { background: var(--text-body); }\n.ax-context__seg--out { background: var(--text-faint); }\n.ax-context__seg--warn { background: var(--warn); }\n.ax-context__legend { display: flex; gap: 14px; }\n.ax-context__key { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); }\n.ax-context__dot { width: 7px; height: 7px; border-radius: 1px; }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-context-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-context-css\";\n s.textContent = AX_CONTEXT_CSS;\n document.head.appendChild(s);\n}\n\nfunction fmt(n) {\n if (n >= 1000) return (n / 1000).toFixed(n % 1000 === 0 ? 0 : 1) + \"k\";\n return String(n);\n}\n\nexport function Context({ used = 0, max = 128000, input, output, label = \"Context\", className = \"\", ...rest }) {\n const pct = Math.min(100, (used / max) * 100);\n const near = pct >= 85;\n const inPct = input != null ? (input / max) * 100 : pct;\n const outPct = output != null ? (output / max) * 100 : 0;\n return (\n <div className={[\"ax-context\", className].filter(Boolean).join(\" \")} {...rest}>\n <div className=\"ax-context__top\">\n <span className=\"ax-context__label\">{label}</span>\n <span className=\"ax-context__val\"><b>{fmt(used)}</b> / {fmt(max)}</span>\n </div>\n <div className=\"ax-context__track\">\n {input != null ? (\n <React.Fragment>\n <span className={\"ax-context__seg \" + (near ? \"ax-context__seg--warn\" : \"ax-context__seg--in\")} style={{ width: inPct + \"%\" }}></span>\n <span className=\"ax-context__seg ax-context__seg--out\" style={{ width: outPct + \"%\" }}></span>\n </React.Fragment>\n ) : (\n <span className={\"ax-context__seg \" + (near ? \"ax-context__seg--warn\" : \"ax-context__seg--in\")} style={{ width: pct + \"%\" }}></span>\n )}\n </div>\n {input != null ? (\n <div className=\"ax-context__legend\">\n <span className=\"ax-context__key\"><span className=\"ax-context__dot\" style={{ background: near ? \"var(--warn)\" : \"var(--text-body)\" }}></span>Input {fmt(input)}</span>\n <span className=\"ax-context__key\"><span className=\"ax-context__dot\" style={{ background: \"var(--text-faint)\" }}></span>Output {fmt(output || 0)}</span>\n </div>\n ) : null}\n </div>\n );\n}\n"],"names":[],"mappings":";;AAEA,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBvB,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;AAEA,SAAS,IAAI,GAAG;AACd,MAAI,KAAK,IAAM,SAAQ,IAAI,KAAM,QAAQ,IAAI,QAAS,IAAI,IAAI,CAAC,IAAI;AACnE,SAAO,OAAO,CAAC;AACjB;AAEO,SAAS,QAAQ,EAAE,OAAO,GAAG,MAAM,OAAQ,OAAO,QAAQ,QAAQ,WAAW,YAAY,IAAI,GAAG,QAAQ;AAC7G,QAAM,MAAM,KAAK,IAAI,KAAM,OAAO,MAAO,GAAG;AAC5C,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,SAAS,OAAQ,QAAQ,MAAO,MAAM;AACpD,QAAM,SAAS,UAAU,OAAQ,SAAS,MAAO,MAAM;AACvD,SACE,qBAAC,OAAA,EAAI,WAAW,CAAC,cAAc,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,MACvE,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,qBAAqB,UAAA,OAAM;AAAA,MAC3C,qBAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA;AAAA,QAAA,oBAAC,KAAA,EAAG,UAAA,IAAI,IAAI,EAAA,CAAE;AAAA,QAAI;AAAA,QAAI,IAAI,GAAG;AAAA,MAAA,EAAA,CAAE;AAAA,IAAA,GACnE;AAAA,IACA,oBAAC,SAAI,WAAU,qBACZ,mBAAS,OACR,qBAAC,MAAM,UAAN,EACC,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAW,sBAAsB,OAAO,0BAA0B,wBAAwB,OAAO,EAAE,OAAO,QAAQ,IAAA,EAAI,CAAG;AAAA,MAC/H,oBAAC,UAAK,WAAU,wCAAuC,OAAO,EAAE,OAAO,SAAS,MAAI,CAAG;AAAA,IAAA,EAAA,CACzF,IAEA,oBAAC,QAAA,EAAK,WAAW,sBAAsB,OAAO,0BAA0B,wBAAwB,OAAO,EAAE,OAAO,MAAM,IAAA,GAAO,GAEjI;AAAA,IACC,SAAS,OACR,qBAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,MAAA,qBAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,mBAAkB,OAAO,EAAE,YAAY,OAAO,gBAAgB,mBAAA,EAAmB,CAAG;AAAA,QAAO;AAAA,QAAO,IAAI,KAAK;AAAA,MAAA,GAAE;AAAA,MAC/J,qBAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA;AAAA,QAAA,oBAAC,UAAK,WAAU,mBAAkB,OAAO,EAAE,YAAY,uBAAuB;AAAA,QAAO;AAAA,QAAQ,IAAI,UAAU,CAAC;AAAA,MAAA,EAAA,CAAE;AAAA,IAAA,EAAA,CAClJ,IACE;AAAA,EAAA,GACN;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ /** Auto-scrolling chat thread container; sticks to bottom unless the user scrolls up (shows a "jump to latest" pill). */
2
+ export interface ConversationProps { autoStick?: boolean; children?: React.ReactNode; }
3
+ export declare function Conversation(props: ConversationProps): JSX.Element;