@opencode-ai/ui 0.0.0-beta-202606251302

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 (346) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +110 -0
  3. package/src/assets/audio/alert-01.aac +0 -0
  4. package/src/assets/audio/alert-01.mp3 +0 -0
  5. package/src/assets/audio/alert-02.aac +0 -0
  6. package/src/assets/audio/alert-02.mp3 +0 -0
  7. package/src/assets/audio/alert-03.aac +0 -0
  8. package/src/assets/audio/alert-03.mp3 +0 -0
  9. package/src/assets/audio/alert-04.aac +0 -0
  10. package/src/assets/audio/alert-04.mp3 +0 -0
  11. package/src/assets/audio/alert-05.aac +0 -0
  12. package/src/assets/audio/alert-05.mp3 +0 -0
  13. package/src/assets/audio/alert-06.aac +0 -0
  14. package/src/assets/audio/alert-06.mp3 +0 -0
  15. package/src/assets/audio/alert-07.aac +0 -0
  16. package/src/assets/audio/alert-07.mp3 +0 -0
  17. package/src/assets/audio/alert-08.aac +0 -0
  18. package/src/assets/audio/alert-08.mp3 +0 -0
  19. package/src/assets/audio/alert-09.aac +0 -0
  20. package/src/assets/audio/alert-09.mp3 +0 -0
  21. package/src/assets/audio/alert-10.aac +0 -0
  22. package/src/assets/audio/alert-10.mp3 +0 -0
  23. package/src/assets/audio/bip-bop-01.aac +0 -0
  24. package/src/assets/audio/bip-bop-01.mp3 +0 -0
  25. package/src/assets/audio/bip-bop-02.aac +0 -0
  26. package/src/assets/audio/bip-bop-02.mp3 +0 -0
  27. package/src/assets/audio/bip-bop-03.aac +0 -0
  28. package/src/assets/audio/bip-bop-03.mp3 +0 -0
  29. package/src/assets/audio/bip-bop-04.aac +0 -0
  30. package/src/assets/audio/bip-bop-04.mp3 +0 -0
  31. package/src/assets/audio/bip-bop-05.aac +0 -0
  32. package/src/assets/audio/bip-bop-05.mp3 +0 -0
  33. package/src/assets/audio/bip-bop-06.aac +0 -0
  34. package/src/assets/audio/bip-bop-06.mp3 +0 -0
  35. package/src/assets/audio/bip-bop-07.aac +0 -0
  36. package/src/assets/audio/bip-bop-07.mp3 +0 -0
  37. package/src/assets/audio/bip-bop-08.aac +0 -0
  38. package/src/assets/audio/bip-bop-08.mp3 +0 -0
  39. package/src/assets/audio/bip-bop-09.aac +0 -0
  40. package/src/assets/audio/bip-bop-09.mp3 +0 -0
  41. package/src/assets/audio/bip-bop-10.aac +0 -0
  42. package/src/assets/audio/bip-bop-10.mp3 +0 -0
  43. package/src/assets/audio/nope-01.aac +0 -0
  44. package/src/assets/audio/nope-01.mp3 +0 -0
  45. package/src/assets/audio/nope-02.aac +0 -0
  46. package/src/assets/audio/nope-02.mp3 +0 -0
  47. package/src/assets/audio/nope-03.aac +0 -0
  48. package/src/assets/audio/nope-03.mp3 +0 -0
  49. package/src/assets/audio/nope-04.aac +0 -0
  50. package/src/assets/audio/nope-04.mp3 +0 -0
  51. package/src/assets/audio/nope-05.aac +0 -0
  52. package/src/assets/audio/nope-05.mp3 +0 -0
  53. package/src/assets/audio/nope-06.aac +0 -0
  54. package/src/assets/audio/nope-06.mp3 +0 -0
  55. package/src/assets/audio/nope-07.aac +0 -0
  56. package/src/assets/audio/nope-07.mp3 +0 -0
  57. package/src/assets/audio/nope-08.aac +0 -0
  58. package/src/assets/audio/nope-08.mp3 +0 -0
  59. package/src/assets/audio/nope-09.aac +0 -0
  60. package/src/assets/audio/nope-09.mp3 +0 -0
  61. package/src/assets/audio/nope-10.aac +0 -0
  62. package/src/assets/audio/nope-10.mp3 +0 -0
  63. package/src/assets/audio/nope-11.aac +0 -0
  64. package/src/assets/audio/nope-11.mp3 +0 -0
  65. package/src/assets/audio/nope-12.aac +0 -0
  66. package/src/assets/audio/nope-12.mp3 +0 -0
  67. package/src/assets/audio/staplebops-01.aac +0 -0
  68. package/src/assets/audio/staplebops-01.mp3 +0 -0
  69. package/src/assets/audio/staplebops-02.aac +0 -0
  70. package/src/assets/audio/staplebops-02.mp3 +0 -0
  71. package/src/assets/audio/staplebops-03.aac +0 -0
  72. package/src/assets/audio/staplebops-03.mp3 +0 -0
  73. package/src/assets/audio/staplebops-04.aac +0 -0
  74. package/src/assets/audio/staplebops-04.mp3 +0 -0
  75. package/src/assets/audio/staplebops-05.aac +0 -0
  76. package/src/assets/audio/staplebops-05.mp3 +0 -0
  77. package/src/assets/audio/staplebops-06.aac +0 -0
  78. package/src/assets/audio/staplebops-06.mp3 +0 -0
  79. package/src/assets/audio/staplebops-07.aac +0 -0
  80. package/src/assets/audio/staplebops-07.mp3 +0 -0
  81. package/src/assets/audio/yup-01.aac +0 -0
  82. package/src/assets/audio/yup-01.mp3 +0 -0
  83. package/src/assets/audio/yup-02.aac +0 -0
  84. package/src/assets/audio/yup-02.mp3 +0 -0
  85. package/src/assets/audio/yup-03.aac +0 -0
  86. package/src/assets/audio/yup-03.mp3 +0 -0
  87. package/src/assets/audio/yup-04.aac +0 -0
  88. package/src/assets/audio/yup-04.mp3 +0 -0
  89. package/src/assets/audio/yup-05.aac +0 -0
  90. package/src/assets/audio/yup-05.mp3 +0 -0
  91. package/src/assets/audio/yup-06.aac +0 -0
  92. package/src/assets/audio/yup-06.mp3 +0 -0
  93. package/src/assets/fonts/Inter.ttf +0 -0
  94. package/src/assets/fonts/JetBrainsMonoNerdFontMono-Regular.woff2 +0 -0
  95. package/src/assets/icons/app/android-studio.svg +369 -0
  96. package/src/assets/icons/app/antigravity.svg +97 -0
  97. package/src/assets/icons/app/cursor.svg +16 -0
  98. package/src/assets/icons/app/file-explorer.svg +20 -0
  99. package/src/assets/icons/app/finder.png +0 -0
  100. package/src/assets/icons/app/ghostty.svg +13 -0
  101. package/src/assets/icons/app/iterm2.svg +13 -0
  102. package/src/assets/icons/app/powershell.svg +14 -0
  103. package/src/assets/icons/app/sublimetext.svg +17 -0
  104. package/src/assets/icons/app/terminal.png +0 -0
  105. package/src/assets/icons/app/textmate.png +0 -0
  106. package/src/assets/icons/app/vscode.svg +39 -0
  107. package/src/assets/icons/app/warp.png +0 -0
  108. package/src/assets/icons/app/xcode.png +0 -0
  109. package/src/assets/icons/app/zed-dark.svg +15 -0
  110. package/src/assets/icons/app/zed.svg +15 -0
  111. package/src/components/accordion.css +123 -0
  112. package/src/components/accordion.tsx +92 -0
  113. package/src/components/animated-number.css +75 -0
  114. package/src/components/animated-number.tsx +109 -0
  115. package/src/components/app-icon.css +5 -0
  116. package/src/components/app-icon.tsx +85 -0
  117. package/src/components/app-icons/sprite.svg +114 -0
  118. package/src/components/app-icons/types.ts +21 -0
  119. package/src/components/avatar.css +49 -0
  120. package/src/components/avatar.tsx +55 -0
  121. package/src/components/button.css +194 -0
  122. package/src/components/button.tsx +33 -0
  123. package/src/components/card.css +94 -0
  124. package/src/components/card.tsx +123 -0
  125. package/src/components/checkbox.css +131 -0
  126. package/src/components/checkbox.tsx +43 -0
  127. package/src/components/collapsible.css +148 -0
  128. package/src/components/collapsible.tsx +48 -0
  129. package/src/components/context-menu.css +134 -0
  130. package/src/components/context-menu.tsx +308 -0
  131. package/src/components/dialog.css +181 -0
  132. package/src/components/dialog.tsx +72 -0
  133. package/src/components/diff-changes.css +42 -0
  134. package/src/components/diff-changes.tsx +115 -0
  135. package/src/components/dock-surface.css +23 -0
  136. package/src/components/dock-surface.tsx +54 -0
  137. package/src/components/dropdown-menu.css +135 -0
  138. package/src/components/dropdown-menu.tsx +308 -0
  139. package/src/components/favicon.tsx +13 -0
  140. package/src/components/file-icon.css +26 -0
  141. package/src/components/file-icon.tsx +588 -0
  142. package/src/components/file-icons/sprite.svg +11707 -0
  143. package/src/components/file-icons/types.ts +1095 -0
  144. package/src/components/font.tsx +1 -0
  145. package/src/components/hover-card.css +61 -0
  146. package/src/components/hover-card.tsx +32 -0
  147. package/src/components/icon-button.css +181 -0
  148. package/src/components/icon-button.tsx +29 -0
  149. package/src/components/icon.css +34 -0
  150. package/src/components/icon.tsx +169 -0
  151. package/src/components/image-preview.css +63 -0
  152. package/src/components/image-preview.tsx +32 -0
  153. package/src/components/inline-input.css +17 -0
  154. package/src/components/inline-input.tsx +22 -0
  155. package/src/components/keybind.css +18 -0
  156. package/src/components/keybind.tsx +20 -0
  157. package/src/components/list.css +331 -0
  158. package/src/components/list.tsx +394 -0
  159. package/src/components/logo.css +4 -0
  160. package/src/components/logo.tsx +62 -0
  161. package/src/components/motion-spring.tsx +58 -0
  162. package/src/components/popover.css +98 -0
  163. package/src/components/popover.tsx +153 -0
  164. package/src/components/progress-circle.css +12 -0
  165. package/src/components/progress-circle.tsx +57 -0
  166. package/src/components/progress.css +63 -0
  167. package/src/components/progress.tsx +39 -0
  168. package/src/components/provider-icon.css +5 -0
  169. package/src/components/provider-icon.tsx +25 -0
  170. package/src/components/provider-icons/sprite.svg +1135 -0
  171. package/src/components/provider-icons/types.ts +105 -0
  172. package/src/components/radio-group.css +187 -0
  173. package/src/components/radio-group.tsx +83 -0
  174. package/src/components/resize-handle.css +58 -0
  175. package/src/components/resize-handle.tsx +82 -0
  176. package/src/components/scroll-view.css +66 -0
  177. package/src/components/scroll-view.tsx +250 -0
  178. package/src/components/select.css +202 -0
  179. package/src/components/select.tsx +174 -0
  180. package/src/components/spinner.css +6 -0
  181. package/src/components/spinner.tsx +52 -0
  182. package/src/components/sticky-accordion-header.css +6 -0
  183. package/src/components/sticky-accordion-header.tsx +18 -0
  184. package/src/components/switch.css +132 -0
  185. package/src/components/switch.tsx +29 -0
  186. package/src/components/tabs.css +635 -0
  187. package/src/components/tabs.tsx +125 -0
  188. package/src/components/tag.css +37 -0
  189. package/src/components/tag.tsx +22 -0
  190. package/src/components/text-field.css +134 -0
  191. package/src/components/text-field.tsx +128 -0
  192. package/src/components/text-reveal.css +150 -0
  193. package/src/components/text-reveal.tsx +143 -0
  194. package/src/components/text-shimmer.css +119 -0
  195. package/src/components/text-shimmer.tsx +62 -0
  196. package/src/components/text-strikethrough.css +27 -0
  197. package/src/components/text-strikethrough.tsx +84 -0
  198. package/src/components/toast.css +236 -0
  199. package/src/components/toast.tsx +185 -0
  200. package/src/components/tooltip.css +74 -0
  201. package/src/components/tooltip.tsx +161 -0
  202. package/src/components/typewriter.css +14 -0
  203. package/src/components/typewriter.tsx +55 -0
  204. package/src/context/dialog.tsx +197 -0
  205. package/src/context/file.tsx +10 -0
  206. package/src/context/helper.tsx +38 -0
  207. package/src/context/i18n.tsx +38 -0
  208. package/src/context/index.ts +4 -0
  209. package/src/context/marked.tsx +522 -0
  210. package/src/context/worker-pool.tsx +20 -0
  211. package/src/custom-elements.d.ts +17 -0
  212. package/src/hooks/create-auto-scroll.tsx +237 -0
  213. package/src/hooks/index.ts +2 -0
  214. package/src/hooks/use-filtered-list.tsx +134 -0
  215. package/src/i18n/ar.ts +168 -0
  216. package/src/i18n/br.ts +168 -0
  217. package/src/i18n/bs.ts +172 -0
  218. package/src/i18n/da.ts +167 -0
  219. package/src/i18n/de.ts +173 -0
  220. package/src/i18n/en.ts +176 -0
  221. package/src/i18n/es.ts +168 -0
  222. package/src/i18n/fr.ts +168 -0
  223. package/src/i18n/ja.ts +167 -0
  224. package/src/i18n/ko.ts +168 -0
  225. package/src/i18n/no.ts +171 -0
  226. package/src/i18n/pl.ts +167 -0
  227. package/src/i18n/ru.ts +167 -0
  228. package/src/i18n/th.ts +169 -0
  229. package/src/i18n/tr.ts +174 -0
  230. package/src/i18n/uk.ts +167 -0
  231. package/src/i18n/zh.ts +171 -0
  232. package/src/i18n/zht.ts +171 -0
  233. package/src/storybook/fixtures.ts +51 -0
  234. package/src/storybook/scaffold.tsx +62 -0
  235. package/src/styles/animations.css +141 -0
  236. package/src/styles/base.css +404 -0
  237. package/src/styles/colors.css +772 -0
  238. package/src/styles/index.css +53 -0
  239. package/src/styles/tailwind/colors.css +285 -0
  240. package/src/styles/tailwind/index.css +78 -0
  241. package/src/styles/tailwind/utilities.css +131 -0
  242. package/src/styles/theme.css +609 -0
  243. package/src/styles/utilities.css +118 -0
  244. package/src/theme/color.ts +299 -0
  245. package/src/theme/context.tsx +370 -0
  246. package/src/theme/default-themes.ts +116 -0
  247. package/src/theme/index.ts +78 -0
  248. package/src/theme/loader.ts +112 -0
  249. package/src/theme/resolve.ts +540 -0
  250. package/src/theme/themes/amoled.json +49 -0
  251. package/src/theme/themes/aura.json +51 -0
  252. package/src/theme/themes/ayu.json +51 -0
  253. package/src/theme/themes/carbonfox.json +53 -0
  254. package/src/theme/themes/catppuccin-frappe.json +85 -0
  255. package/src/theme/themes/catppuccin-macchiato.json +85 -0
  256. package/src/theme/themes/catppuccin.json +45 -0
  257. package/src/theme/themes/cobalt2.json +87 -0
  258. package/src/theme/themes/cursor.json +91 -0
  259. package/src/theme/themes/dracula.json +49 -0
  260. package/src/theme/themes/everforest.json +89 -0
  261. package/src/theme/themes/flexoki.json +86 -0
  262. package/src/theme/themes/github.json +85 -0
  263. package/src/theme/themes/gruvbox.json +45 -0
  264. package/src/theme/themes/kanagawa.json +89 -0
  265. package/src/theme/themes/lucent-orng.json +87 -0
  266. package/src/theme/themes/material.json +87 -0
  267. package/src/theme/themes/matrix.json +113 -0
  268. package/src/theme/themes/mercury.json +86 -0
  269. package/src/theme/themes/monokai.json +49 -0
  270. package/src/theme/themes/nightowl.json +46 -0
  271. package/src/theme/themes/nord.json +46 -0
  272. package/src/theme/themes/oc-2.json +468 -0
  273. package/src/theme/themes/one-dark.json +89 -0
  274. package/src/theme/themes/onedarkpro.json +45 -0
  275. package/src/theme/themes/opencode.json +89 -0
  276. package/src/theme/themes/orng.json +87 -0
  277. package/src/theme/themes/osaka-jade.json +88 -0
  278. package/src/theme/themes/palenight.json +85 -0
  279. package/src/theme/themes/rosepine.json +85 -0
  280. package/src/theme/themes/shadesofpurple.json +51 -0
  281. package/src/theme/themes/solarized.json +49 -0
  282. package/src/theme/themes/synthwave84.json +87 -0
  283. package/src/theme/themes/tokyonight.json +47 -0
  284. package/src/theme/themes/vercel.json +90 -0
  285. package/src/theme/themes/vesper.json +51 -0
  286. package/src/theme/themes/zenburn.json +87 -0
  287. package/src/theme/types.ts +75 -0
  288. package/src/theme/v2/avatar.ts +48 -0
  289. package/src/theme/v2/default-primitives.ts +114 -0
  290. package/src/theme/v2/foreground.ts +60 -0
  291. package/src/theme/v2/mapping.ts +138 -0
  292. package/src/theme/v2/resolve.ts +153 -0
  293. package/src/v2/components/accordion-v2.css +139 -0
  294. package/src/v2/components/accordion-v2.tsx +86 -0
  295. package/src/v2/components/avatar-v2.css +70 -0
  296. package/src/v2/components/avatar-v2.tsx +59 -0
  297. package/src/v2/components/badge-v2.css +27 -0
  298. package/src/v2/components/badge-v2.tsx +20 -0
  299. package/src/v2/components/button-v2.css +186 -0
  300. package/src/v2/components/button-v2.tsx +35 -0
  301. package/src/v2/components/checkbox-v2.css +184 -0
  302. package/src/v2/components/checkbox-v2.tsx +65 -0
  303. package/src/v2/components/dialog-v2.css +150 -0
  304. package/src/v2/components/dialog-v2.tsx +93 -0
  305. package/src/v2/components/diff-changes-v2.css +24 -0
  306. package/src/v2/components/diff-changes-v2.tsx +28 -0
  307. package/src/v2/components/field-v2.css +94 -0
  308. package/src/v2/components/field-v2.tsx +265 -0
  309. package/src/v2/components/icon-button-v2.css +155 -0
  310. package/src/v2/components/icon-button-v2.tsx +37 -0
  311. package/src/v2/components/icon.tsx +129 -0
  312. package/src/v2/components/inline-input-v2.css +218 -0
  313. package/src/v2/components/inline-input-v2.tsx +90 -0
  314. package/src/v2/components/keybind-v2.css +76 -0
  315. package/src/v2/components/keybind-v2.tsx +30 -0
  316. package/src/v2/components/line-comment-v2.css +204 -0
  317. package/src/v2/components/line-comment-v2.tsx +155 -0
  318. package/src/v2/components/menu-v2.css +190 -0
  319. package/src/v2/components/menu-v2.tsx +225 -0
  320. package/src/v2/components/project-avatar-v2.css +126 -0
  321. package/src/v2/components/project-avatar-v2.tsx +64 -0
  322. package/src/v2/components/radio-v2.css +202 -0
  323. package/src/v2/components/radio-v2.tsx +72 -0
  324. package/src/v2/components/segmented-control-v2.css +80 -0
  325. package/src/v2/components/segmented-control-v2.tsx +208 -0
  326. package/src/v2/components/select-v2.css +285 -0
  327. package/src/v2/components/select-v2.tsx +208 -0
  328. package/src/v2/components/switch-v2.css +154 -0
  329. package/src/v2/components/switch-v2.tsx +28 -0
  330. package/src/v2/components/tab-state-indicator.tsx +37 -0
  331. package/src/v2/components/tabs-v2.css +225 -0
  332. package/src/v2/components/tabs-v2.tsx +147 -0
  333. package/src/v2/components/text-input-v2.css +145 -0
  334. package/src/v2/components/text-input-v2.tsx +67 -0
  335. package/src/v2/components/text-shimmer-v2.css +125 -0
  336. package/src/v2/components/text-shimmer-v2.tsx +63 -0
  337. package/src/v2/components/textarea-v2.css +78 -0
  338. package/src/v2/components/textarea-v2.tsx +31 -0
  339. package/src/v2/components/toast-v2.css +215 -0
  340. package/src/v2/components/toast-v2.tsx +144 -0
  341. package/src/v2/components/tooltip-v2.css +53 -0
  342. package/src/v2/components/tooltip-v2.tsx +146 -0
  343. package/src/v2/components/wordmark-v2.tsx +92 -0
  344. package/src/v2/styles/colors.css +172 -0
  345. package/src/v2/styles/tailwind.css +2 -0
  346. package/src/v2/styles/theme.css +441 -0
@@ -0,0 +1,115 @@
1
+ import { createMemo, For, Match, Show, Switch } from "solid-js"
2
+
3
+ export function DiffChanges(props: {
4
+ class?: string
5
+ changes: { additions: number; deletions: number } | { additions: number; deletions: number }[]
6
+ variant?: "default" | "bars"
7
+ }) {
8
+ const variant = () => props.variant ?? "default"
9
+
10
+ const additions = createMemo(() =>
11
+ Array.isArray(props.changes)
12
+ ? props.changes.reduce((acc, diff) => acc + (diff.additions ?? 0), 0)
13
+ : props.changes.additions,
14
+ )
15
+ const deletions = createMemo(() =>
16
+ Array.isArray(props.changes)
17
+ ? props.changes.reduce((acc, diff) => acc + (diff.deletions ?? 0), 0)
18
+ : props.changes.deletions,
19
+ )
20
+ const total = createMemo(() => (additions() ?? 0) + (deletions() ?? 0))
21
+
22
+ const blockCounts = createMemo(() => {
23
+ const TOTAL_BLOCKS = 5
24
+
25
+ const adds = additions() ?? 0
26
+ const dels = deletions() ?? 0
27
+
28
+ if (adds === 0 && dels === 0) {
29
+ return { added: 0, deleted: 0, neutral: TOTAL_BLOCKS }
30
+ }
31
+
32
+ const total = adds + dels
33
+
34
+ if (total < 5) {
35
+ const added = adds > 0 ? 1 : 0
36
+ const deleted = dels > 0 ? 1 : 0
37
+ const neutral = TOTAL_BLOCKS - added - deleted
38
+ return { added, deleted, neutral }
39
+ }
40
+
41
+ const ratio = adds > dels ? adds / dels : dels / adds
42
+ let BLOCKS_FOR_COLORS = TOTAL_BLOCKS
43
+
44
+ if (total < 20) {
45
+ BLOCKS_FOR_COLORS = TOTAL_BLOCKS - 1
46
+ } else if (ratio < 4) {
47
+ BLOCKS_FOR_COLORS = TOTAL_BLOCKS - 1
48
+ }
49
+
50
+ const percentAdded = adds / total
51
+ const percentDeleted = dels / total
52
+
53
+ const added_raw = percentAdded * BLOCKS_FOR_COLORS
54
+ const deleted_raw = percentDeleted * BLOCKS_FOR_COLORS
55
+
56
+ let added = adds > 0 ? Math.max(1, Math.round(added_raw)) : 0
57
+ let deleted = dels > 0 ? Math.max(1, Math.round(deleted_raw)) : 0
58
+
59
+ // Cap bars based on actual change magnitude
60
+ if (adds > 0 && adds <= 5) added = Math.min(added, 1)
61
+ if (adds > 5 && adds <= 10) added = Math.min(added, 2)
62
+ if (dels > 0 && dels <= 5) deleted = Math.min(deleted, 1)
63
+ if (dels > 5 && dels <= 10) deleted = Math.min(deleted, 2)
64
+
65
+ let total_allocated = added + deleted
66
+ if (total_allocated > BLOCKS_FOR_COLORS) {
67
+ if (added_raw > deleted_raw) {
68
+ added = BLOCKS_FOR_COLORS - deleted
69
+ } else {
70
+ deleted = BLOCKS_FOR_COLORS - added
71
+ }
72
+ total_allocated = added + deleted
73
+ }
74
+
75
+ const neutral = Math.max(0, TOTAL_BLOCKS - total_allocated)
76
+
77
+ return { added, deleted, neutral }
78
+ })
79
+
80
+ const ADD_COLOR = "var(--icon-diff-add-base)"
81
+ const DELETE_COLOR = "var(--icon-diff-delete-base)"
82
+ const NEUTRAL_COLOR = "var(--icon-weak-base)"
83
+
84
+ const visibleBlocks = createMemo(() => {
85
+ const counts = blockCounts()
86
+ const blocks = [
87
+ ...Array(counts.added).fill(ADD_COLOR),
88
+ ...Array(counts.deleted).fill(DELETE_COLOR),
89
+ ...Array(counts.neutral).fill(NEUTRAL_COLOR),
90
+ ]
91
+ return blocks.slice(0, 5)
92
+ })
93
+
94
+ return (
95
+ <Show when={variant() === "default" ? total() > 0 : true}>
96
+ <div data-component="diff-changes" data-variant={variant()} classList={{ [props.class ?? ""]: true }}>
97
+ <Switch>
98
+ <Match when={variant() === "bars"}>
99
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 14" fill="none">
100
+ <g>
101
+ <For each={visibleBlocks()}>
102
+ {(color, i) => <rect x={i() * 4} width="2" height="14" rx="1" fill={color} />}
103
+ </For>
104
+ </g>
105
+ </svg>
106
+ </Match>
107
+ <Match when={variant() === "default"}>
108
+ <span data-slot="diff-changes-additions">{`+${additions()}`}</span>
109
+ <span data-slot="diff-changes-deletions">{`-${deletions()}`}</span>
110
+ </Match>
111
+ </Switch>
112
+ </div>
113
+ </Show>
114
+ )
115
+ }
@@ -0,0 +1,23 @@
1
+ [data-dock-surface="shell"] {
2
+ background-color: var(--surface-raised-stronger-non-alpha);
3
+ box-shadow: var(--shadow-xs-border);
4
+ position: relative;
5
+ z-index: 10;
6
+ border-radius: 12px;
7
+ overflow: clip;
8
+ }
9
+
10
+ [data-dock-surface="tray"] {
11
+ background-color: var(--background-base);
12
+ border: 1px solid var(--border-weak-base);
13
+ position: relative;
14
+ z-index: 0;
15
+ border-radius: 12px;
16
+ overflow: clip;
17
+ }
18
+
19
+ [data-dock-surface="tray"][data-dock-attach="top"] {
20
+ margin-top: -0.875rem;
21
+ border-top-left-radius: 0;
22
+ border-top-right-radius: 0;
23
+ }
@@ -0,0 +1,54 @@
1
+ import { type ComponentProps, splitProps } from "solid-js"
2
+
3
+ export interface DockTrayProps extends ComponentProps<"div"> {
4
+ attach?: "none" | "top"
5
+ }
6
+
7
+ export function DockShell(props: ComponentProps<"div">) {
8
+ const [split, rest] = splitProps(props, ["children", "class", "classList"])
9
+ return (
10
+ <div
11
+ {...rest}
12
+ data-dock-surface="shell"
13
+ classList={{
14
+ ...split.classList,
15
+ [split.class ?? ""]: !!split.class,
16
+ }}
17
+ >
18
+ {split.children}
19
+ </div>
20
+ )
21
+ }
22
+
23
+ export function DockShellForm(props: ComponentProps<"form">) {
24
+ const [split, rest] = splitProps(props, ["children", "class", "classList"])
25
+ return (
26
+ <form
27
+ {...rest}
28
+ data-dock-surface="shell"
29
+ classList={{
30
+ ...split.classList,
31
+ [split.class ?? ""]: !!split.class,
32
+ }}
33
+ >
34
+ {split.children}
35
+ </form>
36
+ )
37
+ }
38
+
39
+ export function DockTray(props: DockTrayProps) {
40
+ const [split, rest] = splitProps(props, ["attach", "children", "class", "classList"])
41
+ return (
42
+ <div
43
+ {...rest}
44
+ data-dock-surface="tray"
45
+ data-dock-attach={split.attach || "none"}
46
+ classList={{
47
+ ...split.classList,
48
+ [split.class ?? ""]: !!split.class,
49
+ }}
50
+ >
51
+ {split.children}
52
+ </div>
53
+ )
54
+ }
@@ -0,0 +1,135 @@
1
+ [data-component="dropdown-menu-content"],
2
+ [data-component="dropdown-menu-sub-content"] {
3
+ min-width: 8rem;
4
+ overflow: hidden;
5
+ border-radius: var(--radius-md);
6
+ border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent);
7
+ background-clip: padding-box;
8
+ background-color: var(--surface-raised-stronger-non-alpha);
9
+ padding: 4px;
10
+ box-shadow: var(--shadow-md);
11
+ z-index: 50;
12
+ transform-origin: var(--kb-menu-content-transform-origin);
13
+
14
+ &:focus,
15
+ &:focus-visible {
16
+ outline: none;
17
+ }
18
+
19
+ &[data-closed] {
20
+ animation: dropdown-menu-close 0.15s ease-out;
21
+ }
22
+
23
+ &[data-expanded] {
24
+ animation: dropdown-menu-open 0.15s ease-out;
25
+ }
26
+ }
27
+
28
+ [data-component="dropdown-menu-content"],
29
+ [data-component="dropdown-menu-sub-content"] {
30
+ [data-slot="dropdown-menu-item"],
31
+ [data-slot="dropdown-menu-checkbox-item"],
32
+ [data-slot="dropdown-menu-radio-item"],
33
+ [data-slot="dropdown-menu-sub-trigger"] {
34
+ position: relative;
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 8px;
38
+ padding: 4px 8px;
39
+ border-radius: var(--radius-sm);
40
+ cursor: default;
41
+ user-select: none;
42
+ outline: none;
43
+
44
+ font-family: var(--font-family-sans);
45
+ font-size: var(--font-size-small);
46
+ font-weight: var(--font-weight-medium);
47
+ line-height: var(--line-height-large);
48
+ letter-spacing: var(--letter-spacing-normal);
49
+ color: var(--text-strong);
50
+
51
+ &[data-highlighted] {
52
+ background: var(--surface-raised-base-hover);
53
+ }
54
+
55
+ &[data-disabled] {
56
+ color: var(--text-weak);
57
+ pointer-events: none;
58
+ }
59
+ }
60
+
61
+ [data-slot="dropdown-menu-checkbox-item"],
62
+ [data-slot="dropdown-menu-radio-item"] {
63
+ padding-right: 28px;
64
+ }
65
+
66
+ [data-slot="dropdown-menu-sub-trigger"] {
67
+ &[data-expanded] {
68
+ background: var(--surface-raised-base-hover);
69
+ }
70
+ }
71
+
72
+ [data-slot="dropdown-menu-item-indicator"] {
73
+ display: flex;
74
+ align-items: center;
75
+ justify-content: center;
76
+ width: 16px;
77
+ height: 16px;
78
+ position: absolute;
79
+ right: 8px;
80
+ top: 50%;
81
+ transform: translateY(-50%);
82
+ }
83
+
84
+ [data-slot="dropdown-menu-item-label"] {
85
+ flex: 1;
86
+ }
87
+
88
+ [data-slot="dropdown-menu-item-description"] {
89
+ font-size: var(--font-size-x-small);
90
+ color: var(--text-weak);
91
+ }
92
+
93
+ [data-slot="dropdown-menu-separator"] {
94
+ height: 1px;
95
+ margin: 4px -4px;
96
+ border-top-color: var(--border-weak-base);
97
+ }
98
+
99
+ [data-slot="dropdown-menu-group-label"] {
100
+ display: block;
101
+ padding: 4px 8px;
102
+ font-family: var(--font-family-sans);
103
+ font-size: var(--font-size-x-small);
104
+ font-weight: var(--font-weight-medium);
105
+ line-height: var(--line-height-large);
106
+ letter-spacing: var(--letter-spacing-normal);
107
+ color: var(--text-weak);
108
+ }
109
+
110
+ [data-slot="dropdown-menu-arrow"] {
111
+ fill: var(--surface-raised-stronger-non-alpha);
112
+ }
113
+ }
114
+
115
+ @keyframes dropdown-menu-open {
116
+ from {
117
+ opacity: 0;
118
+ transform: scale(0.96);
119
+ }
120
+ to {
121
+ opacity: 1;
122
+ transform: scale(1);
123
+ }
124
+ }
125
+
126
+ @keyframes dropdown-menu-close {
127
+ from {
128
+ opacity: 1;
129
+ transform: scale(1);
130
+ }
131
+ to {
132
+ opacity: 0;
133
+ transform: scale(0.96);
134
+ }
135
+ }
@@ -0,0 +1,308 @@
1
+ import { DropdownMenu as Kobalte } from "@kobalte/core/dropdown-menu"
2
+ import { splitProps } from "solid-js"
3
+ import type { ComponentProps, ParentProps } from "solid-js"
4
+
5
+ export interface DropdownMenuProps extends ComponentProps<typeof Kobalte> {}
6
+ export interface DropdownMenuTriggerProps extends ComponentProps<typeof Kobalte.Trigger> {}
7
+ export interface DropdownMenuIconProps extends ComponentProps<typeof Kobalte.Icon> {}
8
+ export interface DropdownMenuPortalProps extends ComponentProps<typeof Kobalte.Portal> {}
9
+ export interface DropdownMenuContentProps extends ComponentProps<typeof Kobalte.Content> {}
10
+ export interface DropdownMenuArrowProps extends ComponentProps<typeof Kobalte.Arrow> {}
11
+ export interface DropdownMenuSeparatorProps extends ComponentProps<typeof Kobalte.Separator> {}
12
+ export interface DropdownMenuGroupProps extends ComponentProps<typeof Kobalte.Group> {}
13
+ export interface DropdownMenuGroupLabelProps extends ComponentProps<typeof Kobalte.GroupLabel> {}
14
+ export interface DropdownMenuItemProps extends ComponentProps<typeof Kobalte.Item> {}
15
+ export interface DropdownMenuItemLabelProps extends ComponentProps<typeof Kobalte.ItemLabel> {}
16
+ export interface DropdownMenuItemDescriptionProps extends ComponentProps<typeof Kobalte.ItemDescription> {}
17
+ export interface DropdownMenuItemIndicatorProps extends ComponentProps<typeof Kobalte.ItemIndicator> {}
18
+ export interface DropdownMenuRadioGroupProps extends ComponentProps<typeof Kobalte.RadioGroup> {}
19
+ export interface DropdownMenuRadioItemProps extends ComponentProps<typeof Kobalte.RadioItem> {}
20
+ export interface DropdownMenuCheckboxItemProps extends ComponentProps<typeof Kobalte.CheckboxItem> {}
21
+ export interface DropdownMenuSubProps extends ComponentProps<typeof Kobalte.Sub> {}
22
+ export interface DropdownMenuSubTriggerProps extends ComponentProps<typeof Kobalte.SubTrigger> {}
23
+ export interface DropdownMenuSubContentProps extends ComponentProps<typeof Kobalte.SubContent> {}
24
+
25
+ function DropdownMenuRoot(props: DropdownMenuProps) {
26
+ return <Kobalte {...props} data-component="dropdown-menu" />
27
+ }
28
+
29
+ function DropdownMenuTrigger(props: ParentProps<DropdownMenuTriggerProps>) {
30
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
31
+ return (
32
+ <Kobalte.Trigger
33
+ {...rest}
34
+ data-slot="dropdown-menu-trigger"
35
+ classList={{
36
+ ...local.classList,
37
+ [local.class ?? ""]: !!local.class,
38
+ }}
39
+ >
40
+ {local.children}
41
+ </Kobalte.Trigger>
42
+ )
43
+ }
44
+
45
+ function DropdownMenuIcon(props: ParentProps<DropdownMenuIconProps>) {
46
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
47
+ return (
48
+ <Kobalte.Icon
49
+ {...rest}
50
+ data-slot="dropdown-menu-icon"
51
+ classList={{
52
+ ...local.classList,
53
+ [local.class ?? ""]: !!local.class,
54
+ }}
55
+ >
56
+ {local.children}
57
+ </Kobalte.Icon>
58
+ )
59
+ }
60
+
61
+ function DropdownMenuPortal(props: DropdownMenuPortalProps) {
62
+ return <Kobalte.Portal {...props} />
63
+ }
64
+
65
+ function DropdownMenuContent(props: ParentProps<DropdownMenuContentProps>) {
66
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
67
+ return (
68
+ <Kobalte.Content
69
+ {...rest}
70
+ data-component="dropdown-menu-content"
71
+ classList={{
72
+ ...local.classList,
73
+ [local.class ?? ""]: !!local.class,
74
+ }}
75
+ >
76
+ {local.children}
77
+ </Kobalte.Content>
78
+ )
79
+ }
80
+
81
+ function DropdownMenuArrow(props: DropdownMenuArrowProps) {
82
+ const [local, rest] = splitProps(props, ["class", "classList"])
83
+ return (
84
+ <Kobalte.Arrow
85
+ {...rest}
86
+ data-slot="dropdown-menu-arrow"
87
+ classList={{
88
+ ...local.classList,
89
+ [local.class ?? ""]: !!local.class,
90
+ }}
91
+ />
92
+ )
93
+ }
94
+
95
+ function DropdownMenuSeparator(props: DropdownMenuSeparatorProps) {
96
+ const [local, rest] = splitProps(props, ["class", "classList"])
97
+ return (
98
+ <Kobalte.Separator
99
+ {...rest}
100
+ data-slot="dropdown-menu-separator"
101
+ classList={{
102
+ ...local.classList,
103
+ [local.class ?? ""]: !!local.class,
104
+ }}
105
+ />
106
+ )
107
+ }
108
+
109
+ function DropdownMenuGroup(props: ParentProps<DropdownMenuGroupProps>) {
110
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
111
+ return (
112
+ <Kobalte.Group
113
+ {...rest}
114
+ data-slot="dropdown-menu-group"
115
+ classList={{
116
+ ...local.classList,
117
+ [local.class ?? ""]: !!local.class,
118
+ }}
119
+ >
120
+ {local.children}
121
+ </Kobalte.Group>
122
+ )
123
+ }
124
+
125
+ function DropdownMenuGroupLabel(props: ParentProps<DropdownMenuGroupLabelProps>) {
126
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
127
+ return (
128
+ <Kobalte.GroupLabel
129
+ {...rest}
130
+ data-slot="dropdown-menu-group-label"
131
+ classList={{
132
+ ...local.classList,
133
+ [local.class ?? ""]: !!local.class,
134
+ }}
135
+ >
136
+ {local.children}
137
+ </Kobalte.GroupLabel>
138
+ )
139
+ }
140
+
141
+ function DropdownMenuItem(props: ParentProps<DropdownMenuItemProps>) {
142
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
143
+ return (
144
+ <Kobalte.Item
145
+ {...rest}
146
+ data-slot="dropdown-menu-item"
147
+ classList={{
148
+ ...local.classList,
149
+ [local.class ?? ""]: !!local.class,
150
+ }}
151
+ >
152
+ {local.children}
153
+ </Kobalte.Item>
154
+ )
155
+ }
156
+
157
+ function DropdownMenuItemLabel(props: ParentProps<DropdownMenuItemLabelProps>) {
158
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
159
+ return (
160
+ <Kobalte.ItemLabel
161
+ {...rest}
162
+ data-slot="dropdown-menu-item-label"
163
+ classList={{
164
+ ...local.classList,
165
+ [local.class ?? ""]: !!local.class,
166
+ }}
167
+ >
168
+ {local.children}
169
+ </Kobalte.ItemLabel>
170
+ )
171
+ }
172
+
173
+ function DropdownMenuItemDescription(props: ParentProps<DropdownMenuItemDescriptionProps>) {
174
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
175
+ return (
176
+ <Kobalte.ItemDescription
177
+ {...rest}
178
+ data-slot="dropdown-menu-item-description"
179
+ classList={{
180
+ ...local.classList,
181
+ [local.class ?? ""]: !!local.class,
182
+ }}
183
+ >
184
+ {local.children}
185
+ </Kobalte.ItemDescription>
186
+ )
187
+ }
188
+
189
+ function DropdownMenuItemIndicator(props: ParentProps<DropdownMenuItemIndicatorProps>) {
190
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
191
+ return (
192
+ <Kobalte.ItemIndicator
193
+ {...rest}
194
+ data-slot="dropdown-menu-item-indicator"
195
+ classList={{
196
+ ...local.classList,
197
+ [local.class ?? ""]: !!local.class,
198
+ }}
199
+ >
200
+ {local.children}
201
+ </Kobalte.ItemIndicator>
202
+ )
203
+ }
204
+
205
+ function DropdownMenuRadioGroup(props: ParentProps<DropdownMenuRadioGroupProps>) {
206
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
207
+ return (
208
+ <Kobalte.RadioGroup
209
+ {...rest}
210
+ data-slot="dropdown-menu-radio-group"
211
+ classList={{
212
+ ...local.classList,
213
+ [local.class ?? ""]: !!local.class,
214
+ }}
215
+ >
216
+ {local.children}
217
+ </Kobalte.RadioGroup>
218
+ )
219
+ }
220
+
221
+ function DropdownMenuRadioItem(props: ParentProps<DropdownMenuRadioItemProps>) {
222
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
223
+ return (
224
+ <Kobalte.RadioItem
225
+ {...rest}
226
+ data-slot="dropdown-menu-radio-item"
227
+ classList={{
228
+ ...local.classList,
229
+ [local.class ?? ""]: !!local.class,
230
+ }}
231
+ >
232
+ {local.children}
233
+ </Kobalte.RadioItem>
234
+ )
235
+ }
236
+
237
+ function DropdownMenuCheckboxItem(props: ParentProps<DropdownMenuCheckboxItemProps>) {
238
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
239
+ return (
240
+ <Kobalte.CheckboxItem
241
+ {...rest}
242
+ data-slot="dropdown-menu-checkbox-item"
243
+ classList={{
244
+ ...local.classList,
245
+ [local.class ?? ""]: !!local.class,
246
+ }}
247
+ >
248
+ {local.children}
249
+ </Kobalte.CheckboxItem>
250
+ )
251
+ }
252
+
253
+ function DropdownMenuSub(props: DropdownMenuSubProps) {
254
+ return <Kobalte.Sub {...props} />
255
+ }
256
+
257
+ function DropdownMenuSubTrigger(props: ParentProps<DropdownMenuSubTriggerProps>) {
258
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
259
+ return (
260
+ <Kobalte.SubTrigger
261
+ {...rest}
262
+ data-slot="dropdown-menu-sub-trigger"
263
+ classList={{
264
+ ...local.classList,
265
+ [local.class ?? ""]: !!local.class,
266
+ }}
267
+ >
268
+ {local.children}
269
+ </Kobalte.SubTrigger>
270
+ )
271
+ }
272
+
273
+ function DropdownMenuSubContent(props: ParentProps<DropdownMenuSubContentProps>) {
274
+ const [local, rest] = splitProps(props, ["class", "classList", "children"])
275
+ return (
276
+ <Kobalte.SubContent
277
+ {...rest}
278
+ data-component="dropdown-menu-sub-content"
279
+ classList={{
280
+ ...local.classList,
281
+ [local.class ?? ""]: !!local.class,
282
+ }}
283
+ >
284
+ {local.children}
285
+ </Kobalte.SubContent>
286
+ )
287
+ }
288
+
289
+ export const DropdownMenu = Object.assign(DropdownMenuRoot, {
290
+ Trigger: DropdownMenuTrigger,
291
+ Icon: DropdownMenuIcon,
292
+ Portal: DropdownMenuPortal,
293
+ Content: DropdownMenuContent,
294
+ Arrow: DropdownMenuArrow,
295
+ Separator: DropdownMenuSeparator,
296
+ Group: DropdownMenuGroup,
297
+ GroupLabel: DropdownMenuGroupLabel,
298
+ Item: DropdownMenuItem,
299
+ ItemLabel: DropdownMenuItemLabel,
300
+ ItemDescription: DropdownMenuItemDescription,
301
+ ItemIndicator: DropdownMenuItemIndicator,
302
+ RadioGroup: DropdownMenuRadioGroup,
303
+ RadioItem: DropdownMenuRadioItem,
304
+ CheckboxItem: DropdownMenuCheckboxItem,
305
+ Sub: DropdownMenuSub,
306
+ SubTrigger: DropdownMenuSubTrigger,
307
+ SubContent: DropdownMenuSubContent,
308
+ })
@@ -0,0 +1,13 @@
1
+ import { Link, Meta } from "@solidjs/meta"
2
+
3
+ export const Favicon = () => {
4
+ return (
5
+ <>
6
+ <Link rel="icon" type="image/png" href="/favicon-96x96-v3.png" sizes="96x96" />
7
+ <Link rel="shortcut icon" href="/favicon-v3.ico" />
8
+ <Link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-v3.png" />
9
+ <Link rel="manifest" href="/site.webmanifest" />
10
+ <Meta name="apple-mobile-web-app-title" content="OpenCode" />
11
+ </>
12
+ )
13
+ }
@@ -0,0 +1,26 @@
1
+ [data-component="file-icon"] {
2
+ display: block;
3
+ flex-shrink: 0;
4
+ width: 16px;
5
+ height: 16px;
6
+ }
7
+
8
+ /*
9
+ File tree: show monochrome weak icons by default.
10
+ On hover, show the original file-type colors.
11
+ */
12
+ [data-component="filetree"] .filetree-icon--mono {
13
+ color: var(--icon-base);
14
+ }
15
+
16
+ [data-component="filetree"] .filetree-iconpair {
17
+ position: relative;
18
+ display: inline-flex;
19
+ width: 16px;
20
+ height: 16px;
21
+ }
22
+
23
+ [data-component="filetree"] .filetree-iconpair [data-component="file-icon"] {
24
+ position: absolute;
25
+ inset: 0;
26
+ }